From 9f5645d4d89809f92cd2bfa6a8e92f0873224142 Mon Sep 17 00:00:00 2001 From: Wei Tang Date: Sun, 19 Nov 2023 00:40:38 +0100 Subject: [PATCH] Compliance fix 2 (#219) * Add support for access list in jsontests * Fix control flow * Fix storage reset * Filter out errorous zero value from test files --- .github/workflows/rust.yml | 6 ++++-- interpreter/src/lib.rs | 15 ++++++--------- jsontests/src/run.rs | 14 +++++++++++++- jsontests/src/types.rs | 22 +++++++++++++++++++++- src/backend/in_memory.rs | 13 +++++++------ src/standard/invoker/mod.rs | 7 +++++++ 6 files changed, 58 insertions(+), 19 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index b93096c74..b94e24354 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -36,5 +36,7 @@ jobs: - name: Run tests run: | cargo run --release --verbose -p jsontests -- \ - jsontests/res/ethtests/GeneralStateTests/stExample/add11.json \ - jsontests/res/ethtests/GeneralStateTests/stSLoadTest/ + jsontests/res/ethtests/GeneralStateTests/stExample/ \ + jsontests/res/ethtests/GeneralStateTests/stSLoadTest/ \ + jsontests/res/ethtests/GeneralStateTests/VMTests/vmArithmeticTest/ \ + jsontests/res/ethtests/GeneralStateTests/VMTests/vmBitwiseLogicOperation/ diff --git a/interpreter/src/lib.rs b/interpreter/src/lib.rs index 35a50dc5a..c7a80da81 100644 --- a/interpreter/src/lib.rs +++ b/interpreter/src/lib.rs @@ -160,31 +160,28 @@ impl Machine { let opcode = Opcode(self.code[position]); let control = etable[opcode.as_usize()](self, handle, opcode, self.position); - let mut ret = match control { + match control { Control::Continue => { self.position += 1; - Ok(()) } Control::ContinueN(p) => { self.position = position + p; - Ok(()) } Control::Exit(e) => { self.position = self.code.len(); - Err(Capture::Exit(e)) + return Err(Capture::Exit(e)); } Control::Jump(p) => { self.position = p; - Ok(()) } - Control::Trap(opcode) => Err(Capture::Trap(opcode)), + Control::Trap(opcode) => return Err(Capture::Trap(opcode)), }; - if position >= self.code.len() { - ret = Err(Capture::Exit(ExitSucceed::Stopped.into())); + if self.position >= self.code.len() { + return Err(Capture::Exit(ExitSucceed::Stopped.into())); } - ret + Ok(()) } /// Pick the next opcode. diff --git a/jsontests/src/run.rs b/jsontests/src/run.rs index f79bac95c..6ab3df142 100644 --- a/jsontests/src/run.rs +++ b/jsontests/src/run.rs @@ -15,6 +15,12 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test, debug: bool) -> R _ => return Err(Error::UnsupportedFork), }; + if test.post.expect_exception == Some(TestExpectException::TR_TypeNotSupported) { + // The `evm` crate does not understand transaction format, only the `ethereum` crate. So + // there's nothing for us to test here for `TR_TypeNotSupported`. + return Ok(()); + } + let env = InMemoryEnvironment { block_hashes: BTreeMap::new(), // TODO: fill in this field. block_number: test.env.current_number, @@ -35,6 +41,7 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test, debug: bool) -> R let storage = account .storage .into_iter() + .filter(|(_, value)| *value != U256::zero()) .map(|(key, value)| (u256_to_h256(key), u256_to_h256(value))) .collect::>(); @@ -60,7 +67,12 @@ pub fn run_test(_filename: &str, _test_name: &str, test: Test, debug: bool) -> R data: test.transaction.data, gas_limit: test.transaction.gas_limit, gas_price: test.transaction.gas_price, - access_list: Vec::new(), + access_list: test + .transaction + .access_list + .into_iter() + .map(|access| (access.address, access.storage_keys)) + .collect(), }; let mut run_backend = InMemoryBackend { diff --git a/jsontests/src/types.rs b/jsontests/src/types.rs index 2034b56bb..0d3d317dc 100644 --- a/jsontests/src/types.rs +++ b/jsontests/src/types.rs @@ -39,6 +39,10 @@ impl TestMulti { sender: self.transaction.sender, to: self.transaction.to, value: self.transaction.value[post_state.indexes.value], + access_list: match &self.transaction.access_lists { + Some(access_lists) => access_lists[post_state.indexes.data].clone(), + None => Vec::new(), + }, }, }); } @@ -113,7 +117,14 @@ pub struct TestPostState { pub indexes: TestPostStateIndexes, pub logs: H256, pub txbytes: HexBytes, - pub expect_exception: Option, + pub expect_exception: Option, +} + +#[derive(Clone, Debug, Eq, PartialEq, Deserialize)] +#[allow(non_camel_case_types)] +pub enum TestExpectException { + TR_TypeNotSupported, + TR_IntrinsicGas, } #[derive(Clone, Debug, Eq, PartialEq, Deserialize)] @@ -144,6 +155,14 @@ pub struct TestMultiTransaction { pub sender: H160, pub to: H160, pub value: Vec, + pub access_lists: Option>>, +} + +#[derive(Clone, Debug, Eq, PartialEq, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct TestAccessListItem { + pub address: H160, + pub storage_keys: Vec, } #[derive(Clone, Debug, Eq, PartialEq)] @@ -156,6 +175,7 @@ pub struct TestTransaction { pub sender: H160, pub to: H160, pub value: U256, + pub access_list: Vec, } #[derive(Clone, Debug, Eq, PartialEq, Deserialize)] diff --git a/src/backend/in_memory.rs b/src/backend/in_memory.rs index f23e82055..c63441118 100644 --- a/src/backend/in_memory.rs +++ b/src/backend/in_memory.rs @@ -174,12 +174,13 @@ impl RuntimeBackend for InMemoryBackend { } fn set_storage(&mut self, address: H160, index: H256, value: H256) -> Result<(), ExitError> { - self.current_layer_mut() - .state - .entry(address) - .or_default() - .storage - .insert(index, value); + let entry = self.current_layer_mut().state.entry(address).or_default(); + + if value == H256::default() { + entry.storage.remove(&index); + } else { + entry.storage.insert(index, value); + } Ok(()) } diff --git a/src/standard/invoker/mod.rs b/src/standard/invoker/mod.rs index 546f4eb3f..087b1a7cf 100644 --- a/src/standard/invoker/mod.rs +++ b/src/standard/invoker/mod.rs @@ -193,6 +193,13 @@ where access_list, .. } => { + for (address, keys) in &access_list { + handler.mark_hot(*address, None)?; + for key in keys { + handler.mark_hot(*address, Some(*key))?; + } + } + let code = handler.code(address); let gasometer =