From 71ed3c43ac1d738b158fc2802514c2992d2e01f3 Mon Sep 17 00:00:00 2001 From: wborgeaud Date: Thu, 20 Oct 2022 14:32:28 +0200 Subject: [PATCH] Fix fix interpreter --- .../cpu/kernel/constants/context_metadata.rs | 6 +++- evm/src/cpu/kernel/interpreter.rs | 28 ++++++++--------- evm/src/cpu/kernel/tests/mpt/read.rs | 3 +- evm/src/generation/memory.rs | 30 +++++++++++++++++-- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/evm/src/cpu/kernel/constants/context_metadata.rs b/evm/src/cpu/kernel/constants/context_metadata.rs index a2c460fc..0b2dbee5 100644 --- a/evm/src/cpu/kernel/constants/context_metadata.rs +++ b/evm/src/cpu/kernel/constants/context_metadata.rs @@ -23,10 +23,12 @@ pub(crate) enum ContextMetadata { /// Pointer to the initial version of the state trie, at the creation of this context. Used when /// we need to revert a context. StateTrieCheckpointPointer = 9, + /// Size of active memory. + MSize = 10, } impl ContextMetadata { - pub(crate) const COUNT: usize = 10; + pub(crate) const COUNT: usize = 11; pub(crate) fn all() -> [Self; Self::COUNT] { [ @@ -40,6 +42,7 @@ impl ContextMetadata { Self::CallValue, Self::Static, Self::StateTrieCheckpointPointer, + Self::MSize, ] } @@ -56,6 +59,7 @@ impl ContextMetadata { ContextMetadata::CallValue => "CTX_METADATA_CALL_VALUE", ContextMetadata::Static => "CTX_METADATA_STATIC", ContextMetadata::StateTrieCheckpointPointer => "CTX_METADATA_STATE_TRIE_CHECKPOINT_PTR", + ContextMetadata::MSize => "CTX_METADATA_MSIZE", } } } diff --git a/evm/src/cpu/kernel/interpreter.rs b/evm/src/cpu/kernel/interpreter.rs index 0b274221..0e66a08b 100644 --- a/evm/src/cpu/kernel/interpreter.rs +++ b/evm/src/cpu/kernel/interpreter.rs @@ -49,7 +49,7 @@ impl InterpreterMemory { } impl InterpreterMemory { - fn mload_general(&self, context: usize, segment: Segment, offset: usize) -> U256 { + fn mload_general(&mut self, context: usize, segment: Segment, offset: usize) -> U256 { let value = self.context_memory[context].segments[segment as usize].get(offset); assert!( value.bits() <= segment.bit_range(), @@ -145,18 +145,19 @@ impl<'a> Interpreter<'a> { Ok(()) } - fn code(&self) -> &MemorySegmentState { - &self.memory.context_memory[self.context].segments[Segment::Code as usize] + fn code(&mut self) -> &mut MemorySegmentState { + &mut self.memory.context_memory[self.context].segments[Segment::Code as usize] } - fn code_slice(&self, n: usize) -> Vec { - self.code().content[self.offset..self.offset + n] + fn code_slice(&mut self, n: usize) -> Vec { + let offset = self.offset; + self.code().content[offset..offset + n] .iter() .map(|u256| u256.byte(0)) .collect::>() } - pub(crate) fn get_txn_field(&self, field: NormalizedTxnField) -> U256 { + pub(crate) fn get_txn_field(&mut self, field: NormalizedTxnField) -> U256 { self.memory.context_memory[0].segments[Segment::TxnFields as usize].get(field as usize) } @@ -169,7 +170,7 @@ impl<'a> Interpreter<'a> { &self.memory.context_memory[0].segments[Segment::TxnData as usize].content } - pub(crate) fn get_global_metadata_field(&self, field: GlobalMetadata) -> U256 { + pub(crate) fn get_global_metadata_field(&mut self, field: GlobalMetadata) -> U256 { self.memory.context_memory[0].segments[Segment::GlobalMetadata as usize].get(field as usize) } @@ -224,7 +225,8 @@ impl<'a> Interpreter<'a> { } fn run_opcode(&mut self) -> anyhow::Result<()> { - let opcode = self.code().get(self.offset).byte(0); + let offset = self.offset; + let opcode = self.code().get(offset).byte(0); self.incr(1); match opcode { 0x00 => self.run_stop(), // "STOP", @@ -579,11 +581,9 @@ impl<'a> Interpreter<'a> { } fn run_msize(&mut self) { - let num_bytes = self.memory.context_memory[self.context].segments - [Segment::MainMemory as usize] - .content - .len(); - self.push(U256::from(ceil_div_usize(num_bytes, 32) * 32)); + self.push(U256::from( + self.memory.context_memory[self.context].segments[Segment::MainMemory as usize].msize, + )) } fn run_jumpdest(&mut self) { @@ -709,7 +709,7 @@ mod tests { 0x53, ]; let pis = HashMap::new(); - let run = run(&code, 0, vec![], &pis)?; + let mut run = run(&code, 0, vec![], &pis)?; assert_eq!(run.stack(), &[0xff.into(), 0xff00.into()]); assert_eq!( run.memory.context_memory[0].segments[Segment::MainMemory as usize].get(0x27), diff --git a/evm/src/cpu/kernel/tests/mpt/read.rs b/evm/src/cpu/kernel/tests/mpt/read.rs index d8808e24..12728cd1 100644 --- a/evm/src/cpu/kernel/tests/mpt/read.rs +++ b/evm/src/cpu/kernel/tests/mpt/read.rs @@ -31,7 +31,8 @@ fn mpt_read() -> Result<()> { interpreter.push(0xdeadbeefu32.into()); interpreter.push(0xABCDEFu64.into()); interpreter.push(6.into()); - interpreter.push(interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot)); + let state_trie_root = interpreter.get_global_metadata_field(GlobalMetadata::StateTrieRoot); + interpreter.push(state_trie_root); interpreter.run()?; assert_eq!(interpreter.stack().len(), 1); diff --git a/evm/src/generation/memory.rs b/evm/src/generation/memory.rs index 944b42a6..18ed2e16 100644 --- a/evm/src/generation/memory.rs +++ b/evm/src/generation/memory.rs @@ -1,4 +1,5 @@ use ethereum_types::U256; +use plonky2_util::ceil_div_usize; use crate::memory::memory_stark::MemoryOp; use crate::memory::segments::Segment; @@ -22,19 +23,34 @@ impl Default for MemoryState { } } -#[derive(Clone, Default, Debug)] +#[derive(Clone, Debug)] pub(crate) struct MemoryContextState { /// The content of each memory segment. pub segments: [MemorySegmentState; Segment::COUNT], } -#[derive(Clone, Default, Debug)] +impl Default for MemoryContextState { + fn default() -> Self { + Self { + segments: Segment::all().map(|segment| MemorySegmentState { + content: vec![], + segment, + msize: 0, + }), + } + } +} + +#[derive(Clone, Debug)] pub(crate) struct MemorySegmentState { pub content: Vec, + pub segment: Segment, + pub msize: usize, } impl MemorySegmentState { - pub(crate) fn get(&self, virtual_addr: usize) -> U256 { + pub(crate) fn get(&mut self, virtual_addr: usize) -> U256 { + self.update_msize(virtual_addr); self.content .get(virtual_addr) .copied() @@ -42,9 +58,17 @@ impl MemorySegmentState { } pub(crate) fn set(&mut self, virtual_addr: usize, value: U256) { + assert_eq!(value >> self.segment.bit_range(), U256::zero()); + self.update_msize(virtual_addr); if virtual_addr >= self.content.len() { self.content.resize(virtual_addr + 1, U256::zero()); } self.content[virtual_addr] = value; } + + fn update_msize(&mut self, virtual_addr: usize) { + let word_size = 256 / self.segment.bit_range(); + let new_msize = ceil_div_usize(virtual_addr + 1, word_size) * 32; + self.msize = self.msize.max(new_msize); + } }