From 14a58439e5a6e153ced0113370d11078ca504fdf Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 18 Jul 2022 16:24:47 +0200 Subject: [PATCH 1/6] SHA3 in interpreter --- evm/src/cpu/kernel/interpreter.rs | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 81ce287b..1839aaf2 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -1,4 +1,5 @@ -use ethereum_types::{U256, U512}; +use ethereum_types::{BigEndianHash, U256, U512}; +use keccak_hash::keccak; /// Halt interpreter execution whenever a jump to this offset is done. const HALT_OFFSET: usize = 0xdeadbeef; @@ -25,6 +26,11 @@ impl EvmMemory { U256::from_big_endian(&self.memory[offset..offset + 32]) } + fn mload8(&mut self, offset: usize) -> u8 { + self.expand(offset + 1); + self.memory[offset] + } + fn mstore(&mut self, offset: usize, value: U256) { self.expand(offset + 32); let value_be = { @@ -119,7 +125,7 @@ impl<'a> Interpreter<'a> { 0x1b => todo!(), // "SHL", 0x1c => todo!(), // "SHR", 0x1d => todo!(), // "SAR", - 0x20 => todo!(), // "KECCAK256", + 0x20 => self.run_sha3(), // "SHA3", 0x30 => todo!(), // "ADDRESS", 0x31 => todo!(), // "BALANCE", 0x32 => todo!(), // "ORIGIN", @@ -286,6 +292,16 @@ impl<'a> Interpreter<'a> { self.push(!x); } + fn run_sha3(&mut self) { + let offset = self.pop().as_usize(); + let size = self.pop().as_usize(); + let bytes = (offset..offset + size) + .map(|i| self.memory.mload8(i)) + .collect::>(); + let hash = keccak(bytes); + self.push(hash.into_uint()); + } + fn run_pop(&mut self) { self.pop(); } From 15ee8917784c75a07fbf89337c46c9228ab5c05e Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 18 Jul 2022 16:36:37 +0200 Subject: [PATCH 2/6] SHA3 in asm --- evm/src/cpu/kernel/asm/ecrecover.asm | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/evm/src/cpu/kernel/asm/ecrecover.asm b/evm/src/cpu/kernel/asm/ecrecover.asm index d0994054..2c71d317 100644 --- a/evm/src/cpu/kernel/asm/ecrecover.asm +++ b/evm/src/cpu/kernel/asm/ecrecover.asm @@ -133,7 +133,27 @@ ecrecover_with_first_point: // TODO final_hashing: JUMPDEST - PUSH 0xdeadbeef + // stack: PKx, PKy, retdest + PUSH 0 + // stack: 0, PKx, PKy, retdest + MSTORE + // stack: PKy, retdest + PUSH 0x20 + // stack: 0x20, PKy, retdest + MSTORE + // stack: retdest + PUSH 0x40 + // stack: 0x40, retdest + PUSH 0 + // stack: 0, 0x40, retdest + SHA3 + // stack: hash, retdest + PUSH 0xffffffffffffffffffffffffffffffffffffffff + // stack: 2^160-1, hash, retdest + AND + // stack: address, retdest + SWAP1 + // stack: retdest, address JUMP // Check if v, r, and s are in correct form. From f9ec4e8e7d0f78865ecd0d206fd070c391b2a8c4 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 18 Jul 2022 16:41:17 +0200 Subject: [PATCH 3/6] Modify ecrecover tests --- evm/src/cpu/kernel/opcodes.rs | 1 + evm/src/cpu/kernel/tests/ecrecover.rs | 16 ++++------------ 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/evm/src/cpu/kernel/opcodes.rs b/evm/src/cpu/kernel/opcodes.rs index b8633178..6ca359b7 100644 --- a/evm/src/cpu/kernel/opcodes.rs +++ b/evm/src/cpu/kernel/opcodes.rs @@ -35,6 +35,7 @@ pub(crate) fn get_opcode(mnemonic: &str) -> u8 { "SHR" => 0x1c, "SAR" => 0x1d, "KECCAK256" => 0x20, + "SHA3" => 0x20, "ADDRESS" => 0x30, "BALANCE" => 0x31, "ORIGIN" => 0x32, diff --git a/evm/src/cpu/kernel/tests/ecrecover.rs b/evm/src/cpu/kernel/tests/ecrecover.rs index 5077d042..80257222 100644 --- a/evm/src/cpu/kernel/tests/ecrecover.rs +++ b/evm/src/cpu/kernel/tests/ecrecover.rs @@ -1,20 +1,13 @@ +use std::str::FromStr; + use anyhow::Result; use ethereum_types::U256; -use keccak_hash::keccak; use crate::cpu::kernel::aggregator::combined_kernel; use crate::cpu::kernel::assembler::Kernel; use crate::cpu::kernel::interpreter::run; use crate::cpu::kernel::tests::u256ify; -fn pubkey_to_addr(x: U256, y: U256) -> Vec { - let mut buf = [0; 64]; - x.to_big_endian(&mut buf[0..32]); - y.to_big_endian(&mut buf[32..64]); - let hash = keccak(buf); - hash.0[12..].to_vec() -} - fn test_valid_ecrecover( hash: &str, v: &str, @@ -24,10 +17,9 @@ fn test_valid_ecrecover( kernel: &Kernel, ) -> Result<()> { let ecrecover = kernel.global_labels["ecrecover"]; - let initial_stack = u256ify([s, r, v, hash])?; + let initial_stack = u256ify(["0xdeadbeef", s, r, v, hash])?; let stack = run(&kernel.code, ecrecover, initial_stack).stack; - let got = pubkey_to_addr(stack[1], stack[0]); - assert_eq!(got, hex::decode(&expected[2..]).unwrap()); + assert_eq!(stack[0], U256::from_str(expected).unwrap()); Ok(()) } From ea0d081fa86cd5c030ad5523af544be47636cfda Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 18 Jul 2022 16:53:26 +0200 Subject: [PATCH 4/6] Fix comment --- evm/src/cpu/kernel/asm/ecrecover.asm | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/evm/src/cpu/kernel/asm/ecrecover.asm b/evm/src/cpu/kernel/asm/ecrecover.asm index 2c71d317..95efd914 100644 --- a/evm/src/cpu/kernel/asm/ecrecover.asm +++ b/evm/src/cpu/kernel/asm/ecrecover.asm @@ -107,31 +107,31 @@ ecrecover_with_first_point: // stack: u2, Y, X, retdest // Compute u2 * GENERATOR and chain the call to `ec_mul` with a call to `ec_add` to compute PUBKEY = (X,Y) + u2 * GENERATOR, - // and a call to `final_hashing` to get the final result `SHA3(PUBKEY)[-20:]`. - PUSH final_hashing - // stack: final_hashing, u2, Y, X, retdest + // and a call to `pubkey_to_addr` to get the final result `SHA3(PUBKEY)[-20:]`. + PUSH pubkey_to_addr + // stack: pubkey_to_addr, u2, Y, X, retdest SWAP3 - // stack: X, u2, Y, final_hashing, retdest + // stack: X, u2, Y, pubkey_to_addr, retdest PUSH ec_add_valid_points_secp - // stack: ec_add_valid_points_secp, X, u2, Y, final_hashing, retdest + // stack: ec_add_valid_points_secp, X, u2, Y, pubkey_to_addr, retdest SWAP1 - // stack: X, ec_add_valid_points_secp, u2, Y, final_hashing, retdest + // stack: X, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest PUSH 0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798 // x-coordinate of generator - // stack: Gx, X, ec_add_valid_points_secp, u2, Y, final_hashing, retdest + // stack: Gx, X, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest SWAP1 - // stack: X, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest + // stack: X, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest PUSH 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8 // y-coordinate of generator - // stack: Gy, X, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest + // stack: Gy, X, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest SWAP1 - // stack: X, Gy, Gx, ec_add_valid_points_secp, u2, Y, final_hashing, retdest + // stack: X, Gy, Gx, ec_add_valid_points_secp, u2, Y, pubkey_to_addr, retdest SWAP4 - // stack: u2, Gy, Gx, ec_add_valid_points_secp, X, Y, final_hashing, retdest + // stack: u2, Gy, Gx, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest SWAP2 - // stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, final_hashing, retdest + // stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest %jump(ec_mul_valid_point_secp) -// TODO -final_hashing: +// Take a public key (PKx, PKy) and return the associated address SHA3(PKx || PKy)[-20:]. +pubkey_to_addr: JUMPDEST // stack: PKx, PKy, retdest PUSH 0 From e7dbba8d7ba08a3941d491120a60c627e33659d7 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 19 Jul 2022 15:21:44 +0200 Subject: [PATCH 5/6] s/sha3/keccak256 --- evm/src/cpu/columns.rs | 2 +- evm/src/cpu/decode.rs | 2 +- evm/src/cpu/kernel/asm/ecrecover.asm | 8 ++++---- evm/src/cpu/kernel/interpreter.rs | 4 ++-- evm/src/cpu/kernel/opcodes.rs | 1 - 5 files changed, 8 insertions(+), 9 deletions(-) diff --git a/evm/src/cpu/columns.rs b/evm/src/cpu/columns.rs index f3a400c6..2f4fe7de 100644 --- a/evm/src/cpu/columns.rs +++ b/evm/src/cpu/columns.rs @@ -52,7 +52,7 @@ pub struct CpuColumnsView { pub is_shl: T, pub is_shr: T, pub is_sar: T, - pub is_sha3: T, + pub is_keccak256: T, pub is_address: T, pub is_balance: T, pub is_origin: T, diff --git a/evm/src/cpu/decode.rs b/evm/src/cpu/decode.rs index 0b091558..dce88b3e 100644 --- a/evm/src/cpu/decode.rs +++ b/evm/src/cpu/decode.rs @@ -45,7 +45,7 @@ const OPCODES: [(u64, usize, usize); 102] = [ (0x1c, 0, COL_MAP.is_shr), (0x1d, 0, COL_MAP.is_sar), (0x1e, 1, COL_MAP.is_invalid_1), // 0x1e-0x1f - (0x20, 0, COL_MAP.is_sha3), + (0x20, 0, COL_MAP.is_keccak256), (0x21, 0, COL_MAP.is_invalid_2), (0x22, 1, COL_MAP.is_invalid_3), // 0x22-0x23 (0x24, 2, COL_MAP.is_invalid_4), // 0x24-0x27 diff --git a/evm/src/cpu/kernel/asm/ecrecover.asm b/evm/src/cpu/kernel/asm/ecrecover.asm index 95efd914..538a86dc 100644 --- a/evm/src/cpu/kernel/asm/ecrecover.asm +++ b/evm/src/cpu/kernel/asm/ecrecover.asm @@ -107,7 +107,7 @@ ecrecover_with_first_point: // stack: u2, Y, X, retdest // Compute u2 * GENERATOR and chain the call to `ec_mul` with a call to `ec_add` to compute PUBKEY = (X,Y) + u2 * GENERATOR, - // and a call to `pubkey_to_addr` to get the final result `SHA3(PUBKEY)[-20:]`. + // and a call to `pubkey_to_addr` to get the final result `KECCAK256(PUBKEY)[-20:]`. PUSH pubkey_to_addr // stack: pubkey_to_addr, u2, Y, X, retdest SWAP3 @@ -130,13 +130,13 @@ ecrecover_with_first_point: // stack: Gx, Gy, u2, ec_add_valid_points_secp, X, Y, pubkey_to_addr, retdest %jump(ec_mul_valid_point_secp) -// Take a public key (PKx, PKy) and return the associated address SHA3(PKx || PKy)[-20:]. +// Take a public key (PKx, PKy) and return the associated address KECCAK256(PKx || PKy)[-20:]. pubkey_to_addr: JUMPDEST // stack: PKx, PKy, retdest PUSH 0 // stack: 0, PKx, PKy, retdest - MSTORE + MSTORE // TODO: switch to kernel memory (like `%mstore_current(@SEGMENT_KERNEL_GENERAL)`). // stack: PKy, retdest PUSH 0x20 // stack: 0x20, PKy, retdest @@ -146,7 +146,7 @@ pubkey_to_addr: // stack: 0x40, retdest PUSH 0 // stack: 0, 0x40, retdest - SHA3 + KECCAK256 // stack: hash, retdest PUSH 0xffffffffffffffffffffffffffffffffffffffff // stack: 2^160-1, hash, retdest diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 1839aaf2..cc5b870d 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -125,7 +125,7 @@ impl<'a> Interpreter<'a> { 0x1b => todo!(), // "SHL", 0x1c => todo!(), // "SHR", 0x1d => todo!(), // "SAR", - 0x20 => self.run_sha3(), // "SHA3", + 0x20 => self.run_keccak256(), // "KECCAK256", 0x30 => todo!(), // "ADDRESS", 0x31 => todo!(), // "BALANCE", 0x32 => todo!(), // "ORIGIN", @@ -292,7 +292,7 @@ impl<'a> Interpreter<'a> { self.push(!x); } - fn run_sha3(&mut self) { + fn run_keccak256(&mut self) { let offset = self.pop().as_usize(); let size = self.pop().as_usize(); let bytes = (offset..offset + size) diff --git a/evm/src/cpu/kernel/opcodes.rs b/evm/src/cpu/kernel/opcodes.rs index 6ca359b7..b8633178 100644 --- a/evm/src/cpu/kernel/opcodes.rs +++ b/evm/src/cpu/kernel/opcodes.rs @@ -35,7 +35,6 @@ pub(crate) fn get_opcode(mnemonic: &str) -> u8 { "SHR" => 0x1c, "SAR" => 0x1d, "KECCAK256" => 0x20, - "SHA3" => 0x20, "ADDRESS" => 0x30, "BALANCE" => 0x31, "ORIGIN" => 0x32, From a8ce2a60730e0244ef21c0d68f9216f57acde1c0 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Tue, 19 Jul 2022 15:27:51 +0200 Subject: [PATCH 6/6] Import fix --- evm/src/cpu/kernel/interpreter.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 3ee95e22..7c59fe66 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -1,6 +1,5 @@ use anyhow::bail; use ethereum_types::{BigEndianHash, U256, U512}; -use ethereum_types::{U256, U512}; use keccak_hash::keccak; /// Halt interpreter execution whenever a jump to this offset is done.