From 6b4cce21d89c8cf5154c9d940176ad999d60a4be Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Fri, 21 Oct 2022 18:00:41 +0200 Subject: [PATCH] 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,