From 6b4cce21d89c8cf5154c9d940176ad999d60a4be Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 21 Oct 2022 18:00:41 +0200 Subject: [PATCH 01/12] Start --- evm/src/cpu/kernel/asm/account_code.asm | 93 ++++++++++++++++++++ evm/src/cpu/kernel/asm/util/basic_macros.asm | 18 ++-- evm/src/generation/prover_input.rs | 23 ++++- evm/src/memory/segments.rs | 19 ++-- 4 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 evm/src/cpu/kernel/asm/account_code.asm diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm new file mode 100644 index 00000000..ef8d5504 --- /dev/null +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -0,0 +1,93 @@ +%extcodehash + // stack: address + %mpt_read_state_trie + // stack: account_ptr + %add_const(3) + // stack: codehash_ptr + %mload_trie_data + // stack: codehash +%endmacro + +%extcodesize + // stack: address + %stack (address) -> (address, %after) + %jump(load_code) +%%after: +%endmacro + +%codesize + ADDRESS + %extcodesize +%endmacro + +global extcodecopy: + // stack: address, dest_offset, offset, size, retdest + %stack (address, dest_offset, offset, size, retdest) -> (address, extcodecopy_contd, size, offset, dest_offset, retdest) + %jump(load_code) +extcodecopy_contd: + // stack: code_length, size, offset, dest_offset, retdest + SWAP1 + // stack: size, code_length, offset, dest_offset, retdest + PUSH 0 +extcodecopy_loop: + // stack: i, size, code_length, offset, dest_offset, retdest + DUP2 DUP2 EQ + // stack: i == size, i, size, code_length, offset, dest_offset, retdest + %jumpi(extcodecopy_end) + %stack: (i, size, code_length, offset, dest_offset, retdest) -> (offset, code_length, offset, code_length, dest_offset, i, size, retdest) + LT + // stack: offset < code_length, offset, code_length, dest_offset, i, size, retdest + DUP2 + // stack: offset, offset < code_length, offset, code_length, dest_offset, i, size, retdest + %mload_current(@SEGMENT_KERNEL_ACCOUNT_CODE) + // stack: opcode, offset < code_length, offset, code_length, dest_offset, i, size, retdest + &stack (opcode, offset < code_length, offset, code_length, dest_offset, i, size, retdest) -> (offset < code_length, 0, opcode, offset, code_length, dest_offset, i, size, retdest) + %select_bool + // stack: opcode, offset, code_length, dest_offset, i, size, retdest + DUP4 + // stack: dest_offset, opcode, offset, code_length, dest_offset, i, size, retdest + + +extcodecopy_end: + %stack: (i, size, code_length, offset, dest_offset, size, retdest) -> (retdest) + JUMP + + +load_code: + // stack: address, retdest + %extcodehash + // stack: codehash, retdest + PROVER_INPUT(account_code::length) + // stack: code_length, codehash, retdest + PUSH 0 +load_code_loop: + // stack: i, code_length, codehash, retdest + DUP2 DUP2 EQ + // stack: i == code_length, i, code_length, codehash, retdest + %jumpi(load_code_check) + PROVER_INPUT(account_code::get) + // stack: opcode, i, code_length, codehash, retdest + DUP2 + // stack: i, opcode, i, code_length, codehash, retdest + %mstore_current(@SEGMENT_KERNEL_ACCOUNT_CODE) + // stack: i, code_length, codehash, retdest + %increment + // stack: i+1, code_length, codehash, retdest + %jump(load_code_loop) + +load_code_check: + // stack: i, code_length, codehash, retdest + POP + // stack: code_length, codehash, retdest + %stack (code_length, codehash, retdest) -> (code_length, codehash, retdest, code_length) + PUSH 0 + // stack: 0, code_length, codehash, retdest, code_length + PUSH @SEGMENT_KERNEL_ACCOUNT_CODE + // stack: segment, 0, code_length, codehash, retdest, code_length + GET_CONTEXT + // stack: context, segment, 0, code_length, codehash, retdest, code_length + KECCAK_GENERAL + // stack: shouldbecodehash, codehash, retdest, code_length + %assert_eq + JUMP + diff --git a/evm/src/cpu/kernel/asm/util/basic_macros.asm b/evm/src/cpu/kernel/asm/util/basic_macros.asm index 02a2c807..6ec13835 100644 --- a/evm/src/cpu/kernel/asm/util/basic_macros.asm +++ b/evm/src/cpu/kernel/asm/util/basic_macros.asm @@ -186,24 +186,24 @@ // stack: (pred != 0) * nz + (pred == 0) * z %endmacro -// If pred, yields z; otherwise, yields nz +// If pred, yields x; otherwise, yields y // Assumes pred is boolean (either 0 or 1). %macro select_bool - // stack: pred, nz, z + // stack: pred, y, x DUP1 - // stack: pred, pred, nz, z + // stack: pred, pred, y, x ISZERO - // stack: notpred, pred, nz, z + // stack: notpred, pred, y, x SWAP3 - // stack: z, pred, nz, notpred + // stack: x, pred, y, notpred MUL - // stack: pred * z, nz, notpred + // stack: pred * x, y, notpred SWAP2 - // stack: notpred, nz, pred * z + // stack: notpred, y, pred * x MUL - // stack: notpred * nz, pred * z + // stack: notpred * y, pred * x ADD - // stack: notpred * nz + pred * z + // stack: notpred * y + pred * x %endmacro %macro square diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index d5d7df7c..82a0c7c3 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use ethereum_types::U256; +use ethereum_types::{BigEndianHash, H256, U256}; use plonky2::field::types::Field; use crate::generation::prover_input::EvmField::{ @@ -28,6 +28,7 @@ impl GenerationState { "ff" => self.run_ff(stack, input_fn), "mpt" => self.run_mpt(), "rlp" => self.run_rlp(), + "account_code" => self.run_account_code(stack, input_fn), _ => panic!("Unrecognized prover input function."), } } @@ -63,6 +64,26 @@ impl GenerationState { .pop() .unwrap_or_else(|| panic!("Out of RLP data")) } + + /// Account code + fn run_account_code(&mut self, stack: &[U256], input_fn: &ProverInputFn) -> U256 { + match input_fn.0[1].as_str() { + "length" => { + let codehash = stack.last().expect("Empty stack"); + self.inputs.contract_code[&H256::from_uint(codehash)] + .len() + .into() + } + "get" => { + let stacklen = stack.len(); + // Stack looks like: i, code_length, codehash + let i = stack[stacklen - 1].as_usize(); + let codehash = stack[stacklen - 3]; + self.inputs.contract_code[&H256::from_uint(&codehash)][i].into() + } + _ => panic!("sup?"), + } + } } enum EvmField { diff --git a/evm/src/memory/segments.rs b/evm/src/memory/segments.rs index b8ba904f..021781ac 100644 --- a/evm/src/memory/segments.rs +++ b/evm/src/memory/segments.rs @@ -20,23 +20,25 @@ pub(crate) enum Segment { KernelGeneral = 7, /// Another segment for general purpose kernel use. KernelGeneral2 = 8, + /// Segment to hold account code for opcodes like `CODESIZE, CODECOPY,...`. + KernelAccountCode = 9, /// Contains normalized transaction fields; see `NormalizedTxnField`. - TxnFields = 9, + TxnFields = 10, /// Contains the data field of a transaction. - TxnData = 10, + TxnData = 11, /// A buffer used to hold raw RLP data. - RlpRaw = 11, + RlpRaw = 12, /// Contains all trie data. Tries are stored as immutable, copy-on-write trees, so this is an /// append-only buffer. It is owned by the kernel, so it only lives on context 0. - TrieData = 12, + TrieData = 13, /// A buffer used to store the encodings of a branch node's children. - TrieEncodedChild = 13, + TrieEncodedChild = 14, /// A buffer used to store the lengths of the encodings of a branch node's children. - TrieEncodedChildLen = 14, + TrieEncodedChildLen = 15, } impl Segment { - pub(crate) const COUNT: usize = 15; + pub(crate) const COUNT: usize = 16; pub(crate) fn all() -> [Self; Self::COUNT] { [ @@ -49,6 +51,7 @@ impl Segment { Self::ContextMetadata, Self::KernelGeneral, Self::KernelGeneral2, + Self::KernelAccountCode, Self::TxnFields, Self::TxnData, Self::RlpRaw, @@ -70,6 +73,7 @@ impl Segment { Segment::ContextMetadata => "SEGMENT_CONTEXT_METADATA", Segment::KernelGeneral => "SEGMENT_KERNEL_GENERAL", Segment::KernelGeneral2 => "SEGMENT_KERNEL_GENERAL_2", + Segment::KernelAccountCode => "SEGMENT_KERNEL_ACCOUNT_CODE", Segment::TxnFields => "SEGMENT_NORMALIZED_TXN", Segment::TxnData => "SEGMENT_TXN_DATA", Segment::RlpRaw => "SEGMENT_RLP_RAW", @@ -91,6 +95,7 @@ impl Segment { Segment::ContextMetadata => 256, Segment::KernelGeneral => 256, Segment::KernelGeneral2 => 256, + Segment::KernelAccountCode => 256, Segment::TxnFields => 256, Segment::TxnData => 256, Segment::RlpRaw => 8, From 560b9b2a97bbfd1644fdef654008c69e2b39e761 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 21 Oct 2022 18:11:27 +0200 Subject: [PATCH 02/12] Finish extcodecopy --- evm/src/cpu/kernel/aggregator.rs | 1 + evm/src/cpu/kernel/asm/account_code.asm | 39 +++++++++++++++++++------ 2 files changed, 31 insertions(+), 9 deletions(-) diff --git a/evm/src/cpu/kernel/aggregator.rs b/evm/src/cpu/kernel/aggregator.rs index 8fe49739..1d20fe0c 100644 --- a/evm/src/cpu/kernel/aggregator.rs +++ b/evm/src/cpu/kernel/aggregator.rs @@ -79,6 +79,7 @@ pub(crate) fn combined_kernel() -> Kernel { include_str!("asm/util/assertions.asm"), include_str!("asm/util/basic_macros.asm"), include_str!("asm/util/keccak.asm"), + include_str!("asm/account_code.asm"), ]; let parsed_files = files.iter().map(|f| parse(f)).collect_vec(); diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index ef8d5504..211363fb 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -1,4 +1,4 @@ -%extcodehash +%macro extcodehash // stack: address %mpt_read_state_trie // stack: account_ptr @@ -8,18 +8,24 @@ // stack: codehash %endmacro -%extcodesize - // stack: address - %stack (address) -> (address, %after) +%macro extcodesize + %stack (address) -> (address, %%after) %jump(load_code) %%after: %endmacro -%codesize +%macro codesize ADDRESS %extcodesize %endmacro +%macro codecopy + // stack: dest_offset, offset, size, retdest + ADDRESS + // stack: address, dest_offset, offset, size, retdest + %jump(extcodecopy) +%endmacro + global extcodecopy: // stack: address, dest_offset, offset, size, retdest %stack (address, dest_offset, offset, size, retdest) -> (address, extcodecopy_contd, size, offset, dest_offset, retdest) @@ -34,22 +40,38 @@ extcodecopy_loop: DUP2 DUP2 EQ // stack: i == size, i, size, code_length, offset, dest_offset, retdest %jumpi(extcodecopy_end) - %stack: (i, size, code_length, offset, dest_offset, retdest) -> (offset, code_length, offset, code_length, dest_offset, i, size, retdest) + %stack (i, size, code_length, offset, dest_offset, retdest) -> (offset, code_length, offset, code_length, dest_offset, i, size, retdest) LT // stack: offset < code_length, offset, code_length, dest_offset, i, size, retdest DUP2 // stack: offset, offset < code_length, offset, code_length, dest_offset, i, size, retdest %mload_current(@SEGMENT_KERNEL_ACCOUNT_CODE) // stack: opcode, offset < code_length, offset, code_length, dest_offset, i, size, retdest - &stack (opcode, offset < code_length, offset, code_length, dest_offset, i, size, retdest) -> (offset < code_length, 0, opcode, offset, code_length, dest_offset, i, size, retdest) + %stack (opcode, offset_lt_code_length, offset, code_length, dest_offset, i, size, retdest) -> (offset_lt_code_length, 0, opcode, offset, code_length, dest_offset, i, size, retdest) %select_bool // stack: opcode, offset, code_length, dest_offset, i, size, retdest DUP4 // stack: dest_offset, opcode, offset, code_length, dest_offset, i, size, retdest + %mstore_main + // stack: offset, code_length, dest_offset, i, size, retdest + %increment + // stack: offset+1, code_length, dest_offset, i, size, retdest + SWAP2 + // stack: dest_offset, code_length, offset+1, i, size, retdest + %increment + // stack: dest_offset+1, code_length, offset+1, i, size, retdest + SWAP3 + // stack: i, code_length, offset+1, dest_offset+1, size, retdest + %increment + // stack: i+1, code_length, offset+1, dest_offset+1, size, retdest + %stack (i, code_length, offset, dest_offset, size, retdest) -> (i, size, code_length, offset, dest_offset, retdest) + %jump(extcodecopy_loop) + + extcodecopy_end: - %stack: (i, size, code_length, offset, dest_offset, size, retdest) -> (retdest) + %stack (i, size, code_length, offset, dest_offset, size, retdest) -> (retdest) JUMP @@ -90,4 +112,3 @@ load_code_check: // stack: shouldbecodehash, codehash, retdest, code_length %assert_eq JUMP - From 0d4cf5be476c32d28755556c743655f29774d2e9 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 24 Oct 2022 13:06:53 +0200 Subject: [PATCH 03/12] Minor --- evm/src/cpu/kernel/asm/account_code.asm | 4 ++ evm/src/cpu/kernel/tests/account_code.rs | 49 ++++++++++++++++++++++++ evm/src/cpu/kernel/tests/mod.rs | 1 + 3 files changed, 54 insertions(+) create mode 100644 evm/src/cpu/kernel/tests/account_code.rs diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 211363fb..4563fa0a 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -14,6 +14,9 @@ %%after: %endmacro +global extcodesize: + %extcodesize + %macro codesize ADDRESS %extcodesize @@ -78,6 +81,7 @@ extcodecopy_end: load_code: // stack: address, retdest %extcodehash + STOP // stack: codehash, retdest PROVER_INPUT(account_code::length) // stack: code_length, codehash, retdest diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs new file mode 100644 index 00000000..af1a37ab --- /dev/null +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; +use std::str::FromStr; + +use anyhow::Result; +use ethereum_types::{BigEndianHash, H256, U256}; + +use crate::cpu::kernel::aggregator::combined_kernel; +use crate::cpu::kernel::interpreter::Interpreter; +use crate::cpu::kernel::tests::mpt::extension_to_leaf; +use crate::generation::mpt::{all_mpt_prover_inputs_reversed, AccountRlp}; +use crate::generation::TrieInputs; + +fn test_account_1() -> AccountRlp { + AccountRlp { + nonce: U256::from(1111), + balance: U256::from(2222), + storage_root: H256::from_uint(&U256::from(3333)), + code_hash: H256::from_uint(&U256::from(4444)), + } +} + +pub(crate) fn test_account_1_rlp() -> Vec { + rlp::encode(&test_account_1()).to_vec() +} + +#[test] +fn test_extcodecopy() -> Result<()> { + let trie_inputs = TrieInputs { + state_trie: extension_to_leaf(test_account_1_rlp()), + transactions_trie: Default::default(), + receipts_trie: Default::default(), + storage_tries: vec![], + }; + let kernel = combined_kernel(); + let extcodecopy = kernel.global_labels["extcodecopy"]; + let extcodesize = kernel.global_labels["extcodesize"]; + + let initial_stack = vec![0.into()]; + let mut interpreter = Interpreter::new_with_kernel(extcodesize, initial_stack); + interpreter.generation_state.mpt_prover_inputs = all_mpt_prover_inputs_reversed(&trie_inputs); + interpreter.generation_state.inputs.contract_code = HashMap::from([( + H256::from_str("2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc")?, + vec![0x13, 0x37], + )]); + interpreter.run()?; + assert_eq!(interpreter.stack(), vec![2.into()]); + + Ok(()) +} diff --git a/evm/src/cpu/kernel/tests/mod.rs b/evm/src/cpu/kernel/tests/mod.rs index 9148d6a4..cfccb420 100644 --- a/evm/src/cpu/kernel/tests/mod.rs +++ b/evm/src/cpu/kernel/tests/mod.rs @@ -1,3 +1,4 @@ +mod account_code; mod core; mod curve_ops; mod ecrecover; From 03d7f3d17ecbc5c347b47f1e4d3c9f7b6d84f99b Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 26 Oct 2022 16:39:31 +0200 Subject: [PATCH 04/12] Found bug --- evm/src/cpu/kernel/asm/account_code.asm | 1 - evm/src/cpu/kernel/asm/util/keccak.asm | 4 +- evm/src/cpu/kernel/tests/account_code.rs | 96 ++++++++++++++++++++---- 3 files changed, 83 insertions(+), 18 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 4563fa0a..0f72377e 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -81,7 +81,6 @@ extcodecopy_end: load_code: // stack: address, retdest %extcodehash - STOP // stack: codehash, retdest PROVER_INPUT(account_code::length) // stack: code_length, codehash, retdest diff --git a/evm/src/cpu/kernel/asm/util/keccak.asm b/evm/src/cpu/kernel/asm/util/keccak.asm index 5c05a2d4..92ba8d38 100644 --- a/evm/src/cpu/kernel/asm/util/keccak.asm +++ b/evm/src/cpu/kernel/asm/util/keccak.asm @@ -8,7 +8,7 @@ %stack (word) -> (0, @SEGMENT_KERNEL_GENERAL, 0, word, $num_bytes, %%after_mstore) %jump(mstore_unpacking) %%after_mstore: - // stack: (empty) - %stack () -> (0, @SEGMENT_KERNEL_GENERAL, 0, $num_bytes) // context, segment, offset, len + // stack: offset + %stack (offset) -> (0, @SEGMENT_KERNEL_GENERAL, 0, $num_bytes) // context, segment, offset, len KECCAK_GENERAL %endmacro diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index af1a37ab..77e106f1 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -2,11 +2,13 @@ use std::collections::HashMap; use std::str::FromStr; use anyhow::Result; +use eth_trie_utils::partial_trie::PartialTrie; use ethereum_types::{BigEndianHash, H256, U256}; -use crate::cpu::kernel::aggregator::combined_kernel; +use crate::cpu::kernel::aggregator::{combined_kernel, KERNEL}; +use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; -use crate::cpu::kernel::tests::mpt::extension_to_leaf; +use crate::cpu::kernel::tests::mpt::{extension_to_leaf, nibbles_64}; use crate::generation::mpt::{all_mpt_prover_inputs_reversed, AccountRlp}; use crate::generation::TrieInputs; @@ -14,8 +16,11 @@ fn test_account_1() -> AccountRlp { AccountRlp { nonce: U256::from(1111), balance: U256::from(2222), - storage_root: H256::from_uint(&U256::from(3333)), - code_hash: H256::from_uint(&U256::from(4444)), + storage_root: PartialTrie::Empty.calc_hash(), + code_hash: H256::from_str( + "2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc", + ) + .unwrap(), } } @@ -25,19 +30,80 @@ pub(crate) fn test_account_1_rlp() -> Vec { #[test] fn test_extcodecopy() -> Result<()> { - let trie_inputs = TrieInputs { - state_trie: extension_to_leaf(test_account_1_rlp()), - transactions_trie: Default::default(), - receipts_trie: Default::default(), - storage_tries: vec![], - }; - let kernel = combined_kernel(); - let extcodecopy = kernel.global_labels["extcodecopy"]; - let extcodesize = kernel.global_labels["extcodesize"]; + let state_trie: PartialTrie = Default::default(); + let trie_inputs = Default::default(); + let account = test_account_1(); - let initial_stack = vec![0.into()]; - let mut interpreter = Interpreter::new_with_kernel(extcodesize, initial_stack); + let load_all_mpts = KERNEL.global_labels["load_all_mpts"]; + let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; + let mpt_hash_state_trie = KERNEL.global_labels["mpt_hash_state_trie"]; + let extcodecopy = KERNEL.global_labels["extcodecopy"]; + let extcodesize = KERNEL.global_labels["extcodesize"]; + + let initial_stack = vec![0xDEADBEEFu32.into()]; + let mut interpreter = Interpreter::new_with_kernel(load_all_mpts, initial_stack); interpreter.generation_state.mpt_prover_inputs = all_mpt_prover_inputs_reversed(&trie_inputs); + interpreter.run()?; + assert_eq!(interpreter.stack(), vec![]); + + let k = nibbles_64(U256::from_str( + "5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a", + )?); + // Next, execute mpt_insert_state_trie. + interpreter.offset = mpt_insert_state_trie; + let trie_data = interpreter.get_trie_data_mut(); + if trie_data.is_empty() { + // In the assembly we skip over 0, knowing trie_data[0] = 0 by default. + // Since we don't explicitly set it to 0, we need to do so here. + trie_data.push(0.into()); + } + let value_ptr = trie_data.len(); + trie_data.push(account.nonce); + trie_data.push(account.balance); + // In memory, storage_root gets interpreted as a pointer to a storage trie, + // so we have to ensure the pointer is valid. It's easiest to set it to 0, + // which works as an empty node, since trie_data[0] = 0 = MPT_TYPE_EMPTY. + trie_data.push(H256::zero().into_uint()); + trie_data.push(account.code_hash.into_uint()); + let trie_data_len = trie_data.len().into(); + interpreter.set_global_metadata_field(GlobalMetadata::TrieDataSize, trie_data_len); + interpreter.push(0xDEADBEEFu32.into()); + interpreter.push(value_ptr.into()); // value_ptr + interpreter.push(k.packed); // key + + dbg!(interpreter.stack()); + interpreter.run()?; + assert_eq!( + interpreter.stack().len(), + 0, + "Expected empty stack after insert, found {:?}", + interpreter.stack() + ); + + // Now, execute mpt_hash_state_trie. + interpreter.offset = mpt_hash_state_trie; + interpreter.push(0xDEADBEEFu32.into()); + interpreter.run()?; + + assert_eq!( + interpreter.stack().len(), + 1, + "Expected 1 item on stack after hashing, found {:?}", + interpreter.stack() + ); + let hash = H256::from_uint(&interpreter.stack()[0]); + + let updated_trie = state_trie.insert(k, rlp::encode(&account).to_vec()); + let expected_state_trie_hash = updated_trie.calc_hash(); + assert_eq!(hash, expected_state_trie_hash); + + // let initial_stack = vec![0.into()]; + interpreter.pop(); + interpreter.push(U256::zero()); + dbg!(interpreter.stack()); + interpreter.offset = extcodesize; + // let mut interpreter = Interpreter::new_with_kernel(extcodesize, initial_stack); + // interpreter.generation_state.mpt_prover_inputs = all_mpt_prover_inputs_reversed(&trie_inputs); interpreter.generation_state.inputs.contract_code = HashMap::from([( H256::from_str("2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc")?, vec![0x13, 0x37], From 8b1152c3b3e1d3fe7f1b198f9cd5d1110a7076af Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 27 Oct 2022 09:32:29 +0200 Subject: [PATCH 05/12] Working codesize --- evm/src/cpu/kernel/asm/account_code.asm | 3 +++ evm/src/cpu/kernel/tests/account_code.rs | 6 ++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 0f72377e..0353b481 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -15,7 +15,10 @@ %endmacro global extcodesize: + // stack: address, retdest %extcodesize + // stack: extcodesize(address), retdest + SWAP1 JUMP %macro codesize ADDRESS diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index 77e106f1..c71b50df 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -37,7 +37,7 @@ fn test_extcodecopy() -> Result<()> { let load_all_mpts = KERNEL.global_labels["load_all_mpts"]; let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let mpt_hash_state_trie = KERNEL.global_labels["mpt_hash_state_trie"]; - let extcodecopy = KERNEL.global_labels["extcodecopy"]; + // let extcodecopy = KERNEL.global_labels["extcodecopy"]; let extcodesize = KERNEL.global_labels["extcodesize"]; let initial_stack = vec![0xDEADBEEFu32.into()]; @@ -99,11 +99,9 @@ fn test_extcodecopy() -> Result<()> { // let initial_stack = vec![0.into()]; interpreter.pop(); + interpreter.push(0xDEADBEEFu64.into()); interpreter.push(U256::zero()); - dbg!(interpreter.stack()); interpreter.offset = extcodesize; - // let mut interpreter = Interpreter::new_with_kernel(extcodesize, initial_stack); - // interpreter.generation_state.mpt_prover_inputs = all_mpt_prover_inputs_reversed(&trie_inputs); interpreter.generation_state.inputs.contract_code = HashMap::from([( H256::from_str("2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc")?, vec![0x13, 0x37], From 4c0b3b6079f681def4c36ab28c66461b8c420d86 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 27 Oct 2022 09:55:33 +0200 Subject: [PATCH 06/12] Working with random address and code --- evm/src/cpu/kernel/tests/account_code.rs | 78 +++++++++++++++--------- 1 file changed, 48 insertions(+), 30 deletions(-) diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index c71b50df..d84702ec 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -3,7 +3,10 @@ use std::str::FromStr; use anyhow::Result; use eth_trie_utils::partial_trie::PartialTrie; -use ethereum_types::{BigEndianHash, H256, U256}; +use ethereum_types::{Address, BigEndianHash, H256, U256}; +use hex_literal::hex; +use keccak_hash::keccak; +use rand::{thread_rng, Rng}; use crate::cpu::kernel::aggregator::{combined_kernel, KERNEL}; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; @@ -12,43 +15,47 @@ use crate::cpu::kernel::tests::mpt::{extension_to_leaf, nibbles_64}; use crate::generation::mpt::{all_mpt_prover_inputs_reversed, AccountRlp}; use crate::generation::TrieInputs; -fn test_account_1() -> AccountRlp { +fn test_account(code: &[u8]) -> AccountRlp { AccountRlp { nonce: U256::from(1111), balance: U256::from(2222), storage_root: PartialTrie::Empty.calc_hash(), - code_hash: H256::from_str( - "2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc", - ) - .unwrap(), + code_hash: keccak(code), } } -pub(crate) fn test_account_1_rlp() -> Vec { - rlp::encode(&test_account_1()).to_vec() +fn random_code() -> Vec { + let mut rng = thread_rng(); + let num_bytes = rng.gen_range(0..10000); + (0..num_bytes).map(|_| rng.gen()).collect() } -#[test] -fn test_extcodecopy() -> Result<()> { - let state_trie: PartialTrie = Default::default(); - let trie_inputs = Default::default(); - let account = test_account_1(); +fn test_account_rlp(code: &[u8]) -> Vec { + rlp::encode(&test_account(code)).to_vec() +} +// Stolen from `tests/mpt/insert.rs` +fn prepare_interpreter( + interpreter: &mut Interpreter, + address: Address, + account: &AccountRlp, +) -> Result<()> { let load_all_mpts = KERNEL.global_labels["load_all_mpts"]; let mpt_insert_state_trie = KERNEL.global_labels["mpt_insert_state_trie"]; let mpt_hash_state_trie = KERNEL.global_labels["mpt_hash_state_trie"]; - // let extcodecopy = KERNEL.global_labels["extcodecopy"]; - let extcodesize = KERNEL.global_labels["extcodesize"]; + let state_trie: PartialTrie = Default::default(); + let trie_inputs = Default::default(); + + interpreter.offset = load_all_mpts; + interpreter.push(0xDEADBEEFu32.into()); - let initial_stack = vec![0xDEADBEEFu32.into()]; - let mut interpreter = Interpreter::new_with_kernel(load_all_mpts, initial_stack); interpreter.generation_state.mpt_prover_inputs = all_mpt_prover_inputs_reversed(&trie_inputs); interpreter.run()?; assert_eq!(interpreter.stack(), vec![]); - let k = nibbles_64(U256::from_str( - "5380c7b7ae81a58eb98d9c78de4a1fd7fd9535fc953ed2be602daaa41767312a", - )?); + let k = nibbles_64(U256::from_big_endian( + keccak(address.to_fixed_bytes()).as_bytes(), + )); // Next, execute mpt_insert_state_trie. interpreter.offset = mpt_insert_state_trie; let trie_data = interpreter.get_trie_data_mut(); @@ -71,7 +78,6 @@ fn test_extcodecopy() -> Result<()> { interpreter.push(value_ptr.into()); // value_ptr interpreter.push(k.packed); // key - dbg!(interpreter.stack()); interpreter.run()?; assert_eq!( interpreter.stack().len(), @@ -93,21 +99,33 @@ fn test_extcodecopy() -> Result<()> { ); let hash = H256::from_uint(&interpreter.stack()[0]); - let updated_trie = state_trie.insert(k, rlp::encode(&account).to_vec()); + let updated_trie = state_trie.insert(k, rlp::encode(account).to_vec()); let expected_state_trie_hash = updated_trie.calc_hash(); assert_eq!(hash, expected_state_trie_hash); - // let initial_stack = vec![0.into()]; + Ok(()) +} + +#[test] +fn test_extcodecopy() -> Result<()> { + let code = random_code(); + let account = test_account(&code); + + let mut interpreter = Interpreter::new_with_kernel(0, vec![]); + let address: Address = thread_rng().gen(); + prepare_interpreter(&mut interpreter, address, &account)?; + + let extcodecopy = KERNEL.global_labels["extcodecopy"]; + let extcodesize = KERNEL.global_labels["extcodesize"]; + interpreter.pop(); - interpreter.push(0xDEADBEEFu64.into()); - interpreter.push(U256::zero()); + interpreter.push(0xDEADBEEFu32.into()); + interpreter.push(U256::from_big_endian(address.as_bytes())); interpreter.offset = extcodesize; - interpreter.generation_state.inputs.contract_code = HashMap::from([( - H256::from_str("2636a8beb2c41b8ccafa9a55a5a5e333892a83b491df3a67d2768946a9f9c6dc")?, - vec![0x13, 0x37], - )]); + interpreter.generation_state.inputs.contract_code = + HashMap::from([(keccak(&code), code.clone())]); interpreter.run()?; - assert_eq!(interpreter.stack(), vec![2.into()]); + assert_eq!(interpreter.stack(), vec![code.len().into()]); Ok(()) } From 6bee508f6a264d4ebc78a9723bd354e2327c5a7b Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 27 Oct 2022 09:56:52 +0200 Subject: [PATCH 07/12] Clippy --- evm/src/cpu/kernel/tests/account_code.rs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index d84702ec..0efd96eb 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -1,19 +1,16 @@ use std::collections::HashMap; -use std::str::FromStr; use anyhow::Result; use eth_trie_utils::partial_trie::PartialTrie; use ethereum_types::{Address, BigEndianHash, H256, U256}; -use hex_literal::hex; use keccak_hash::keccak; use rand::{thread_rng, Rng}; -use crate::cpu::kernel::aggregator::{combined_kernel, KERNEL}; +use crate::cpu::kernel::aggregator::KERNEL; use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; -use crate::cpu::kernel::tests::mpt::{extension_to_leaf, nibbles_64}; +use crate::cpu::kernel::tests::mpt::nibbles_64; use crate::generation::mpt::{all_mpt_prover_inputs_reversed, AccountRlp}; -use crate::generation::TrieInputs; fn test_account(code: &[u8]) -> AccountRlp { AccountRlp { @@ -30,10 +27,6 @@ fn random_code() -> Vec { (0..num_bytes).map(|_| rng.gen()).collect() } -fn test_account_rlp(code: &[u8]) -> Vec { - rlp::encode(&test_account(code)).to_vec() -} - // Stolen from `tests/mpt/insert.rs` fn prepare_interpreter( interpreter: &mut Interpreter, From dc8a62fbee628f33113211439bdee2931c2bb8e3 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 27 Oct 2022 11:06:24 +0200 Subject: [PATCH 08/12] Codecopy test --- evm/src/cpu/kernel/asm/account_code.asm | 19 ++++--- evm/src/cpu/kernel/interpreter.rs | 2 +- evm/src/cpu/kernel/tests/account_code.rs | 65 ++++++++++++++++++++++-- 3 files changed, 73 insertions(+), 13 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 0353b481..7d560ec1 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -8,6 +8,12 @@ // stack: codehash %endmacro + +%macro codesize + ADDRESS + %extcodesize +%endmacro + %macro extcodesize %stack (address) -> (address, %%after) %jump(load_code) @@ -20,10 +26,6 @@ global extcodesize: // stack: extcodesize(address), retdest SWAP1 JUMP -%macro codesize - ADDRESS - %extcodesize -%endmacro %macro codecopy // stack: dest_offset, offset, size, retdest @@ -73,14 +75,15 @@ extcodecopy_loop: %stack (i, code_length, offset, dest_offset, size, retdest) -> (i, size, code_length, offset, dest_offset, retdest) %jump(extcodecopy_loop) - - - extcodecopy_end: - %stack (i, size, code_length, offset, dest_offset, size, retdest) -> (retdest) + %stack (i, size, code_length, offset, dest_offset, retdest) -> (retdest) JUMP +// Loads the code at `address` in the `SEGMENT_KERNEL_ACCOUNT_CODE` at the current context and starting at offset 0. +// Checks that the hash of the loaded code corresponds to the `codehash` in the state trie. +// Pre stack: address, retdest +// Post stack: extcodesize(address) load_code: // stack: address, retdest %extcodehash diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 8057792b..478d5413 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -71,7 +71,7 @@ pub struct Interpreter<'a> { kernel_mode: bool, jumpdests: Vec, pub(crate) offset: usize, - context: usize, + pub(crate) context: usize, pub(crate) memory: InterpreterMemory, pub(crate) generation_state: GenerationState, prover_inputs_map: &'a HashMap, diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index 0efd96eb..0576e0e4 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -11,6 +11,7 @@ use crate::cpu::kernel::constants::global_metadata::GlobalMetadata; use crate::cpu::kernel::interpreter::Interpreter; use crate::cpu::kernel::tests::mpt::nibbles_64; use crate::generation::mpt::{all_mpt_prover_inputs_reversed, AccountRlp}; +use crate::memory::segments::Segment; fn test_account(code: &[u8]) -> AccountRlp { AccountRlp { @@ -23,11 +24,12 @@ fn test_account(code: &[u8]) -> AccountRlp { fn random_code() -> Vec { let mut rng = thread_rng(); - let num_bytes = rng.gen_range(0..10000); + let num_bytes = rng.gen_range(0..1000); (0..num_bytes).map(|_| rng.gen()).collect() } // Stolen from `tests/mpt/insert.rs` +// Prepare the interpreter by inserting the account in the state trie. fn prepare_interpreter( interpreter: &mut Interpreter, address: Address, @@ -99,6 +101,33 @@ fn prepare_interpreter( Ok(()) } +#[test] +fn test_extcodesize() -> Result<()> { + let code = random_code(); + let account = test_account(&code); + + let mut interpreter = Interpreter::new_with_kernel(0, vec![]); + let address: Address = thread_rng().gen(); + // Prepare the interpreter by inserting the account in the state trie. + prepare_interpreter(&mut interpreter, address, &account)?; + + let extcodesize = KERNEL.global_labels["extcodesize"]; + + // Test `extcodesize` + interpreter.offset = extcodesize; + interpreter.pop(); + assert!(interpreter.stack().is_empty()); + interpreter.push(0xDEADBEEFu32.into()); + interpreter.push(U256::from_big_endian(address.as_bytes())); + interpreter.generation_state.inputs.contract_code = + HashMap::from([(keccak(&code), code.clone())]); + interpreter.run()?; + + assert_eq!(interpreter.stack(), vec![code.len().into()]); + + Ok(()) +} + #[test] fn test_extcodecopy() -> Result<()> { let code = random_code(); @@ -106,19 +135,47 @@ fn test_extcodecopy() -> Result<()> { let mut interpreter = Interpreter::new_with_kernel(0, vec![]); let address: Address = thread_rng().gen(); + // Prepare the interpreter by inserting the account in the state trie. prepare_interpreter(&mut interpreter, address, &account)?; let extcodecopy = KERNEL.global_labels["extcodecopy"]; - let extcodesize = KERNEL.global_labels["extcodesize"]; + // Put random data in main memory. + let mut rng = thread_rng(); + for i in 0..2000 { + interpreter.memory.context_memory[interpreter.context].segments + [Segment::MainMemory as usize] + .set(i, U256::from(rng.gen::())); + } + + let dest_offset = rng.gen_range(0..3000); + let offset = rng.gen_range(0..1500); + let size = rng.gen_range(0..1500); + + // Test `extcodecopy` + interpreter.offset = extcodecopy; interpreter.pop(); + assert!(interpreter.stack().is_empty()); interpreter.push(0xDEADBEEFu32.into()); + interpreter.push(size.into()); + interpreter.push(offset.into()); + interpreter.push(dest_offset.into()); interpreter.push(U256::from_big_endian(address.as_bytes())); - interpreter.offset = extcodesize; interpreter.generation_state.inputs.contract_code = HashMap::from([(keccak(&code), code.clone())]); interpreter.run()?; - assert_eq!(interpreter.stack(), vec![code.len().into()]); + + assert!(interpreter.stack().is_empty()); + // Check that the code was correctly copied to memory. + for i in 0..size { + let memory = interpreter.memory.context_memory[interpreter.context].segments + [Segment::MainMemory as usize] + .get(dest_offset + i); + assert_eq!( + memory, + code.get(offset + i).copied().unwrap_or_default().into() + ); + } Ok(()) } From fd96d30e24d2e233179ef6e36114a19bb859aaa1 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 27 Oct 2022 14:57:17 +0200 Subject: [PATCH 09/12] Minor --- evm/src/cpu/kernel/asm/account_code.asm | 17 ++++++++++++----- evm/src/cpu/kernel/tests/account_code.rs | 7 ++++++- evm/src/generation/prover_input.rs | 9 ++++++--- evm/src/memory/segments.rs | 2 +- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index 7d560ec1..d40e64ef 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -10,6 +10,7 @@ %macro codesize + // stack: (empty) ADDRESS %extcodesize %endmacro @@ -34,15 +35,21 @@ global extcodesize: %jump(extcodecopy) %endmacro +// Pre stack: address, dest_offset, offset, size, retdest +// Post stack: (empty) global extcodecopy: // stack: address, dest_offset, offset, size, retdest %stack (address, dest_offset, offset, size, retdest) -> (address, extcodecopy_contd, size, offset, dest_offset, retdest) %jump(load_code) + extcodecopy_contd: // stack: code_length, size, offset, dest_offset, retdest SWAP1 // stack: size, code_length, offset, dest_offset, retdest PUSH 0 + +// Loop copying the `code[offset]` to `memory[dest_offset]` until `i==size`. +// Each iteration increments `offset, dest_offset, i`. extcodecopy_loop: // stack: i, size, code_length, offset, dest_offset, retdest DUP2 DUP2 EQ @@ -56,6 +63,7 @@ extcodecopy_loop: %mload_current(@SEGMENT_KERNEL_ACCOUNT_CODE) // stack: opcode, offset < code_length, offset, code_length, dest_offset, i, size, retdest %stack (opcode, offset_lt_code_length, offset, code_length, dest_offset, i, size, retdest) -> (offset_lt_code_length, 0, opcode, offset, code_length, dest_offset, i, size, retdest) + // If `offset >= code_length`, use `opcode=0`. Necessary since `SEGMENT_KERNEL_ACCOUNT_CODE` might be clobbered from previous calls. %select_bool // stack: opcode, offset, code_length, dest_offset, i, size, retdest DUP4 @@ -91,6 +99,8 @@ load_code: PROVER_INPUT(account_code::length) // stack: code_length, codehash, retdest PUSH 0 + +// Loop non-deterministically querying `code[i]` and storing it in `SEGMENT_KERNEL_ACCOUNT_CODE` at offset `i`, until `i==code_length`. load_code_loop: // stack: i, code_length, codehash, retdest DUP2 DUP2 EQ @@ -106,15 +116,12 @@ load_code_loop: // stack: i+1, code_length, codehash, retdest %jump(load_code_loop) +// Check that the hash of the loaded code equals `codehash`. load_code_check: // stack: i, code_length, codehash, retdest POP // stack: code_length, codehash, retdest - %stack (code_length, codehash, retdest) -> (code_length, codehash, retdest, code_length) - PUSH 0 - // stack: 0, code_length, codehash, retdest, code_length - PUSH @SEGMENT_KERNEL_ACCOUNT_CODE - // stack: segment, 0, code_length, codehash, retdest, code_length + %stack (code_length, codehash, retdest) -> (@SEGMENT_KERNEL_ACCOUNT_CODE, 0, code_length, codehash, retdest, code_length) GET_CONTEXT // stack: context, segment, 0, code_length, codehash, retdest, code_length KECCAK_GENERAL diff --git a/evm/src/cpu/kernel/tests/account_code.rs b/evm/src/cpu/kernel/tests/account_code.rs index 0576e0e4..ae9fc30d 100644 --- a/evm/src/cpu/kernel/tests/account_code.rs +++ b/evm/src/cpu/kernel/tests/account_code.rs @@ -13,6 +13,7 @@ use crate::cpu::kernel::tests::mpt::nibbles_64; use crate::generation::mpt::{all_mpt_prover_inputs_reversed, AccountRlp}; use crate::memory::segments::Segment; +// Test account with a given code hash. fn test_account(code: &[u8]) -> AccountRlp { AccountRlp { nonce: U256::from(1111), @@ -140,14 +141,18 @@ fn test_extcodecopy() -> Result<()> { let extcodecopy = KERNEL.global_labels["extcodecopy"]; - // Put random data in main memory. + // Put random data in main memory and the `KernelAccountCode` segment for realism. let mut rng = thread_rng(); for i in 0..2000 { interpreter.memory.context_memory[interpreter.context].segments [Segment::MainMemory as usize] .set(i, U256::from(rng.gen::())); + interpreter.memory.context_memory[interpreter.context].segments + [Segment::KernelAccountCode as usize] + .set(i, U256::from(rng.gen::())); } + // Random inputs let dest_offset = rng.gen_range(0..3000); let offset = rng.gen_range(0..1500); let size = rng.gen_range(0..1500); diff --git a/evm/src/generation/prover_input.rs b/evm/src/generation/prover_input.rs index 82a0c7c3..ad1cfce0 100644 --- a/evm/src/generation/prover_input.rs +++ b/evm/src/generation/prover_input.rs @@ -65,23 +65,26 @@ impl GenerationState { .unwrap_or_else(|| panic!("Out of RLP data")) } - /// Account code + /// Account code. fn run_account_code(&mut self, stack: &[U256], input_fn: &ProverInputFn) -> U256 { match input_fn.0[1].as_str() { "length" => { + // Return length of code. + // stack: codehash let codehash = stack.last().expect("Empty stack"); self.inputs.contract_code[&H256::from_uint(codehash)] .len() .into() } "get" => { + // Return `code[i]`. + // stack: i, code_length, codehash let stacklen = stack.len(); - // Stack looks like: i, code_length, codehash let i = stack[stacklen - 1].as_usize(); let codehash = stack[stacklen - 3]; self.inputs.contract_code[&H256::from_uint(&codehash)][i].into() } - _ => panic!("sup?"), + _ => panic!("Invalid prover input function."), } } } diff --git a/evm/src/memory/segments.rs b/evm/src/memory/segments.rs index 021781ac..f8d536e9 100644 --- a/evm/src/memory/segments.rs +++ b/evm/src/memory/segments.rs @@ -95,7 +95,7 @@ impl Segment { Segment::ContextMetadata => 256, Segment::KernelGeneral => 256, Segment::KernelGeneral2 => 256, - Segment::KernelAccountCode => 256, + Segment::KernelAccountCode => 8, Segment::TxnFields => 256, Segment::TxnData => 256, Segment::RlpRaw => 8, From 7647c5b51ba075f5e0c32ea4f6dc8208d1485dbb Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Mon, 31 Oct 2022 10:15:43 +0100 Subject: [PATCH 10/12] Use address macro instead of opcode --- evm/src/cpu/kernel/asm/account_code.asm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index d40e64ef..bc97883e 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -11,7 +11,7 @@ %macro codesize // stack: (empty) - ADDRESS + %address %extcodesize %endmacro @@ -30,7 +30,7 @@ global extcodesize: %macro codecopy // stack: dest_offset, offset, size, retdest - ADDRESS + %address // stack: address, dest_offset, offset, size, retdest %jump(extcodecopy) %endmacro From 35c00fa6a7627f954255f8604ff33a81c944019c Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 2 Nov 2022 10:37:19 +0100 Subject: [PATCH 11/12] Return 0 if account doesn't exist --- evm/src/cpu/kernel/asm/account_code.asm | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index bc97883e..deb88c59 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -1,12 +1,16 @@ -%macro extcodehash - // stack: address +retzero: + %stack (account_ptr, retdest) -> (retdest, 0) + JUMP + +global extcodehash: + // stack: address, retdest %mpt_read_state_trie // stack: account_ptr + DUP1 ISZERO %jumpi(retzero) %add_const(3) // stack: codehash_ptr %mload_trie_data // stack: codehash -%endmacro %macro codesize @@ -93,8 +97,9 @@ extcodecopy_end: // Pre stack: address, retdest // Post stack: extcodesize(address) load_code: - // stack: address, retdest - %extcodehash + %stack: (address, retdest) -> (extcodehash, address, load_code_ctd, retdest) + JUMP +load_code_ctd: // stack: codehash, retdest PROVER_INPUT(account_code::length) // stack: code_length, codehash, retdest From 8198355565f4e4eca30742a927c9db61817b17bd Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Wed, 2 Nov 2022 11:06:14 +0100 Subject: [PATCH 12/12] Fix + Use context=0 --- evm/src/cpu/kernel/asm/account_code.asm | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/evm/src/cpu/kernel/asm/account_code.asm b/evm/src/cpu/kernel/asm/account_code.asm index deb88c59..14ea4037 100644 --- a/evm/src/cpu/kernel/asm/account_code.asm +++ b/evm/src/cpu/kernel/asm/account_code.asm @@ -5,12 +5,13 @@ retzero: global extcodehash: // stack: address, retdest %mpt_read_state_trie - // stack: account_ptr + // stack: account_ptr, retdest DUP1 ISZERO %jumpi(retzero) %add_const(3) - // stack: codehash_ptr + // stack: codehash_ptr, retdest %mload_trie_data - // stack: codehash + // stack: codehash, retdest + SWAP1 JUMP %macro codesize @@ -97,7 +98,7 @@ extcodecopy_end: // Pre stack: address, retdest // Post stack: extcodesize(address) load_code: - %stack: (address, retdest) -> (extcodehash, address, load_code_ctd, retdest) + %stack (address, retdest) -> (extcodehash, address, load_code_ctd, retdest) JUMP load_code_ctd: // stack: codehash, retdest @@ -126,9 +127,7 @@ load_code_check: // stack: i, code_length, codehash, retdest POP // stack: code_length, codehash, retdest - %stack (code_length, codehash, retdest) -> (@SEGMENT_KERNEL_ACCOUNT_CODE, 0, code_length, codehash, retdest, code_length) - GET_CONTEXT - // stack: context, segment, 0, code_length, codehash, retdest, code_length + %stack (code_length, codehash, retdest) -> (0, @SEGMENT_KERNEL_ACCOUNT_CODE, 0, code_length, codehash, retdest, code_length) KECCAK_GENERAL // stack: shouldbecodehash, codehash, retdest, code_length %assert_eq