From 1ba2388166bcd16ea536d238338914c2df777e27 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 15 Oct 2025 02:27:18 +0200 Subject: [PATCH 001/127] bump: tag v91 revm v30.1.1 (#3099) --- CHANGELOG.md | 22 ++++++++++++++++++++++ MIGRATION_GUIDE.md | 7 ++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5204ef9a0..94bc483c07 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v91 +date: 15.10.2025 + +Patch release with a JumpTable serde fix + +* `revm-primitives`: 21.0.0 -> 21.0.1 (✓ API compatible changes) +* `revm-bytecode`: 7.0.0 -> 7.0.1 (✓ API compatible changes) +* `revm-context`: 10.1.0 -> 10.1.1 (✓ API compatible changes) +* `revm-interpreter`: 27.0.0 -> 27.0.1 (✓ API compatible changes) +* `revm-precompile`: 28.1.0 -> 28.1.1 (✓ API compatible changes) +* `revm-handler`: 11.1.0 -> 11.1.1 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-state`: 8.0.0 -> 8.0.1 +* `revm-database-interface`: 8.0.1 -> 8.0.2 +* `revm-context-interface`: 11.1.0 -> 11.1.1 +* `revm-database`: 9.0.0 -> 9.0.1 +* `revm-inspector`: 11.1.0 -> 11.1.1 +* `revm`: 30.1.0 -> 30.1.1 +* `revm-statetest-types`: 10.1.0 -> 10.1.1 +* `revme`: 8.2.0 -> 8.2.1 +* `op-revm`: 11.1.0 -> 11.1.1 + # v90 date: 10.10.2025 diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index f15708e1f2..f8ed1d9698 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,9 @@ -# v90 tag ( revm v30.0.1) + +# v91 tag ( revm v30.1.1) + +No breaking changes + +# v90 tag ( revm v30.1.0) * Removal of some deprecated functions. `into_plain_state`, `regenerate_hash` were deprecated few releases ago. From 948de496f7400e1da8ee5d518d388a7df8c2c996 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 15 Oct 2025 14:32:01 +0200 Subject: [PATCH 002/127] revert: use JumpTable old serde format (#3101) * revert: JumpTable old serde format * fix resize and bump all test fixtures * rm unused import * Update crates/bytecode/src/legacy/jump_map.rs Co-authored-by: Arsenii Kulikov --------- Co-authored-by: Arsenii Kulikov --- crates/bytecode/src/legacy/jump_map.rs | 48 +++++----------- .../op_revm_testdata/test_deposit_tx.json | 9 ++- .../test_halted_deposit_tx.json | 20 +++++-- ...all_bls12_381_g1_add_input_wrong_size.json | 45 +++++++++++---- ...d_tx_call_bls12_381_g1_add_out_of_gas.json | 45 +++++++++++---- ...all_bls12_381_g1_msm_input_wrong_size.json | 45 +++++++++++---- ...d_tx_call_bls12_381_g1_msm_out_of_gas.json | 45 +++++++++++---- ...l_bls12_381_g1_msm_wrong_input_layout.json | 45 +++++++++++---- ...all_bls12_381_g2_add_input_wrong_size.json | 45 +++++++++++---- ...d_tx_call_bls12_381_g2_add_out_of_gas.json | 45 +++++++++++---- ...all_bls12_381_g2_msm_input_wrong_size.json | 45 +++++++++++---- ...d_tx_call_bls12_381_g2_msm_out_of_gas.json | 45 +++++++++++---- ...l_bls12_381_g2_msm_wrong_input_layout.json | 45 +++++++++++---- ...12_381_map_fp2_to_g2_input_wrong_size.json | 45 +++++++++++---- ...ll_bls12_381_map_fp2_to_g2_out_of_gas.json | 45 +++++++++++---- ...s12_381_map_fp_to_g1_input_wrong_size.json | 45 +++++++++++---- ...all_bls12_381_map_fp_to_g1_out_of_gas.json | 45 +++++++++++---- ...ll_bls12_381_pairing_input_wrong_size.json | 45 +++++++++++---- ..._tx_call_bls12_381_pairing_out_of_gas.json | 45 +++++++++++---- ..._bls12_381_pairing_wrong_input_layout.json | 45 +++++++++++---- .../test_halted_tx_call_bn254_pair_fjord.json | 45 +++++++++++---- ...est_halted_tx_call_bn254_pair_granite.json | 45 +++++++++++---- .../test_halted_tx_call_p256verify.json | 45 +++++++++++---- .../op_revm_testdata/test_log_inspector.json | 56 +++++++++++++++---- .../test_tx_call_p256verify.json | 45 +++++++++++---- .../revm_testdata/test_multi_tx_create.json | 38 ++++++++++--- .../test_selfdestruct_multi_tx.json | 36 +++++++++--- 27 files changed, 874 insertions(+), 278 deletions(-) diff --git a/crates/bytecode/src/legacy/jump_map.rs b/crates/bytecode/src/legacy/jump_map.rs index 562f53e562..1347b44778 100644 --- a/crates/bytecode/src/legacy/jump_map.rs +++ b/crates/bytecode/src/legacy/jump_map.rs @@ -10,10 +10,8 @@ use std::{fmt::Debug, sync::Arc}; /// /// It is immutable, cheap to clone and memory efficient, with one bit per byte in the bytecode. #[derive(Clone, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct JumpTable { /// Cached pointer to table data to avoid Arc overhead on lookup - #[cfg_attr(feature = "serde", serde(skip))] table_ptr: *const u8, /// Number of bits in the table. len: usize, @@ -65,35 +63,26 @@ impl Default for JumpTable { } } +#[cfg(feature = "serde")] +impl serde::Serialize for JumpTable { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut bitvec = BitVec::::from_vec(self.table.to_vec()); + bitvec.resize(self.len, false); + bitvec.serialize(serializer) + } +} + #[cfg(feature = "serde")] impl<'de> serde::Deserialize<'de> for JumpTable { fn deserialize(deserializer: D) -> Result where D: serde::Deserializer<'de>, { - #[derive(serde::Deserialize)] - - struct JumpTableSerde { - #[serde(alias = "bits")] - len: usize, - #[serde(alias = "data")] - table: Table, - } - - #[derive(serde::Deserialize, Debug)] - #[serde(untagged)] - enum Table { - Data(std::vec::Vec), - Table(Bytes), - } - - let data = JumpTableSerde::deserialize(deserializer)?; - let table = match data.table { - Table::Table(table) => table, - Table::Data(data) => Bytes::from(data), - }; - - Ok(Self::from_bytes_arc(Arc::new(table), data.len)) + let bitvec = BitVec::deserialize(deserializer)?; + Ok(Self::new(bitvec)) } } @@ -235,21 +224,12 @@ mod tests { "data": [5] }"#; - let new_format = r#" - { - "len": 4, - "table": "0x05" - }"#; - let table: JumpTable = serde_json::from_str(legacy_format).expect("Failed to deserialize"); assert_eq!(table.len, 4); assert!(table.is_valid(0)); assert!(!table.is_valid(1)); assert!(table.is_valid(2)); assert!(!table.is_valid(3)); - - let new_table: JumpTable = serde_json::from_str(new_format).expect("Failed to deserialize"); - assert_eq!(new_table, table); } #[test] diff --git a/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json index 9b2029ce56..ce989e10db 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json @@ -18,8 +18,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json index 7e7b36361a..0769dd9c2f 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json @@ -13,8 +13,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -33,8 +38,15 @@ "LegacyAnalyzed": { "bytecode": "0x5000", "jump_table": { - "len": 1, - "table": "0x00" + "bits": 1, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 1 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json index 8cd1b7f9bb..9ab987baba 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json index 47e57970b0..4d1f78ca80 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json index 680feb30be..5e9e175426 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json index cfe195eb3e..d2a41cfed6 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json index 67a214f020..d825d723b8 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json index c7bd90d5d5..58c506307a 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json index 36262bb3be..c050e75ec1 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json index fa95ae5ed2..bae68df493 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json index 6b975d9658..59b81d7b5e 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json index caa0a01cdc..87cb378c40 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json index 61b28b9eba..25718c3549 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json index 5870684c57..4e12839026 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json index f3c95534dc..250bcb34c5 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json index 2967d7d35d..cc66059ecf 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json index 7f68950948..c550b7a9c7 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json index 23c2a935d7..e3ecc1304f 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json index 8638f098c5..fadbf7cb6f 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json index 70b6029f13..4f98b9d9ad 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json index e22fcb268a..b457155b93 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json index 8c6633224c..a21e7ce5e3 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json @@ -17,8 +17,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -37,8 +42,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -57,8 +67,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -77,8 +92,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -97,8 +117,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json index 1e8fbb1365..145505a365 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json @@ -24,8 +24,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -44,8 +49,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -64,8 +74,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -84,8 +99,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -104,8 +124,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -124,8 +149,15 @@ "LegacyAnalyzed": { "bytecode": "0x600080a000", "jump_table": { - "len": 5, - "table": "0x00" + "bits": 5, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 5 } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json index e63ed6319d..87cdf23853 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json @@ -18,8 +18,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -38,8 +43,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -58,8 +68,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -78,8 +93,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -98,8 +118,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json index 44927c973d..60cff1e58f 100644 --- a/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json +++ b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json @@ -46,8 +46,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -66,8 +71,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -86,8 +96,15 @@ "LegacyAnalyzed": { "bytecode": "0x61ffffff00", "jump_table": { - "len": 5, - "table": "0x00" + "bits": 5, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 5 } @@ -106,8 +123,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } diff --git a/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json index 2e2fabbab6..ccc0fe6dd4 100644 --- a/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json +++ b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json @@ -29,8 +29,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -49,8 +54,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -69,8 +79,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } @@ -89,8 +104,13 @@ "LegacyAnalyzed": { "bytecode": "0x00", "jump_table": { - "len": 0, - "table": "0x" + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" }, "original_len": 0 } From be2c3551ac39868908dec0c70f6820ad5009dff2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 15 Oct 2025 14:39:04 +0200 Subject: [PATCH 003/127] chore: release (#3102) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ bins/revme/CHANGELOG.md | 6 ++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 6 ++++++ crates/bytecode/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 6 ++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 6 ++++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 6 ++++++ crates/database/Cargo.toml | 2 +- crates/database/interface/CHANGELOG.md | 6 ++++++ crates/database/interface/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 6 ++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 6 ++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 6 ++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 6 ++++++ crates/op-revm/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 6 ++++++ crates/revm/Cargo.toml | 2 +- crates/state/CHANGELOG.md | 6 ++++++ crates/state/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 6 ++++++ crates/statetest-types/Cargo.toml | 2 +- 28 files changed, 116 insertions(+), 38 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 98fdaa7102..d77cf65ec9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "11.1.1" +version = "11.1.2" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "30.1.1" +version = "30.1.2" dependencies = [ "revm-bytecode", "revm-context", @@ -3552,7 +3552,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.0.1" +version = "7.0.2" dependencies = [ "bitvec", "paste", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "10.1.1" +version = "10.1.2" dependencies = [ "bitvec", "cfg-if", @@ -3580,7 +3580,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "11.1.1" +version = "11.1.2" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3594,7 +3594,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.1" +version = "9.0.2" dependencies = [ "alloy-eips", "alloy-provider", @@ -3610,7 +3610,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.2" +version = "8.0.3" dependencies = [ "auto_impl", "either", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "11.1.1" +version = "11.1.2" dependencies = [ "alloy-eip7702", "alloy-provider", @@ -3658,7 +3658,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "11.1.1" +version = "11.1.2" dependencies = [ "auto_impl", "either", @@ -3675,7 +3675,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "27.0.1" +version = "27.0.2" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3725,7 +3725,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.0.1" +version = "8.0.2" dependencies = [ "bitflags", "revm-bytecode", @@ -3735,7 +3735,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "10.1.1" +version = "10.1.2" dependencies = [ "alloy-eips", "k256", @@ -3747,7 +3747,7 @@ dependencies = [ [[package]] name = "revme" -version = "8.2.1" +version = "8.2.2" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index c04cfa1a3e..a165e7a4ca 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "30.1.1", default-features = false } +revm = { path = "crates/revm", version = "30.1.2", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.1", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.0.1", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "9.0.1", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.2", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "8.0.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "27.0.1", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.1.1", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.0.2", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "9.0.2", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.3", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "8.0.2", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "27.0.2", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.1.2", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "28.1.1", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.1.1", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "10.1.1", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "11.1.1", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "11.1.1", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.1.1", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.1.2", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "10.1.2", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "11.1.2", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "11.1.2", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.1.2", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 89ad00610f..bde007d34c 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.2.2](https://github.com/bluealloy/revm/compare/revme-v8.2.1...revme-v8.2.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-database-interface, revm-context-interface, revm-context, revm-database, revm-inspector, revm, revm-statetest-types + ## [8.2.1](https://github.com/bluealloy/revm/compare/revme-v8.2.0...revme-v8.2.1) - 2025-10-15 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index bfa8da575e..f56ef11e49 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "8.2.1" +version = "8.2.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index 0803202fb3..bc50b15a1c 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.0.2](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.0.1...revm-bytecode-v7.0.2) - 2025-10-15 + +### Other + +- use JumpTable old serde format ([#3101](https://github.com/bluealloy/revm/pull/3101)) + ## [7.0.1](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.0.0...revm-bytecode-v7.0.1) - 2025-10-15 ### Fixed diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index e568840731..c69af45246 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "7.0.1" +version = "7.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 59e0cebe47..20c171b98f 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.1.2](https://github.com/bluealloy/revm/compare/revm-context-v10.1.1...revm-context-v10.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-database-interface, revm-context-interface + ## [10.1.1](https://github.com/bluealloy/revm/compare/revm-context-v10.1.0...revm-context-v10.1.1) - 2025-10-15 ### Other diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 633f15187b..f554eba269 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "10.1.1" +version = "10.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index 93ee11452e..318df1a825 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.2](https://github.com/bluealloy/revm/compare/revm-context-interface-v11.1.1...revm-context-interface-v11.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-state, revm-database-interface + ## [11.1.1](https://github.com/bluealloy/revm/compare/revm-context-interface-v11.1.0...revm-context-interface-v11.1.1) - 2025-10-15 ### Other diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index f381b407c8..8dd2962c88 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "11.1.1" +version = "11.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index 78c4b2e43a..debbba7d98 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.2](https://github.com/bluealloy/revm/compare/revm-database-v9.0.1...revm-database-v9.0.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-database-interface + ## [9.0.1](https://github.com/bluealloy/revm/compare/revm-database-v9.0.0...revm-database-v9.0.1) - 2025-10-15 ### Other diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index d9fd4fe017..7173ba3d0e 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "9.0.1" +version = "9.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/interface/CHANGELOG.md b/crates/database/interface/CHANGELOG.md index 4717e67481..065a59891f 100644 --- a/crates/database/interface/CHANGELOG.md +++ b/crates/database/interface/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.0.3](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.2...revm-database-interface-v8.0.3) - 2025-10-15 + +### Other + +- updated the following local packages: revm-state + ## [8.0.2](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.1...revm-database-interface-v8.0.2) - 2025-10-15 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index b86656476e..ddff4d8309 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database-interface" description = "Revm Database interface" -version = "8.0.2" +version = "8.0.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 476f37f264..a875f89397 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.2](https://github.com/bluealloy/revm/compare/revm-handler-v11.1.1...revm-handler-v11.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-database-interface, revm-context-interface, revm-context, revm-database, revm-interpreter + ## [11.1.1](https://github.com/bluealloy/revm/compare/revm-handler-v11.1.0...revm-handler-v11.1.1) - 2025-10-15 ### Other diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index cf90f99835..9ee503bc2d 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "11.1.1" +version = "11.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 6b388ff89c..ef3f4851b8 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.2](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.1...revm-inspector-v11.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-state, revm-database-interface, revm-context, revm-database, revm-interpreter, revm-handler + ## [11.1.1](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.0...revm-inspector-v11.1.1) - 2025-10-15 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 613f630877..b9faafa743 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "11.1.1" +version = "11.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 6e0fe840cf..a8a6111b39 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -51,6 +51,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [27.0.2](https://github.com/bluealloy/revm/compare/revm-interpreter-v27.0.1...revm-interpreter-v27.0.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-context-interface + ## [27.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v27.0.0...revm-interpreter-v27.0.1) - 2025-10-15 ### Fixed diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index ba7e15eb87..b07f7f1697 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "27.0.1" +version = "27.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 1e2b533343..07b0d79137 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.2](https://github.com/bluealloy/revm/compare/op-revm-v11.1.1...op-revm-v11.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm + ## [11.1.1](https://github.com/bluealloy/revm/compare/op-revm-v11.1.0...op-revm-v11.1.1) - 2025-10-15 ### Other diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 90b3b6ae91..10ac297692 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "11.1.1" +version = "11.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 770981b2dc..fc2d908d07 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [30.1.2](https://github.com/bluealloy/revm/compare/revm-v30.1.1...revm-v30.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-database-interface, revm-context-interface, revm-context, revm-database, revm-interpreter, revm-handler, revm-inspector + ## [30.1.1](https://github.com/bluealloy/revm/compare/revm-v30.1.0...revm-v30.1.1) - 2025-10-15 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 81c18bec39..590e38cba7 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "30.1.1" +version = "30.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index 190f11d1f0..e927e782c8 100644 --- a/crates/state/CHANGELOG.md +++ b/crates/state/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.0.2](https://github.com/bluealloy/revm/compare/revm-state-v8.0.1...revm-state-v8.0.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm-bytecode + ## [8.0.1](https://github.com/bluealloy/revm/compare/revm-state-v8.0.0...revm-state-v8.0.1) - 2025-10-15 ### Other diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index c2c2505401..07649c32ed 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "8.0.1" +version = "8.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 2c3730f786..e2ad81252c 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.1.2](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.1...revm-statetest-types-v10.1.2) - 2025-10-15 + +### Other + +- updated the following local packages: revm + ## [10.1.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.0...revm-statetest-types-v10.1.1) - 2025-10-15 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 2492ab7a63..dca2dbaa87 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "10.1.1" +version = "10.1.2" authors.workspace = true edition.workspace = true keywords.workspace = true From 91ed59fe40013b125852dd443731b7f142438b39 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 15 Oct 2025 15:36:51 +0200 Subject: [PATCH 004/127] bump: tag v92 revm v30.1.2 (#3103) --- CHANGELOG.md | 20 ++++++++++++++++++++ MIGRATION_GUIDE.md | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 94bc483c07..a0913245f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,25 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v92 +date 15.10.2025 + +Patch release that would revert JumpTable serde serialization/deserialization to before v90 release + +* `revm-bytecode`: 7.0.1 -> 7.0.2 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-state`: 8.0.1 -> 8.0.2 +* `revm-database-interface`: 8.0.2 -> 8.0.3 +* `revm-context-interface`: 11.1.1 -> 11.1.2 +* `revm-context`: 10.1.1 -> 10.1.2 +* `revm-database`: 9.0.1 -> 9.0.2 +* `revm-interpreter`: 27.0.1 -> 27.0.2 +* `revm-handler`: 11.1.1 -> 11.1.2 +* `revm-inspector`: 11.1.1 -> 11.1.2 +* `revm`: 30.1.1 -> 30.1.2 +* `revm-statetest-types`: 10.1.1 -> 10.1.2 +* `revme`: 8.2.1 -> 8.2.2 +* `op-revm`: 11.1.1 -> 11.1.2 + # v91 date: 15.10.2025 diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index f8ed1d9698..f404fb31b2 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,8 @@ +# v92 tag ( revm v30.1.2) + +No breaking changes + # v91 tag ( revm v30.1.1) No breaking changes From 9613d612763de70ebe54cb5c72b6a88db8d5f80f Mon Sep 17 00:00:00 2001 From: 0xMushow <105550256+0xMushow@users.noreply.github.com> Date: Thu, 16 Oct 2025 12:43:29 +0200 Subject: [PATCH 005/127] typo(instructions): fix typo in spurious_dragon variable (#3106) --- .../interpreter/src/instructions/contract/call_helpers.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/interpreter/src/instructions/contract/call_helpers.rs b/crates/interpreter/src/instructions/contract/call_helpers.rs index 4d2ee93a9d..88163bea09 100644 --- a/crates/interpreter/src/instructions/contract/call_helpers.rs +++ b/crates/interpreter/src/instructions/contract/call_helpers.rs @@ -134,7 +134,7 @@ pub fn load_account_delegated( ) -> Result<(u64, Bytecode, B256), LoadError> { let mut cost = 0; let is_berlin = spec.is_enabled_in(SpecId::BERLIN); - let is_spurioud_dragon = spec.is_enabled_in(SpecId::SPURIOUS_DRAGON); + let is_spurious_dragon = spec.is_enabled_in(SpecId::SPURIOUS_DRAGON); let skip_cold_load = is_berlin && remaining_gas < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; let account = host.load_account_info_skip_cold_load(address, true, skip_cold_load)?; @@ -145,7 +145,7 @@ pub fn load_account_delegated( let mut code_hash = account.code_hash(); // New account cost, as account is empty there is no delegated account and we can return early. if create_empty_account && account.is_empty { - cost += new_account_cost(is_spurioud_dragon, transfers_value); + cost += new_account_cost(is_spurious_dragon, transfers_value); return Ok((cost, bytecode, code_hash)); } @@ -175,11 +175,11 @@ pub fn load_account_delegated( /// Returns new account cost. #[inline] -pub fn new_account_cost(is_spurioud_dragon: bool, transfers_value: bool) -> u64 { +pub fn new_account_cost(is_spurious_dragon: bool, transfers_value: bool) -> u64 { // EIP-161: State trie clearing (invariant-preserving alternative) // Pre-Spurious Dragon: always charge for new account // Post-Spurious Dragon: only charge if value is transferred - if !is_spurioud_dragon || transfers_value { + if !is_spurious_dragon || transfers_value { return NEWACCOUNT; } 0 From ff1eb09736ec50d438935877a74e92e6cec20b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wojtek=20=C5=81opata?= Date: Fri, 17 Oct 2025 12:38:32 +0200 Subject: [PATCH 006/127] fix: return MemoryLimitOOG when memory_limit is enabled (#3109) --- crates/interpreter/src/instructions/macros.rs | 5 ++ crates/interpreter/src/interpreter.rs | 82 +++++++++++++++++++ .../src/interpreter/shared_memory.rs | 19 +++-- crates/interpreter/src/interpreter_types.rs | 7 +- 4 files changed, 104 insertions(+), 9 deletions(-) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index a37e3b7d34..7e675dc74c 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -132,6 +132,11 @@ macro_rules! resize_memory { $crate::resize_memory!($interpreter, $offset, $len, ()) }; ($interpreter:expr, $offset:expr, $len:expr, $ret:expr) => { + #[cfg(feature = "memory_limit")] + if $interpreter.memory.limit_reached($offset, $len) { + $interpreter.halt_memory_limit_oog(); + return $ret; + } if !$crate::interpreter::resize_memory( &mut $interpreter.gas, &mut $interpreter.memory, diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index efa72aa9f7..3eeb6f10b0 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -233,6 +233,13 @@ impl Interpreter { #[cold] #[inline(never)] pub fn halt_memory_oog(&mut self) { + self.halt(InstructionResult::MemoryOOG); + } + + /// Halt the interpreter with an out-of-gas error. + #[cold] + #[inline(never)] + pub fn halt_memory_limit_oog(&mut self) { self.halt(InstructionResult::MemoryLimitOOG); } @@ -431,3 +438,78 @@ mod tests { ); } } + +#[test] +fn test_mstore_big_offset_memory_oog() { + use super::*; + use crate::{host::DummyHost, instructions::instruction_table}; + use bytecode::Bytecode; + use primitives::Bytes; + + let code = Bytes::from( + &[ + 0x60, 0x00, // PUSH1 0x00 + 0x61, 0x27, 0x10, // PUSH2 0x2710 (10,000) + 0x52, // MSTORE + 0x00, // STOP + ][..], + ); + let bytecode = Bytecode::new_raw(code); + + let mut interpreter = Interpreter::::new( + SharedMemory::new(), + ExtBytecode::new(bytecode), + InputsImpl::default(), + false, + SpecId::default(), + 1000, + ); + + let table = instruction_table::(); + let mut host = DummyHost; + let action = interpreter.run_plain(&table, &mut host); + + assert!(action.is_return()); + assert_eq!( + action.instruction_result(), + Some(InstructionResult::MemoryOOG) + ); +} + +#[test] +#[cfg(feature = "memory_limit")] +fn test_mstore_big_offset_memory_limit_oog() { + use super::*; + use crate::{host::DummyHost, instructions::instruction_table}; + use bytecode::Bytecode; + use primitives::Bytes; + + let code = Bytes::from( + &[ + 0x60, 0x00, // PUSH1 0x00 + 0x61, 0x27, 0x10, // PUSH2 0x2710 (10,000) + 0x52, // MSTORE + 0x00, // STOP + ][..], + ); + let bytecode = Bytecode::new_raw(code); + + let mut interpreter = Interpreter::::new( + SharedMemory::new_with_memory_limit(1000), + ExtBytecode::new(bytecode), + InputsImpl::default(), + false, + SpecId::default(), + 100000, + ); + + let table = instruction_table::(); + let mut host = DummyHost; + let action = interpreter.run_plain(&table, &mut host); + + assert!(action.is_return()); + assert_eq!( + action.instruction_result(), + Some(InstructionResult::MemoryLimitOOG) + ); +} diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index 6eb28741a4..deb0ffcd5e 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -125,6 +125,17 @@ impl MemoryTr for SharedMemory { self.resize(new_size); true } + + /// Returns `true` if the `new_size` for the current context memory will + /// make the shared buffer length exceed the `memory_limit`. + #[cfg(feature = "memory_limit")] + #[inline] + fn limit_reached(&self, offset: usize, len: usize) -> bool { + self.my_checkpoint + .saturating_add(offset) + .saturating_add(len) as u64 + > self.memory_limit + } } impl SharedMemory { @@ -200,14 +211,6 @@ impl SharedMemory { self.buffer().dbg_borrow_mut() } - /// Returns `true` if the `new_size` for the current context memory will - /// make the shared buffer length exceed the `memory_limit`. - #[cfg(feature = "memory_limit")] - #[inline] - pub fn limit_reached(&self, new_size: usize) -> bool { - self.my_checkpoint.saturating_add(new_size) as u64 > self.memory_limit - } - /// Prepares the shared memory for a new child context. /// /// # Panics diff --git a/crates/interpreter/src/interpreter_types.rs b/crates/interpreter/src/interpreter_types.rs index 0b1540a26e..3478be4ea2 100644 --- a/crates/interpreter/src/interpreter_types.rs +++ b/crates/interpreter/src/interpreter_types.rs @@ -144,8 +144,13 @@ pub trait MemoryTr { /// /// # Note /// - /// It checks memory limits. + /// It checks if the memory allocation fits under gas cap. fn resize(&mut self, new_size: usize) -> bool; + + /// Returns `true` if the `new_size` for the current context memory will + /// make the shared buffer length exceed the `memory_limit`. + #[cfg(feature = "memory_limit")] + fn limit_reached(&self, offset: usize, len: usize) -> bool; } /// Functions needed for Interpreter Stack operations. From 5d0c77ea7d6fff30f48249788b749f3af8800931 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 17 Oct 2025 16:04:46 +0200 Subject: [PATCH 007/127] feat: Optional Bytecode in CallInput (#3110) * feat: Optional Bytecode in CallInput * fmt --- crates/handler/src/execution.rs | 5 ++--- crates/handler/src/frame.rs | 16 ++++++++++++++-- crates/interpreter/src/instructions/contract.rs | 12 ++++-------- .../src/interpreter_action/call_inputs.rs | 8 ++++---- 4 files changed, 24 insertions(+), 17 deletions(-) diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index aecda06d20..e79f9d4b4c 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -17,14 +17,13 @@ pub fn create_init_frame( match tx.kind() { TxKind::Call(target_address) => { - let (bytecode, bytecode_hash) = bytecode.unwrap_or_default(); + let known_bytecode = bytecode.map(|(code, hash)| (hash, code)); FrameInput::Call(Box::new(CallInputs { input: CallInput::Bytes(input), gas_limit, target_address, bytecode_address: target_address, - bytecode, - bytecode_hash, + known_bytecode, caller: tx.caller(), value: CallValue::Transfer(tx.value()), scheme: CallScheme::Call, diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index df97956023..ed71b69038 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -201,8 +201,20 @@ impl EthFrame { }))); } - let bytecode = inputs.bytecode.clone(); - let bytecode_hash = inputs.bytecode_hash; + // Get bytecode and hash - either from known_bytecode or load from account + let (bytecode, bytecode_hash) = if let Some((hash, code)) = inputs.known_bytecode.clone() { + // Use provided bytecode and hash + (code, hash) + } else { + // Load account and get its bytecode + let account = ctx + .journal_mut() + .load_account_code(inputs.bytecode_address)?; + ( + account.info.code.clone().unwrap_or_default(), + account.info.code_hash, + ) + }; // Returns success if bytecode is empty. if bytecode.is_empty() { diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index e3137ff04b..22a36f6629 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -144,8 +144,7 @@ pub fn call( target_address: to, caller: context.interpreter.input.target_address(), bytecode_address: to, - bytecode, - bytecode_hash, + known_bytecode: Some((bytecode_hash, bytecode)), value: CallValue::Transfer(value), scheme: CallScheme::Call, is_static: context.interpreter.runtime_flag.is_static(), @@ -188,8 +187,7 @@ pub fn call_code( target_address: context.interpreter.input.target_address(), caller: context.interpreter.input.target_address(), bytecode_address: to, - bytecode, - bytecode_hash, + known_bytecode: Some((bytecode_hash, bytecode)), value: CallValue::Transfer(value), scheme: CallScheme::CallCode, is_static: context.interpreter.runtime_flag.is_static(), @@ -232,8 +230,7 @@ pub fn delegate_call( target_address: context.interpreter.input.target_address(), caller: context.interpreter.input.caller_address(), bytecode_address: to, - bytecode, - bytecode_hash, + known_bytecode: Some((bytecode_hash, bytecode)), value: CallValue::Apparent(context.interpreter.input.call_value()), scheme: CallScheme::DelegateCall, is_static: context.interpreter.runtime_flag.is_static(), @@ -276,8 +273,7 @@ pub fn static_call( target_address: to, caller: context.interpreter.input.target_address(), bytecode_address: to, - bytecode, - bytecode_hash, + known_bytecode: Some((bytecode_hash, bytecode)), value: CallValue::Transfer(U256::ZERO), scheme: CallScheme::StaticCall, is_static: true, diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index 581bc15c95..e7224607cf 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -79,10 +79,10 @@ pub struct CallInputs { /// /// Previously `context.code_address`. pub bytecode_address: Address, - /// Bytecode that is going to be executed. - pub bytecode: Bytecode, - /// Bytecode hash, - pub bytecode_hash: B256, + /// Known bytecode and its hash. + /// If None, bytecode will be loaded from the account at `bytecode_address`. + /// If Some((hash, bytecode)), the provided bytecode and hash will be used. + pub known_bytecode: Option<(B256, Bytecode)>, /// Target address, this account storage is going to be modified. /// /// Previously `context.address`. From 539f1d36a50ade968ce8215d3f39ce290999bad8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 17 Oct 2025 16:50:11 +0200 Subject: [PATCH 008/127] chore: release (#3108) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 14 +++++++------- Cargo.toml | 12 ++++++------ bins/revme/CHANGELOG.md | 6 ++++++ bins/revme/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 6 ++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 6 ++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 14 ++++++++++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 6 ++++++ crates/op-revm/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 6 ++++++ crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 6 ++++++ crates/statetest-types/Cargo.toml | 2 +- 16 files changed, 70 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d77cf65ec9..41acfe4fe4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "11.1.2" +version = "11.1.3" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "30.1.2" +version = "30.1.3" dependencies = [ "revm-bytecode", "revm-context", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "11.1.2" +version = "11.2.0" dependencies = [ "alloy-eip7702", "alloy-provider", @@ -3658,7 +3658,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "11.1.2" +version = "11.1.3" dependencies = [ "auto_impl", "either", @@ -3675,7 +3675,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "27.0.2" +version = "28.0.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3735,7 +3735,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "10.1.2" +version = "10.1.3" dependencies = [ "alloy-eips", "k256", @@ -3747,7 +3747,7 @@ dependencies = [ [[package]] name = "revme" -version = "8.2.2" +version = "8.2.3" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index a165e7a4ca..b08203400a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "30.1.2", default-features = false } +revm = { path = "crates/revm", version = "30.1.3", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.1", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.0.2", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.2", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.3", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.0.2", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "27.0.2", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.1.2", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "28.0.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.1.3", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "28.1.1", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.1.2", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.1.3", default-features = false } context = { path = "crates/context", package = "revm-context", version = "10.1.2", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "11.1.2", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "11.1.2", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.1.2", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "11.2.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.1.3", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index bde007d34c..b95ff2dcf6 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.2.3](https://github.com/bluealloy/revm/compare/revme-v8.2.2...revme-v8.2.3) - 2025-10-17 + +### Other + +- updated the following local packages: revm-inspector, revm, revm-statetest-types + ## [8.2.2](https://github.com/bluealloy/revm/compare/revme-v8.2.1...revme-v8.2.2) - 2025-10-15 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index f56ef11e49..04860de281 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "8.2.2" +version = "8.2.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index a875f89397..12c47d51cf 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.2.0](https://github.com/bluealloy/revm/compare/revm-handler-v11.1.2...revm-handler-v11.2.0) - 2025-10-17 + +### Added + +- Optional Bytecode in CallInput ([#3110](https://github.com/bluealloy/revm/pull/3110)) + ## [11.1.2](https://github.com/bluealloy/revm/compare/revm-handler-v11.1.1...revm-handler-v11.1.2) - 2025-10-15 ### Other diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 9ee503bc2d..b774f6ef08 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "11.1.2" +version = "11.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index ef3f4851b8..930d2c7c70 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.3](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.2...revm-inspector-v11.1.3) - 2025-10-17 + +### Other + +- updated the following local packages: revm-interpreter, revm-handler + ## [11.1.2](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.1...revm-inspector-v11.1.2) - 2025-10-15 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index b9faafa743..07eef91ee2 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "11.1.2" +version = "11.1.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index a8a6111b39..63f77521d8 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -51,6 +51,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [28.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v27.0.2...revm-interpreter-v28.0.0) - 2025-10-17 + +### Added + +- Optional Bytecode in CallInput ([#3110](https://github.com/bluealloy/revm/pull/3110)) + +### Fixed + +- return MemoryLimitOOG when memory_limit is enabled ([#3109](https://github.com/bluealloy/revm/pull/3109)) + +### Other + +- *(instructions)* fix typo in spurious_dragon variable ([#3106](https://github.com/bluealloy/revm/pull/3106)) + ## [27.0.2](https://github.com/bluealloy/revm/compare/revm-interpreter-v27.0.1...revm-interpreter-v27.0.2) - 2025-10-15 ### Other diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index b07f7f1697..faae0394c6 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "27.0.2" +version = "28.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 07b0d79137..3d2a7f661f 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.3](https://github.com/bluealloy/revm/compare/op-revm-v11.1.2...op-revm-v11.1.3) - 2025-10-17 + +### Other + +- updated the following local packages: revm + ## [11.1.2](https://github.com/bluealloy/revm/compare/op-revm-v11.1.1...op-revm-v11.1.2) - 2025-10-15 ### Other diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 10ac297692..7a2d00a792 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "11.1.2" +version = "11.1.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index fc2d908d07..655a4112eb 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [30.1.3](https://github.com/bluealloy/revm/compare/revm-v30.1.2...revm-v30.1.3) - 2025-10-17 + +### Other + +- updated the following local packages: revm-interpreter, revm-handler, revm-inspector + ## [30.1.2](https://github.com/bluealloy/revm/compare/revm-v30.1.1...revm-v30.1.2) - 2025-10-15 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 590e38cba7..6c3c105702 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "30.1.2" +version = "30.1.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index e2ad81252c..39c1fdd428 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.1.3](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.2...revm-statetest-types-v10.1.3) - 2025-10-17 + +### Other + +- updated the following local packages: revm + ## [10.1.2](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.1...revm-statetest-types-v10.1.2) - 2025-10-15 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index dca2dbaa87..dba0602863 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "10.1.2" +version = "10.1.3" authors.workspace = true edition.workspace = true keywords.workspace = true From 0f4aebc67f28621d36c5ca757d983da6986b59d2 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 17 Oct 2025 19:49:48 +0200 Subject: [PATCH 009/127] bump: tag v93 revm v30.1.0 (#3112) --- CHANGELOG.md | 16 ++++++++++++++++ Cargo.lock | 10 +++++----- Cargo.toml | 8 ++++---- bins/revme/CHANGELOG.md | 2 +- bins/revme/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 2 +- crates/op-revm/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 2 +- crates/statetest-types/Cargo.toml | 2 +- 13 files changed, 35 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0913245f2..d78c5c1437 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v93 +date: 17.10.2025 + +Small release with one breaking change. Bytecode in CallInput is now optional + +* `revm-interpreter`: 27.0.2 -> 28.0.0 (⚠ API breaking changes) +* `revm-handler`: 11.1.2 -> 11.2.0 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-inspector`: 11.1.2 -> 11.1.3 +* `revm`: 30.1.2 -> 30.1.3 +* `revm-statetest-types`: 10.1.2 -> 10.1.3 +* `revme`: 8.2.2 -> 8.2.3 +* `op-revm`: 11.1.2 -> 11.1.3 + +revm-handler revm-inspector revm revm-statetest-types revme op-revm + # v92 date 15.10.2025 diff --git a/Cargo.lock b/Cargo.lock index 41acfe4fe4..f254c9dd81 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "11.1.3" +version = "11.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "30.1.3" +version = "30.2.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3658,7 +3658,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "11.1.3" +version = "11.2.0" dependencies = [ "auto_impl", "either", @@ -3735,7 +3735,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "10.1.3" +version = "10.2.0" dependencies = [ "alloy-eips", "k256", @@ -3747,7 +3747,7 @@ dependencies = [ [[package]] name = "revme" -version = "8.2.3" +version = "8.3.0" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index b08203400a..10d511308c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "30.1.3", default-features = false } +revm = { path = "crates/revm", version = "30.2.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.1", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.0.2", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.2", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.3", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.0.2", default-features = false } interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "28.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.1.3", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.2.0", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "28.1.1", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.1.3", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.2.0", default-features = false } context = { path = "crates/context", package = "revm-context", version = "10.1.2", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "11.1.2", default-features = false } handler = { path = "crates/handler", package = "revm-handler", version = "11.2.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.1.3", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.2.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index b95ff2dcf6..76741cdceb 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [8.2.3](https://github.com/bluealloy/revm/compare/revme-v8.2.2...revme-v8.2.3) - 2025-10-17 +## [8.3.0](https://github.com/bluealloy/revm/compare/revme-v8.2.2...revme-v8.3.0) - 2025-10-17 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 04860de281..474f589d02 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "8.2.3" +version = "8.3.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 930d2c7c70..6a4394c222 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [11.1.3](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.2...revm-inspector-v11.1.3) - 2025-10-17 +## [11.2.0](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.2...revm-inspector-v11.2.0) - 2025-10-17 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 07eef91ee2..82d59056f2 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "11.1.3" +version = "11.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 3d2a7f661f..75a997848c 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [11.1.3](https://github.com/bluealloy/revm/compare/op-revm-v11.1.2...op-revm-v11.1.3) - 2025-10-17 +## [11.2.0](https://github.com/bluealloy/revm/compare/op-revm-v11.1.2...op-revm-v11.2.0) - 2025-10-17 ### Other diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 7a2d00a792..c952cb4e57 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "11.1.3" +version = "11.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 655a4112eb..fed5061f54 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [30.1.3](https://github.com/bluealloy/revm/compare/revm-v30.1.2...revm-v30.1.3) - 2025-10-17 +## [30.2.0](https://github.com/bluealloy/revm/compare/revm-v30.1.2...revm-v30.2.0) - 2025-10-17 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 6c3c105702..6f3f76c85d 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "30.1.3" +version = "30.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 39c1fdd428..43e85bac0f 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [10.1.3](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.2...revm-statetest-types-v10.1.3) - 2025-10-17 +## [10.2.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.2...revm-statetest-types-v10.2.0) - 2025-10-17 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index dba0602863..8a6aac680f 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "10.1.3" +version = "10.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true From 283d5a968a8dcad324d551785e35de21ac281965 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 17 Oct 2025 20:00:17 +0200 Subject: [PATCH 010/127] chore: journal transfer fn cleanup (#3085) * chore: journal transfer fn cleanup * reintroduce caller touch * Update crates/context/src/journal/inner.rs Co-authored-by: Arsenii Kulikov --------- Co-authored-by: Arsenii Kulikov --- crates/context/src/journal/inner.rs | 36 ++--------------------------- 1 file changed, 2 insertions(+), 34 deletions(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 05162e370e..3b98d3fd24 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -343,8 +343,7 @@ impl JournalInner { // sub balance from let from_account = self.state.get_mut(&from).unwrap(); - // no need to touch caller account. - // Self::touch_account(&mut self.journal, from, from_account); + Self::touch_account(&mut self.journal, from, from_account); let from_balance = &mut from_account.info.balance; let Some(from_balance_decr) = from_balance.checked_sub(balance) else { return Some(TransferError::OutOfFunds); @@ -377,40 +376,9 @@ impl JournalInner { to: Address, balance: U256, ) -> Result, DB::Error> { - if balance.is_zero() { - self.load_account(db, to)?; - let to_account = self.state.get_mut(&to).unwrap(); - Self::touch_account(&mut self.journal, to, to_account); - return Ok(None); - } - // load accounts self.load_account(db, from)?; self.load_account(db, to)?; - - // sub balance from - let from_account = self.state.get_mut(&from).unwrap(); - Self::touch_account(&mut self.journal, from, from_account); - let from_balance = &mut from_account.info.balance; - - let Some(from_balance_decr) = from_balance.checked_sub(balance) else { - return Ok(Some(TransferError::OutOfFunds)); - }; - *from_balance = from_balance_decr; - - // add balance to - let to_account = &mut self.state.get_mut(&to).unwrap(); - Self::touch_account(&mut self.journal, to, to_account); - let to_balance = &mut to_account.info.balance; - let Some(to_balance_incr) = to_balance.checked_add(balance) else { - // Overflow of U256 balance is not possible to happen on mainnet. We don't bother to return funds from from_acc. - return Ok(Some(TransferError::OverflowPayment)); - }; - *to_balance = to_balance_incr; - - self.journal - .push(ENTRY::balance_transfer(from, to, balance)); - - Ok(None) + Ok(self.transfer_loaded(from, to, balance)) } /// Creates account or returns false if collision is detected. From f061bf374bf8edf56be432c9c86cce5f5f8836e2 Mon Sep 17 00:00:00 2001 From: Galoretka Date: Fri, 17 Oct 2025 21:02:21 +0300 Subject: [PATCH 011/127] chore(inspector): remove redundant EthInterpreter import in either.rs (#3093) * chore(inspector): remove redundant EthInterpreter import in either.rs * fmt --- crates/inspector/src/either.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/inspector/src/either.rs b/crates/inspector/src/either.rs index 7b4da7249b..239d76bb38 100644 --- a/crates/inspector/src/either.rs +++ b/crates/inspector/src/either.rs @@ -101,8 +101,6 @@ mod tests { #[test] fn test_either_inspector_type_check() { - use interpreter::interpreter::EthInterpreter; - // This test verifies that Either // implements the Inspector trait as required by the issue fn _requires_inspector>(inspector: T) -> T { From e9875b4db0d40e056caeff3eefb8e047ad4ab68c Mon Sep 17 00:00:00 2001 From: Skylar Ray <137945430+sky-coderay@users.noreply.github.com> Date: Fri, 17 Oct 2025 21:04:38 +0300 Subject: [PATCH 012/127] fix(op-revm): add missing enveloped_tx validation in validate_env (#3094) * fix(op-revm): add missing enveloped_tx validation in validate_env * cargo fmt --- crates/op-revm/src/handler.rs | 29 +++++++++++++++++++++++++ crates/op-revm/src/transaction/error.rs | 17 ++++++++++++++- 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 98c054f467..e94f3049c9 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -88,6 +88,12 @@ where } return Ok(()); } + + // Check that non-deposit transactions have enveloped_tx set + if tx.enveloped_tx().is_none() { + return Err(OpTransactionError::MissingEnvelopedTx.into()); + } + self.mainnet.validate_env(evm) } @@ -1500,4 +1506,27 @@ mod tests { 0 ); } + + #[test] + fn test_validate_missing_enveloped_tx() { + use crate::transaction::deposit::DepositTransactionParts; + + // Create a non-deposit transaction without enveloped_tx + let ctx = Context::op().with_tx(OpTransaction { + base: TxEnv::builder().build_fill(), + enveloped_tx: None, // Missing enveloped_tx for non-deposit transaction + deposit: DepositTransactionParts::default(), // No source_hash means non-deposit + }); + + let mut evm = ctx.build_op(); + let handler = + OpHandler::<_, EVMError<_, OpTransactionError>, EthFrame>::new(); + + assert_eq!( + handler.validate_env(&mut evm), + Err(EVMError::Transaction( + OpTransactionError::MissingEnvelopedTx + )) + ); + } } diff --git a/crates/op-revm/src/transaction/error.rs b/crates/op-revm/src/transaction/error.rs index ba13cab90e..ad28175ee2 100644 --- a/crates/op-revm/src/transaction/error.rs +++ b/crates/op-revm/src/transaction/error.rs @@ -41,6 +41,11 @@ pub enum OpTransactionError { /// are cause for non-inclusion, so a special [OpHaltReason][crate::OpHaltReason] variant was introduced to handle this /// case for failed deposit transactions. HaltedDepositPostRegolith, + /// Missing enveloped transaction bytes for non-deposit transaction. + /// + /// Non-deposit transactions on Optimism must have `enveloped_tx` field set + /// to properly calculate L1 costs. + MissingEnvelopedTx, } impl TransactionError for OpTransactionError {} @@ -61,6 +66,12 @@ impl Display for OpTransactionError { "deposit transaction halted post-regolith; error will be bubbled up to main return handler" ) } + Self::MissingEnvelopedTx => { + write!( + f, + "missing enveloped transaction bytes for non-deposit transaction" + ) + } } } } @@ -98,7 +109,11 @@ mod test { assert_eq!( OpTransactionError::HaltedDepositPostRegolith.to_string(), "deposit transaction halted post-regolith; error will be bubbled up to main return handler" - ) + ); + assert_eq!( + OpTransactionError::MissingEnvelopedTx.to_string(), + "missing enveloped transaction bytes for non-deposit transaction" + ); } #[cfg(feature = "serde")] From 54dcc6de3da11c8d780c6b13fcc7d9da156bb575 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 18 Oct 2025 02:12:42 +0800 Subject: [PATCH 013/127] chore: typo eip4788 (#3111) --- bins/revme/src/cmd/blockchaintest/pre_block.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest/pre_block.rs b/bins/revme/src/cmd/blockchaintest/pre_block.rs index b3611cbbd6..11d7dc0cc2 100644 --- a/bins/revme/src/cmd/blockchaintest/pre_block.rs +++ b/bins/revme/src/cmd/blockchaintest/pre_block.rs @@ -32,7 +32,7 @@ pub fn pre_block_transition< } if let Some(parent_beacon_block_root) = parent_beacon_block_root { - system_call_eip4844_beacon_root(spec, parent_beacon_block_root, evm); + system_call_eip4788_beacon_root(spec, parent_beacon_block_root, evm); } } @@ -62,7 +62,7 @@ pub(crate) fn system_call_eip2935_blockhash( pub const BEACON_ROOTS_ADDRESS: Address = address!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); /// Beacon root system call EIP-4788 -pub(crate) fn system_call_eip4844_beacon_root( +pub(crate) fn system_call_eip4788_beacon_root( spec: SpecId, parent_beacon_block_root: B256, evm: &mut impl SystemCallCommitEvm, From 5c0be133ff8f6a21c1da5399841a0f2cd281d174 Mon Sep 17 00:00:00 2001 From: "fuder.eth" Date: Fri, 17 Oct 2025 21:14:43 +0300 Subject: [PATCH 014/127] Update blockchaintest.rs (#3107) --- bins/revme/src/cmd/blockchaintest.rs | 34 ++++++++++++---------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 009c299c62..9d8b69ad4f 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -389,26 +389,22 @@ fn validate_post_state( } } - // Check for unexpected storage entries - for (slot, actual_value) in actual_account - .account - .as_ref() - .map(|a| &a.storage) - .unwrap_or(&HashMap::new()) - .iter() - { - let slot = *slot; - let actual_value = *actual_value; - if !expected_account.storage.contains_key(&slot) && !actual_value.is_zero() { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); + // Check for unexpected storage entries. Avoid allocating a temporary HashMap when the account is None. + if let Some(acc) = actual_account.account.as_ref() { + for (slot, actual_value) in &acc.storage { + let slot = *slot; + let actual_value = *actual_value; + if !expected_account.storage.contains_key(&slot) && !actual_value.is_zero() { + if print_env_on_error { + print_error_with_state(debug_info, state, Some(expected_post_state)); + } + return Err(TestExecutionError::PostStateValidation { + address: *address, + field: format!("storage_unexpected[{slot}]"), + expected: "0x0".to_string(), + actual: format!("{actual_value}"), + }); } - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: format!("storage_unexpected[{slot}]"), - expected: "0x0".to_string(), - actual: format!("{actual_value}"), - }); } } From 273ddf3d327a5d1d6bae0b025a95334b442ed526 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 17 Oct 2025 20:15:04 +0200 Subject: [PATCH 015/127] chore: consolidate revme imports (#3088) --- Cargo.lock | 8 ------- bins/revme/Cargo.toml | 18 +++++++------- bins/revme/src/cmd/bench/analysis.rs | 4 ++-- bins/revme/src/cmd/bench/burntpix.rs | 6 ++--- .../revme/src/cmd/bench/gas_cost_estimator.rs | 4 ++-- bins/revme/src/cmd/bench/snailtracer.rs | 7 +++--- bins/revme/src/cmd/bench/transfer.rs | 4 ++-- bins/revme/src/cmd/bench/transfer_multi.rs | 6 ++--- bins/revme/src/cmd/blockchaintest.rs | 24 +++++++++---------- .../src/cmd/blockchaintest/post_block.rs | 11 +++++---- .../revme/src/cmd/blockchaintest/pre_block.rs | 11 +++++---- bins/revme/src/cmd/evmrunner.rs | 6 ++--- bins/revme/src/cmd/statetest/merkle_trie.rs | 6 +++-- bins/revme/src/cmd/statetest/runner.rs | 8 +++---- crates/revm/Cargo.toml | 3 +++ 15 files changed, 65 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f254c9dd81..860315e298 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3759,14 +3759,6 @@ dependencies = [ "k256", "plain_hasher", "revm", - "revm-bytecode", - "revm-context", - "revm-context-interface", - "revm-database", - "revm-database-interface", - "revm-inspector", - "revm-primitives", - "revm-state", "revm-statetest-types", "serde", "serde_json", diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 474f589d02..a1a7a10e32 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -11,16 +11,16 @@ rust-version.workspace = true [dependencies] # revm -revm = { workspace = true, features = ["std", "hashbrown", "c-kzg", "blst"] } -primitives.workspace = true -database.workspace = true -database-interface.workspace = true -state.workspace = true -bytecode = { workspace = true, features = ["std", "parse"] } -context.workspace = true -context-interface.workspace = true -inspector = { workspace = true, features = ["std", "tracer"] } +revm = { workspace = true, features = [ + "std", + "c-kzg", + "blst", + "tracer", + "parse", +] } statetest-types.workspace = true + +# criterion criterion.workspace = true # alloy diff --git a/bins/revme/src/cmd/bench/analysis.rs b/bins/revme/src/cmd/bench/analysis.rs index e12bc97e96..816d5ea83b 100644 --- a/bins/revme/src/cmd/bench/analysis.rs +++ b/bins/revme/src/cmd/bench/analysis.rs @@ -1,8 +1,8 @@ -use context::TxEnv; use criterion::Criterion; -use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; use revm::{ bytecode::Bytecode, + context::TxEnv, + database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}, primitives::{bytes, hex, Bytes, TxKind}, Context, ExecuteEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index ba7a14f85f..bbeaee7de5 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -1,8 +1,6 @@ pub mod static_data; -use context::TxEnv; use criterion::Criterion; -use primitives::{StorageKey, StorageValue}; use static_data::{ BURNTPIX_ADDRESS_ONE, BURNTPIX_ADDRESS_THREE, BURNTPIX_ADDRESS_TWO, BURNTPIX_BYTECODE_FOUR, BURNTPIX_BYTECODE_ONE, BURNTPIX_BYTECODE_THREE, BURNTPIX_BYTECODE_TWO, BURNTPIX_MAIN_ADDRESS, @@ -10,10 +8,12 @@ use static_data::{ }; use alloy_sol_types::{sol, SolCall}; -use database::{CacheDB, BENCH_CALLER}; use revm::{ + context::TxEnv, + database::{CacheDB, BENCH_CALLER}, database_interface::EmptyDB, primitives::{hex, keccak256, Address, Bytes, TxKind, B256, U256}, + primitives::{StorageKey, StorageValue}, state::{AccountInfo, Bytecode}, Context, ExecuteEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/bench/gas_cost_estimator.rs b/bins/revme/src/cmd/bench/gas_cost_estimator.rs index 06db3292a5..26d889233c 100644 --- a/bins/revme/src/cmd/bench/gas_cost_estimator.rs +++ b/bins/revme/src/cmd/bench/gas_cost_estimator.rs @@ -1,8 +1,8 @@ -use context::TxEnv; use criterion::Criterion; -use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; use revm::{ bytecode::Bytecode, + context::TxEnv, + database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}, primitives::{hex, Bytes, TxKind}, Context, ExecuteEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/bench/snailtracer.rs b/bins/revme/src/cmd/bench/snailtracer.rs index d0a0bf5f4e..222a7ecc7d 100644 --- a/bins/revme/src/cmd/bench/snailtracer.rs +++ b/bins/revme/src/cmd/bench/snailtracer.rs @@ -1,9 +1,10 @@ -use context::TxEnv; use criterion::Criterion; -use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; -use inspector::NoOpInspector; + use revm::{ bytecode::Bytecode, + context::TxEnv, + database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}, + inspector::NoOpInspector, primitives::{bytes, hex, Bytes, TxKind}, Context, ExecuteEvm, InspectEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index ac196dfe97..717cc5f8c4 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -1,9 +1,9 @@ -use context::{ContextTr, TxEnv}; use criterion::Criterion; -use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET, BENCH_TARGET_BALANCE}; use revm::{ bytecode::Bytecode, + context::{ContextTr, TxEnv}, context_interface::JournalTr, + database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET, BENCH_TARGET_BALANCE}, primitives::{TxKind, U256}, Context, ExecuteEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/bench/transfer_multi.rs b/bins/revme/src/cmd/bench/transfer_multi.rs index d22c467677..7312db41f9 100644 --- a/bins/revme/src/cmd/bench/transfer_multi.rs +++ b/bins/revme/src/cmd/bench/transfer_multi.rs @@ -1,12 +1,12 @@ -use context::TxEnv; use criterion::Criterion; -use database::{InMemoryDB, BENCH_CALLER, BENCH_TARGET}; use revm::{ + context::TxEnv, + database::{InMemoryDB, BENCH_CALLER, BENCH_TARGET}, interpreter::instructions::utility::IntoAddress, primitives::{TxKind, U256}, + state::AccountInfo, Context, ExecuteCommitEvm, ExecuteEvm, MainBuilder, MainContext, }; -use state::AccountInfo; pub fn run(criterion: &mut Criterion) { let mut db = InMemoryDB::default(); diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 9d8b69ad4f..763aeaf122 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -2,19 +2,19 @@ pub mod post_block; pub mod pre_block; use clap::Parser; -use context::ContextTr; -use context_interface::block::BlobExcessGasAndPrice; -use database::states::bundle_state::BundleRetention; -use database::{EmptyDB, State}; -use inspector::inspectors::TracerEip3155; -use primitives::{hardfork::SpecId, hex, Address, HashMap, U256}; -use revm::handler::EvmTr; + use revm::{ - context::cfg::CfgEnv, context_interface::result::HaltReason, Context, MainBuilder, MainContext, + bytecode::Bytecode, + context::{cfg::CfgEnv, ContextTr}, + context_interface::{block::BlobExcessGasAndPrice, result::HaltReason}, + database::{states::bundle_state::BundleRetention, EmptyDB, State}, + handler::EvmTr, + inspector::inspectors::TracerEip3155, + primitives::{hardfork::SpecId, hex, Address, HashMap, U256}, + state::AccountInfo, + Context, Database, ExecuteCommitEvm, ExecuteEvm, InspectEvm, MainBuilder, MainContext, }; -use revm::{Database, ExecuteCommitEvm, ExecuteEvm, InspectEvm}; use serde_json::json; -use state::AccountInfo; use statetest_types::blockchain::{ Account, BlockchainTest, BlockchainTestCase, ForkSpec, Withdrawal, }; @@ -657,8 +657,8 @@ fn execute_blockchain_test( let account_info = AccountInfo { balance: account.balance, nonce: account.nonce, - code_hash: primitives::keccak256(&account.code), - code: Some(bytecode::Bytecode::new_raw(account.code.clone())), + code_hash: revm::primitives::keccak256(&account.code), + code: Some(Bytecode::new_raw(account.code.clone())), }; // Store for debug info diff --git a/bins/revme/src/cmd/blockchaintest/post_block.rs b/bins/revme/src/cmd/blockchaintest/post_block.rs index 4c85d9b0ee..f768e389e1 100644 --- a/bins/revme/src/cmd/blockchaintest/post_block.rs +++ b/bins/revme/src/cmd/blockchaintest/post_block.rs @@ -1,7 +1,10 @@ -use context::{Block, ContextTr}; -use database::State; -use primitives::{hardfork::SpecId, ONE_ETHER, ONE_GWEI}; -use revm::{handler::EvmTr, Database, SystemCallCommitEvm}; +use revm::{ + context::{Block, ContextTr}, + database::State, + handler::EvmTr, + primitives::{hardfork::SpecId, ONE_ETHER, ONE_GWEI}, + Database, SystemCallCommitEvm, +}; use statetest_types::blockchain::Withdrawal; /// Post block transition that includes: diff --git a/bins/revme/src/cmd/blockchaintest/pre_block.rs b/bins/revme/src/cmd/blockchaintest/pre_block.rs index 11d7dc0cc2..90fb922740 100644 --- a/bins/revme/src/cmd/blockchaintest/pre_block.rs +++ b/bins/revme/src/cmd/blockchaintest/pre_block.rs @@ -1,9 +1,12 @@ //! Pre block state transition -use context::{Block, ContextTr}; -use database::State; -use primitives::{address, hardfork::SpecId, Address, B256}; -use revm::{handler::EvmTr, Database, SystemCallCommitEvm}; +use revm::{ + context::{Block, ContextTr}, + database::{Database, State}, + handler::EvmTr, + primitives::{address, hardfork::SpecId, Address, B256}, + SystemCallCommitEvm, +}; /// Pre block state transition /// diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 7a626a83fb..7708f7a69f 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -1,9 +1,9 @@ use clap::Parser; -use context::TxEnv; -use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; -use inspector::{inspectors::TracerEip3155, InspectEvm}; use revm::{ bytecode::{Bytecode, BytecodeDecodeError}, + context::TxEnv, + database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}, + inspector::{inspectors::TracerEip3155, InspectEvm}, primitives::{hex, TxKind}, Context, Database, ExecuteEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/statetest/merkle_trie.rs b/bins/revme/src/cmd/statetest/merkle_trie.rs index c6b6418787..b8af986d7a 100644 --- a/bins/revme/src/cmd/statetest/merkle_trie.rs +++ b/bins/revme/src/cmd/statetest/merkle_trie.rs @@ -1,11 +1,13 @@ use std::convert::Infallible; use alloy_rlp::{RlpEncodable, RlpMaxEncodedLen}; -use context::result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}; -use database::{EmptyDB, PlainAccount, State}; use hash_db::Hasher; use plain_hasher::PlainHasher; use revm::primitives::{keccak256, Address, Log, B256, U256}; +use revm::{ + context::result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, + database::{EmptyDB, PlainAccount, State}, +}; use triehash::sec_trie_root; pub struct TestValidationResult { diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 3b517c8214..2ea90806c8 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -1,15 +1,15 @@ use crate::cmd::statetest::merkle_trie::{compute_test_roots, TestValidationResult}; -use database::State; use indicatif::{ProgressBar, ProgressDrawTarget}; -use inspector::{inspectors::TracerEip3155, InspectCommitEvm}; -use primitives::U256; use revm::{ context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv}, context_interface::{ result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, Cfg, }, + database, database_interface::EmptyDB, + inspector::{inspectors::TracerEip3155, InspectCommitEvm}, + primitives::U256, primitives::{hardfork::SpecId, Bytes, B256}, Context, ExecuteCommitEvm, MainBuilder, MainContext, }; @@ -222,7 +222,7 @@ fn check_evm_execution( expected_output: Option<&Bytes>, test_name: &str, exec_result: &Result, EVMError>, - db: &mut State, + db: &mut database::State, spec: SpecId, print_json_outcome: bool, ) -> Result<(), TestErrorKind> { diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 6f3f76c85d..c79b2f9d7f 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -78,6 +78,9 @@ alloydb = ["database/alloydb"] serde-json = ["serde", "inspector/tracer"] tracer = ["inspector/tracer"] +# Enables parsing opcodes from strings. +parse = ["bytecode/parse"] + dev = [ "memory_limit", "optional_balance_check", From ca7a08b798cd22cee4d39bffab539146660a4d92 Mon Sep 17 00:00:00 2001 From: 0xMushow <105550256+0xMushow@users.noreply.github.com> Date: Fri, 17 Oct 2025 20:29:09 +0200 Subject: [PATCH 016/127] chore(precompile): remove unused mainnet_address() function (#3091) * chore(precompile): remove unused mainnet_address() function * nit --- crates/precompile/src/id.rs | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/crates/precompile/src/id.rs b/crates/precompile/src/id.rs index 3adb5f1003..8c4077fee1 100644 --- a/crates/precompile/src/id.rs +++ b/crates/precompile/src/id.rs @@ -1,8 +1,6 @@ use std::borrow::Cow; use std::fmt; -use primitives::{address, Address}; - use crate::{Precompile, PrecompileSpecId}; /// Precompile with address and function. @@ -58,32 +56,6 @@ impl PrecompileId { Self::Custom(id.into()) } - /// Returns the mainnet address for the precompile. - pub fn mainnet_address(&self) -> Option
{ - let address = match self { - Self::EcRec => address!("0x0000000000000000000000000000000000000001"), - Self::Sha256 => address!("0x0000000000000000000000000000000000000002"), - Self::Ripemd160 => address!("0x0000000000000000000000000000000000000003"), - Self::Identity => address!("0x0000000000000000000000000000000000000004"), - Self::ModExp => address!("0x0000000000000000000000000000000000000005"), - Self::Bn254Add => address!("0x0000000000000000000000000000000000000006"), - Self::Bn254Mul => address!("0x0000000000000000000000000000000000000007"), - Self::Bn254Pairing => address!("0x0000000000000000000000000000000000000008"), - Self::Blake2F => address!("0x0000000000000000000000000000000000000009"), - Self::KzgPointEvaluation => address!("0x000000000000000000000000000000000000000A"), - Self::Bls12G1Add => address!("0x000000000000000000000000000000000000000B"), - Self::Bls12G1Msm => address!("0x000000000000000000000000000000000000000C"), - Self::Bls12G2Add => address!("0x000000000000000000000000000000000000000D"), - Self::Bls12G2Msm => address!("0x000000000000000000000000000000000000000E"), - Self::Bls12Pairing => address!("0x000000000000000000000000000000000000000F"), - Self::Bls12MapFpToGp1 => address!("0x0000000000000000000000000000000000000010"), - Self::Bls12MapFp2ToGp2 => address!("0x0000000000000000000000000000000000000011"), - Self::P256Verify => address!("0x0000000000000000000000000000000000000012"), - Self::Custom(_) => return None, - }; - Some(address) - } - /// Returns the name of the precompile as defined in EIP-7910. pub fn name(&self) -> &str { match self { From ee8c7dc6bf21b3cc0310bee4942346240f48be47 Mon Sep 17 00:00:00 2001 From: Ryan Date: Sat, 18 Oct 2025 22:17:00 +0800 Subject: [PATCH 017/127] chore: remove redundant alloy-eip7702 from handler dev-dependencies (#3105) * remove redundant alloy-eip7702 from handler dev-dependencies * cleanup * more clean up * revert wrong ci fix --- Cargo.lock | 1 - crates/handler/Cargo.toml | 3 --- crates/inspector/Cargo.toml | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 860315e298..7ad44be63d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3638,7 +3638,6 @@ dependencies = [ name = "revm-handler" version = "11.2.0" dependencies = [ - "alloy-eip7702", "alloy-provider", "alloy-signer", "alloy-signer-local", diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index b774f6ef08..429c42efa6 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -36,7 +36,6 @@ serde = { workspace = true, optional = true } [dev-dependencies] database.workspace = true -alloy-eip7702.workspace = true alloy-provider.workspace = true alloy-signer.workspace = true alloy-signer-local.workspace = true @@ -45,7 +44,6 @@ alloy-signer-local.workspace = true default = ["std"] std = [ "serde?/std", - "alloy-eip7702/std", "bytecode/std", "context/std", "context-interface/std", @@ -61,7 +59,6 @@ serde = [ "primitives/serde", "state/serde", "context-interface/serde", - "alloy-eip7702/serde", "bytecode/serde", "context/serde", "database/serde", diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 82d59056f2..958b5859cd 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -57,8 +57,8 @@ std = [ ] serde = [ "dep:serde", - "database/serde", "context/serde", + "database/serde", "database-interface/serde", "handler/serde", "interpreter/serde", From e9fca7e30de2ab329c4792a20abf3c6175209efd Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 20 Oct 2025 15:55:24 +0200 Subject: [PATCH 018/127] chore(op): use helper function in validate against state (#3069) --- crates/handler/src/pre_execution.rs | 22 +++++-- crates/op-revm/src/handler.rs | 97 ++++++----------------------- crates/op-revm/src/l1block.rs | 31 ++++++++- examples/erc20_gas/src/handler.rs | 9 +-- 4 files changed, 66 insertions(+), 93 deletions(-) diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 95174ae3c4..5fd5613691 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -65,6 +65,21 @@ pub fn load_accounts< Ok(()) } +/// Validates caller account nonce and code according to EIP-3607. +#[inline] +pub fn validate_account_nonce_and_code_with_components( + caller_info: &mut AccountInfo, + tx: impl Transaction, + cfg: impl Cfg, +) -> Result<(), InvalidTransaction> { + validate_account_nonce_and_code( + caller_info, + tx.nonce(), + cfg.is_eip3607_disabled(), + cfg.is_nonce_check_disabled(), + ) +} + /// Validates caller account nonce and code according to EIP-3607. #[inline] pub fn validate_account_nonce_and_code( @@ -153,12 +168,7 @@ pub fn validate_against_state_and_deduct_caller< // Load caller's account. let caller_account = journal.load_account_code(tx.caller())?.data; - validate_account_nonce_and_code( - &mut caller_account.info, - tx.nonce(), - cfg.is_eip3607_disabled(), - cfg.is_nonce_check_disabled(), - )?; + validate_account_nonce_and_code_with_components(&mut caller_account.info, tx, cfg)?; let new_balance = calculate_caller_fee(caller_account.info.balance, tx, block, cfg)?; diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index e94f3049c9..6aeaaed158 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -16,7 +16,7 @@ use revm::{ evm::FrameTr, handler::EvmTrError, post_execution::{self, reimburse_caller}, - pre_execution::validate_account_nonce_and_code, + pre_execution::{calculate_caller_fee, validate_account_nonce_and_code_with_components}, EthFrame, EvmTr, FrameResult, Handler, MainnetHandler, }, inspector::{Inspector, InspectorEvmTr, InspectorHandler}, @@ -101,19 +101,10 @@ where &self, evm: &mut Self::Evm, ) -> Result<(), Self::Error> { - let ctx = evm.ctx(); - - let basefee = ctx.block().basefee() as u128; - let blob_price = ctx.block().blob_gasprice().unwrap_or_default(); - let is_deposit = ctx.tx().tx_type() == DEPOSIT_TRANSACTION_TYPE; - let spec = ctx.cfg().spec(); - let block_number = ctx.block().number(); - let is_balance_check_disabled = ctx.cfg().is_balance_check_disabled(); - let is_eip3607_disabled = ctx.cfg().is_eip3607_disabled(); - let is_nonce_check_disabled = ctx.cfg().is_nonce_check_disabled(); + let (block, tx, cfg, journal, chain, _) = evm.ctx().all_mut(); + let spec = cfg.spec(); - if is_deposit { - let (block, tx, cfg, journal, _, _) = evm.ctx().all_mut(); + if tx.tx_type() == DEPOSIT_TRANSACTION_TYPE { let basefee = block.basefee() as u128; let blob_price = block.blob_gasprice().unwrap_or_default(); // deposit skips max fee check and just deducts the effective balance spending. @@ -148,87 +139,35 @@ where return Ok(()); } - let mut additional_cost = U256::ZERO; - // L1 block info is stored in the context for later use. // and it will be reloaded from the database if it is not for the current block. - if ctx.chain().l2_block != Some(block_number) { - *ctx.chain_mut() = L1BlockInfo::try_fetch(ctx.db_mut(), block_number, spec)?; + if chain.l2_block != Some(block.number()) { + *chain = L1BlockInfo::try_fetch(journal.db_mut(), block.number(), spec)?; } - if !ctx.cfg().is_fee_charge_disabled() { - // account for additional cost of l1 fee and operator fee - // account for additional cost of l1 fee and operator fee - let Some(enveloped_tx) = ctx.tx().enveloped_tx().cloned() else { - return Err(ERROR::from_string( - "[OPTIMISM] Failed to load enveloped transaction.".into(), - )); - }; - - // compute L1 cost - additional_cost = ctx.chain_mut().calculate_tx_l1_cost(&enveloped_tx, spec); - - // compute operator fee - if spec.is_enabled_in(OpSpecId::ISTHMUS) { - let gas_limit = U256::from(ctx.tx().gas_limit()); - let operator_fee_charge = - ctx.chain() - .operator_fee_charge(&enveloped_tx, gas_limit, spec); - additional_cost = additional_cost.saturating_add(operator_fee_charge); - } - } - - let (tx, journal) = ctx.tx_journal_mut(); - let caller_account = journal.load_account_code(tx.caller())?.data; // validates account nonce and code - validate_account_nonce_and_code( - &mut caller_account.info, - tx.nonce(), - is_eip3607_disabled, - is_nonce_check_disabled, - )?; - - let mut new_balance = caller_account.info.balance; - - // Check if account has enough balance for `gas_limit * max_fee`` and value transfer. - // Transfer will be done inside `*_inner` functions. - if !is_balance_check_disabled { - // check additional cost and deduct it from the caller's balances - let Some(balance) = new_balance.checked_sub(additional_cost) else { + validate_account_nonce_and_code_with_components(&mut caller_account.info, tx, cfg)?; + + // check additional cost and deduct it from the caller's balances + let mut balance = caller_account.info.balance; + + if !cfg.is_fee_charge_disabled() { + let additional_cost = chain.tx_cost_with_tx(tx, spec); + let Some(new_balance) = balance.checked_sub(additional_cost) else { return Err(InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(additional_cost), - balance: Box::new(new_balance), + balance: Box::new(balance), } .into()); }; - tx.ensure_enough_balance(balance)?; - } - - // subtracting max balance spending with value that is going to be deducted later in the call. - let gas_balance_spending = tx - .gas_balance_spending(basefee, blob_price) - .expect("effective balance is always smaller than max balance so it can't overflow"); - - // If the transaction is not a deposit transaction, subtract the L1 data fee from the - // caller's balance directly after minting the requested amount of ETH. - // Additionally deduct the operator fee from the caller's account. - // - // In case of deposit additional cost will be zero. - let op_gas_balance_spending = gas_balance_spending.saturating_add(additional_cost); - - new_balance = new_balance.saturating_sub(op_gas_balance_spending); - - if is_balance_check_disabled { - // Make sure the caller's balance is at least the value of the transaction. - // this is not consensus critical, and it is used in testing. - new_balance = new_balance.max(tx.value()); + balance = new_balance } - let old_balance = - caller_account.caller_initial_modification(new_balance, tx.kind().is_call()); + let balance = calculate_caller_fee(balance, tx, block, cfg)?; + let old_balance = caller_account.caller_initial_modification(balance, tx.kind().is_call()); // NOTE: all changes to the caller account should journaled so in case of error // we can revert the changes. journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index fd92a32c46..c3a6dc2172 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -7,7 +7,7 @@ use crate::{ NON_ZERO_BYTE_COST, OPERATOR_FEE_CONSTANT_OFFSET, OPERATOR_FEE_JOVIAN_MULTIPLIER, OPERATOR_FEE_SCALARS_SLOT, OPERATOR_FEE_SCALAR_DECIMAL, OPERATOR_FEE_SCALAR_OFFSET, }, - transaction::estimate_tx_compressed_size, + transaction::{estimate_tx_compressed_size, OpTxTr}, OpSpecId, }; use revm::{ @@ -256,6 +256,35 @@ impl L1BlockInfo { self.tx_l1_cost = None; } + /// Calculate additional transaction cost with OpTxTr. + /// + /// Internally calls [`L1BlockInfo::tx_cost`]. + #[track_caller] + pub fn tx_cost_with_tx(&mut self, tx: impl OpTxTr, spec: OpSpecId) -> U256 { + // account for additional cost of l1 fee and operator fee + let enveloped_tx = tx + .enveloped_tx() + .expect("all not deposit tx have enveloped tx") + .clone(); + let gas_limit = U256::from(tx.gas_limit()); + self.tx_cost(&enveloped_tx, gas_limit, spec) + } + + /// Calculate additional transaction cost. + #[inline] + pub fn tx_cost(&mut self, enveloped_tx: &[u8], gas_limit: U256, spec: OpSpecId) -> U256 { + // compute L1 cost + let mut additional_cost = self.calculate_tx_l1_cost(enveloped_tx, spec); + + // compute operator fee + if spec.is_enabled_in(OpSpecId::ISTHMUS) { + let operator_fee_charge = self.operator_fee_charge(enveloped_tx, gas_limit, spec); + additional_cost = additional_cost.saturating_add(operator_fee_charge); + } + + additional_cost + } + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, depending on the [OpSpecId] passed. pub fn calculate_tx_l1_cost(&mut self, input: &[u8], spec_id: OpSpecId) -> U256 { if let Some(tx_l1_cost) = self.tx_l1_cost { diff --git a/examples/erc20_gas/src/handler.rs b/examples/erc20_gas/src/handler.rs index 230f2d161c..8213164550 100644 --- a/examples/erc20_gas/src/handler.rs +++ b/examples/erc20_gas/src/handler.rs @@ -2,7 +2,7 @@ use revm::{ context::Cfg, context_interface::{result::HaltReason, Block, ContextTr, JournalTr, Transaction}, handler::{ - pre_execution::{calculate_caller_fee, validate_account_nonce_and_code}, + pre_execution::{calculate_caller_fee, validate_account_nonce_and_code_with_components}, EvmTr, EvmTrError, FrameResult, FrameTr, Handler, }, interpreter::interpreter_action::FrameInit, @@ -54,12 +54,7 @@ where // Load caller's account. let caller_account = journal.load_account_code(tx.caller())?.data; - validate_account_nonce_and_code( - &mut caller_account.info, - tx.nonce(), - cfg.is_eip3607_disabled(), - cfg.is_nonce_check_disabled(), - )?; + validate_account_nonce_and_code_with_components(&mut caller_account.info, tx, cfg)?; // make changes to the account. Account balance stays the same caller_account From d6106a7eecaa6105752ae159a186d1f896b70d7a Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 21 Oct 2025 19:05:54 +0200 Subject: [PATCH 019/127] feat: dont load access list immediately (#3116) * feat: dont load access list immediatly * nits fmt * nit, rm clone --- .../context/interface/src/journaled_state.rs | 18 +-- crates/context/src/journal.rs | 23 ++-- crates/context/src/journal/inner.rs | 124 +++++++----------- crates/context/src/journal/warm_addresses.rs | 58 ++++++-- crates/handler/src/pre_execution.rs | 11 +- examples/cheatcode_inspector/src/main.rs | 10 +- 6 files changed, 116 insertions(+), 128 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index ffc5f5b0bf..511fad530a 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -6,7 +6,7 @@ use crate::{ use core::ops::{Deref, DerefMut}; use database_interface::Database; use primitives::{ - hardfork::SpecId, Address, Bytes, HashSet, Log, StorageKey, StorageValue, B256, U256, + hardfork::SpecId, Address, Bytes, HashMap, HashSet, Log, StorageKey, StorageValue, B256, U256, }; use state::{Account, AccountInfo, Bytecode}; use std::{borrow::Cow, vec::Vec}; @@ -87,20 +87,8 @@ pub trait JournalTr { target: Address, ) -> Result, ::Error>; - /// Warms the account and storage. - fn warm_account_and_storage( - &mut self, - address: Address, - storage_keys: impl IntoIterator, - ) -> Result<(), ::Error>; - - /// Warms the account. Internally calls [`JournalTr::warm_account_and_storage`] with empty storage keys. - fn warm_account( - &mut self, - address: Address, - ) -> Result<(), ::Error> { - self.warm_account_and_storage(address, []) - } + /// Sets access list inside journal. + fn warm_access_list(&mut self, access_list: HashMap>); /// Warms the coinbase account. fn warm_coinbase_account(&mut self, address: Address); diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 2b35572c67..7780d91299 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -18,7 +18,9 @@ use context_interface::{ }; use core::ops::{Deref, DerefMut}; use database_interface::Database; -use primitives::{hardfork::SpecId, Address, HashSet, Log, StorageKey, StorageValue, B256, U256}; +use primitives::{ + hardfork::SpecId, Address, HashMap, HashSet, Log, StorageKey, StorageValue, B256, U256, +}; use state::{Account, EvmState}; use std::vec::Vec; @@ -147,6 +149,11 @@ impl JournalTr for Journal { self.inner.selfdestruct(&mut self.database, address, target) } + #[inline] + fn warm_access_list(&mut self, access_list: HashMap>) { + self.inner.warm_addresses.set_access_list(access_list); + } + fn warm_coinbase_account(&mut self, address: Address) { self.inner.warm_addresses.set_coinbase(address); } @@ -168,18 +175,6 @@ impl JournalTr for Journal { self.inner.depth } - #[inline] - fn warm_account_and_storage( - &mut self, - address: Address, - storage_keys: impl IntoIterator, - ) -> Result<(), ::Error> { - self.inner - .load_account_optional(&mut self.database, address, false, storage_keys, false) - .map_err(JournalLoadError::unwrap_db_error)?; - Ok(()) - } - #[inline] fn set_spec_id(&mut self, spec_id: SpecId) { self.inner.spec = spec_id; @@ -347,7 +342,7 @@ impl JournalTr for Journal { ) -> Result, JournalLoadError<::Error>> { let spec = self.inner.spec; self.inner - .load_account_optional(&mut self.database, address, load_code, [], skip_cold_load) + .load_account_optional(&mut self.database, address, load_code, skip_cold_load) .map(|a| { AccountInfoLoad::new(&a.data.info, a.is_cold, a.state_clear_aware_is_empty(spec)) }) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 3b98d3fd24..4e89f74010 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -117,7 +117,7 @@ impl JournalInner { journal.clear(); // Clear coinbase address warming for next tx - warm_addresses.clear_coinbase(); + warm_addresses.clear_coinbase_and_access_list(); // increment transaction id. *transaction_id += 1; logs.clear(); @@ -147,7 +147,7 @@ impl JournalInner { *transaction_id += 1; // Clear coinbase address warming for next tx - warm_addresses.clear_coinbase(); + warm_addresses.clear_coinbase_and_access_list(); } /// Take the [`EvmState`] and clears the journal by resetting it to initial state. @@ -171,7 +171,7 @@ impl JournalInner { // Spec is not changed. And it is always set again in execution. let _ = spec; // Clear coinbase address warming for next tx - warm_addresses.clear_coinbase(); + warm_addresses.clear_coinbase_and_access_list(); let state = mem::take(state); logs.clear(); @@ -586,7 +586,7 @@ impl JournalInner { db: &mut DB, address: Address, ) -> Result, DB::Error> { - self.load_account_optional(db, address, false, [], false) + self.load_account_optional(db, address, false, false) .map_err(JournalLoadError::unwrap_db_error) } @@ -606,7 +606,7 @@ impl JournalInner { let spec = self.spec; let is_eip7702_enabled = spec.is_enabled_in(SpecId::PRAGUE); let account = self - .load_account_optional(db, address, is_eip7702_enabled, [], false) + .load_account_optional(db, address, is_eip7702_enabled, false) .map_err(JournalLoadError::unwrap_db_error)?; let is_empty = account.state_clear_aware_is_empty(spec); @@ -622,7 +622,7 @@ impl JournalInner { if let Some(Bytecode::Eip7702(code)) = &account.info.code { let address = code.address(); let delegate_account = self - .load_account_optional(db, address, true, [], false) + .load_account_optional(db, address, true, false) .map_err(JournalLoadError::unwrap_db_error)?; account_load.data.is_delegate_account_cold = Some(delegate_account.is_cold); } @@ -642,18 +642,17 @@ impl JournalInner { db: &mut DB, address: Address, ) -> Result, DB::Error> { - self.load_account_optional(db, address, true, [], false) + self.load_account_optional(db, address, true, false) .map_err(JournalLoadError::unwrap_db_error) } /// Loads account. If account is already loaded it will be marked as warm. #[inline(never)] - pub fn load_account_optional( + pub(crate) fn load_account_optional( &mut self, db: &mut DB, address: Address, load_code: bool, - storage_keys: impl IntoIterator, skip_cold_load: bool, ) -> Result, JournalLoadError> { let load = match self.state.entry(address) { @@ -725,18 +724,6 @@ impl JournalInner { info.code = Some(code); } } - - for storage_key in storage_keys.into_iter() { - sload_with_account( - load.data, - db, - &mut self.journal, - self.transaction_id, - address, - storage_key, - false, - )?; - } Ok(load) } @@ -755,16 +742,44 @@ impl JournalInner { ) -> Result, JournalLoadError> { // assume acc is warm let account = self.state.get_mut(&address).unwrap(); - // only if account is created in this tx we can assume that storage is empty. - sload_with_account( - account, - db, - &mut self.journal, - self.transaction_id, - address, - key, - skip_cold_load, - ) + + let is_newly_created = account.is_created(); + let (value, is_cold) = match account.storage.entry(key) { + Entry::Occupied(occ) => { + let slot = occ.into_mut(); + // skip load if account is cold. + let is_cold = slot.is_cold_transaction_id(self.transaction_id); + if skip_cold_load && is_cold { + return Err(JournalLoadError::ColdLoadSkipped); + } + slot.mark_warm_with_transaction_id(self.transaction_id); + (slot.present_value, is_cold) + } + Entry::Vacant(vac) => { + if skip_cold_load { + return Err(JournalLoadError::ColdLoadSkipped); + } + // if storage was cleared, we don't need to ping db. + let value = if is_newly_created { + StorageValue::ZERO + } else { + db.storage(address, key)? + }; + vac.insert(EvmStorageSlot::new(value, self.transaction_id)); + + // is storage cold + let is_cold = !self.warm_addresses.is_storage_warm(&address, &key); + + (value, is_cold) + } + }; + + if is_cold { + // add it to journal as cold loaded. + self.journal.push(ENTRY::storage_warmed(address, key)); + } + + Ok(StateLoad::new(value, is_cold)) } /// Stores storage slot. @@ -867,50 +882,3 @@ impl JournalInner { self.logs.push(log); } } - -/// Loads storage slot with account. -#[inline] -pub fn sload_with_account( - account: &mut Account, - db: &mut DB, - journal: &mut Vec, - transaction_id: usize, - address: Address, - key: StorageKey, - skip_cold_load: bool, -) -> Result, JournalLoadError> { - let is_newly_created = account.is_created(); - let (value, is_cold) = match account.storage.entry(key) { - Entry::Occupied(occ) => { - let slot = occ.into_mut(); - // skip load if account is cold. - let is_cold = slot.is_cold_transaction_id(transaction_id); - if skip_cold_load && is_cold { - return Err(JournalLoadError::ColdLoadSkipped); - } - slot.mark_warm_with_transaction_id(transaction_id); - (slot.present_value, is_cold) - } - Entry::Vacant(vac) => { - if skip_cold_load { - return Err(JournalLoadError::ColdLoadSkipped); - } - // if storage was cleared, we don't need to ping db. - let value = if is_newly_created { - StorageValue::ZERO - } else { - db.storage(address, key)? - }; - vac.insert(EvmStorageSlot::new(value, transaction_id)); - - (value, true) - } - }; - - if is_cold { - // add it to journal as cold loaded. - journal.push(ENTRY::storage_warmed(address, key)); - } - - Ok(StateLoad::new(value, is_cold)) -} diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs index 8335563ee4..ac5f1a6a40 100644 --- a/crates/context/src/journal/warm_addresses.rs +++ b/crates/context/src/journal/warm_addresses.rs @@ -3,9 +3,17 @@ //! It is used to optimize access to precompile addresses. use bitvec::{bitvec, vec::BitVec}; -use primitives::{short_address, Address, HashSet, SHORT_ADDRESS_CAP}; +use primitives::{short_address, Address, HashMap, HashSet, StorageKey, SHORT_ADDRESS_CAP}; /// Stores addresses that are warm loaded. Contains precompiles and coinbase address. +/// +/// It contains precompiles addresses that are not changed frequently and AccessList that +/// is changed per transaction. +/// +/// [WarmAddresses::precompiles] will always contain all precompile addresses. +/// +/// As precompiles addresses are usually very small, precompile_short_addresses will +/// contain bitset of shrunk precompile address. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct WarmAddresses { @@ -15,9 +23,11 @@ pub struct WarmAddresses { /// will be stored in this bit vector for faster access. precompile_short_addresses: BitVec, /// `true` if all precompiles are short addresses. - all_short_addresses: bool, + precompile_all_short_addresses: bool, /// Coinbase address. coinbase: Option
, + /// Access list + access_list: HashMap>, } impl Default for WarmAddresses { @@ -33,8 +43,9 @@ impl WarmAddresses { Self { precompile_set: HashSet::default(), precompile_short_addresses: bitvec![0; SHORT_ADDRESS_CAP], - all_short_addresses: true, + precompile_all_short_addresses: true, coinbase: None, + access_list: HashMap::default(), } } @@ -64,7 +75,7 @@ impl WarmAddresses { } } - self.all_short_addresses = all_short_addresses; + self.precompile_all_short_addresses = all_short_addresses; self.precompile_set = addresses; } @@ -74,12 +85,25 @@ impl WarmAddresses { self.coinbase = Some(address); } + /// Set the access list. + #[inline] + pub fn set_access_list(&mut self, access_list: HashMap>) { + self.access_list = access_list; + } + /// Clear the coinbase address. #[inline] pub fn clear_coinbase(&mut self) { self.coinbase = None; } + /// Clear the coinbase and access list. + #[inline] + pub fn clear_coinbase_and_access_list(&mut self) { + self.coinbase = None; + self.access_list.clear(); + } + /// Returns true if the address is warm loaded. #[inline] pub fn is_warm(&self, address: &Address) -> bool { @@ -88,6 +112,11 @@ impl WarmAddresses { return true; } + // if it is part of access list. + if self.access_list.contains_key(address) { + return true; + } + // if there are no precompiles, it is cold loaded and bitvec is not set. if self.precompile_set.is_empty() { return false; @@ -98,13 +127,22 @@ impl WarmAddresses { return self.precompile_short_addresses[short_address]; } - // if all precompiles are short addresses, it is cold loaded. - if self.all_short_addresses { - return false; + if !self.precompile_all_short_addresses { + // in the end check if it is inside precompile set + return self.precompile_set.contains(address); + } + + false + } + + /// Returns true if the storage is warm loaded. + #[inline] + pub fn is_storage_warm(&self, address: &Address, key: &StorageKey) -> bool { + if let Some(access_list) = self.access_list.get(address) { + return access_list.contains(key); } - // in the end check if it is inside precompile set - self.precompile_set.contains(address) + false } /// Returns true if the address is cold loaded. @@ -146,7 +184,7 @@ mod tests { assert!(warm_addresses.is_warm(&coinbase_addr)); // Test clearing coinbase - warm_addresses.clear_coinbase(); + warm_addresses.clear_coinbase_and_access_list(); assert!(warm_addresses.coinbase.is_none()); assert!(!warm_addresses.is_warm(&coinbase_addr)); } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 5fd5613691..a4a9d4a65c 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -13,8 +13,8 @@ use context_interface::{ Block, Cfg, Database, }; use core::cmp::Ordering; -use primitives::StorageKey; use primitives::{eip7702, hardfork::SpecId, KECCAK_EMPTY, U256}; +use primitives::{Address, HashMap, HashSet, StorageKey}; use state::AccountInfo; /// Loads and warms accounts for execution, including precompiles and access list. @@ -53,12 +53,13 @@ pub fn load_accounts< // legacy is only tx type that does not have access list. if tx.tx_type() != TransactionType::Legacy { if let Some(access_list) = tx.access_list() { + let mut map: HashMap> = HashMap::default(); for item in access_list { - journal.warm_account_and_storage( - *item.address(), - item.storage_slots().map(|i| StorageKey::from_be_bytes(i.0)), - )?; + map.entry(*item.address()) + .or_default() + .extend(item.storage_slots().map(|key| U256::from_be_bytes(key.0))); } + journal.warm_access_list(map); } } diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index 53c1df9162..269e7e8c68 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -110,13 +110,11 @@ impl JournalTr for Backend { self.journaled_state.selfdestruct(address, target) } - fn warm_account_and_storage( + fn warm_access_list( &mut self, - address: Address, - storage_keys: impl IntoIterator, - ) -> Result<(), ::Error> { - self.journaled_state - .warm_account_and_storage(address, storage_keys) + access_list: revm::primitives::HashMap>, + ) { + self.journaled_state.warm_access_list(access_list); } fn warm_coinbase_account(&mut self, address: Address) { From eb69b28aded5681e32bbb9de1d42e85c72c3c873 Mon Sep 17 00:00:00 2001 From: makcandrov Date: Tue, 21 Oct 2025 10:20:13 -0700 Subject: [PATCH 020/127] feat: impl `Sealable` for `Bytecode` (#3118) --- crates/bytecode/src/bytecode.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/bytecode/src/bytecode.rs b/crates/bytecode/src/bytecode.rs index a6f09b7aa5..d3af31d5a0 100644 --- a/crates/bytecode/src/bytecode.rs +++ b/crates/bytecode/src/bytecode.rs @@ -8,7 +8,7 @@ use crate::{ eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES}, BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode, }; -use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY}; +use primitives::{alloy_primitives::Sealable, keccak256, Address, Bytes, B256, KECCAK_EMPTY}; /// Main bytecode structure with all variants. #[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] @@ -27,6 +27,13 @@ impl Default for Bytecode { } } +impl Sealable for Bytecode { + #[inline] + fn hash_slow(&self) -> B256 { + self.hash_slow() + } +} + impl Bytecode { /// Creates a new legacy analyzed [`Bytecode`] with exactly one STOP opcode. #[inline] From 33154d8cbbbcb457987956c46bd1302b44926cac Mon Sep 17 00:00:00 2001 From: theo <80177219+theochap@users.noreply.github.com> Date: Wed, 22 Oct 2025 05:43:13 -0400 Subject: [PATCH 021/127] fix(jovian): fixes the DA footprint update storage slot. fix l1 fork associated with Jovian. (#3120) * fix(jovian/storage): fix jovian's storage slot for da footprint gas scalar * fix(jovian): fix l1 hardfork matching jovian. expose da footprint gas scalar getter --- crates/op-revm/src/constants.rs | 6 +++--- crates/op-revm/src/handler.rs | 31 +++++++++++++------------------ crates/op-revm/src/l1block.rs | 11 ++++++++--- crates/op-revm/src/spec.rs | 5 ++--- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/crates/op-revm/src/constants.rs b/crates/op-revm/src/constants.rs index 243343e804..2c93bff13b 100644 --- a/crates/op-revm/src/constants.rs +++ b/crates/op-revm/src/constants.rs @@ -20,7 +20,7 @@ pub const OPERATOR_FEE_CONSTANT_OFFSET: usize = 24; /// The Jovian daFootprintGasScalar value is packed into a single storage slot. Byte offset within /// the storage slot of the 16-byte daFootprintGasScalar attribute. -pub const DA_FOOTPRINT_GAS_SCALAR_OFFSET: usize = 0; +pub const DA_FOOTPRINT_GAS_SCALAR_OFFSET: usize = 18; /// The fixed point decimal scaling factor associated with the operator fee scalar. /// @@ -48,9 +48,9 @@ pub const ECOTONE_L1_FEE_SCALARS_SLOT: U256 = U256::from_limbs([3u64, 0, 0, 0]); /// offsets [OPERATOR_FEE_SCALAR_OFFSET] and [OPERATOR_FEE_CONSTANT_OFFSET] respectively. pub const OPERATOR_FEE_SCALARS_SLOT: U256 = U256::from_limbs([8u64, 0, 0, 0]); -/// As of the Jovian upgrade, this storage slot stores the 32-bit daFootprintGasScalar attribute at +/// As of the Jovian upgrade, this storage slot stores the 16-bit daFootprintGasScalar attribute at /// offset [DA_FOOTPRINT_GAS_SCALAR_OFFSET]. -pub const DA_FOOTPRINT_GAS_SCALAR_SLOT: U256 = U256::from_limbs([9u64, 0, 0, 0]); +pub const DA_FOOTPRINT_GAS_SCALAR_SLOT: U256 = U256::from_limbs([8u64, 0, 0, 0]); /// An empty 64-bit set of scalar values. pub const EMPTY_SCALARS: [u8; 8] = [0u8; 8]; diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 6aeaaed158..cd9a3462cd 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -457,9 +457,8 @@ mod tests { use crate::{ api::default_ctx::OpContext, constants::{ - BASE_FEE_SCALAR_OFFSET, DA_FOOTPRINT_GAS_SCALAR_SLOT, ECOTONE_L1_BLOB_BASE_FEE_SLOT, - ECOTONE_L1_FEE_SCALARS_SLOT, L1_BASE_FEE_SLOT, L1_BLOCK_CONTRACT, - OPERATOR_FEE_SCALARS_SLOT, + BASE_FEE_SCALAR_OFFSET, ECOTONE_L1_BLOB_BASE_FEE_SLOT, ECOTONE_L1_FEE_SCALARS_SLOT, + L1_BASE_FEE_SLOT, L1_BLOCK_CONTRACT, OPERATOR_FEE_SCALARS_SLOT, }, DefaultOp, OpBuilder, OpTransaction, }; @@ -769,15 +768,14 @@ mod tests { 0, 0, ]); - const OPERATOR_FEE_SCALAR: u64 = 5; - const OPERATOR_FEE_CONST: u64 = 6; - const OPERATOR_FEE: U256 = - U256::from_limbs([OPERATOR_FEE_CONST, OPERATOR_FEE_SCALAR, 0, 0]); - const DA_FOOTPRINT_GAS_SCALAR: u16 = 7; - const DA_FOOTPRINT_GAS_SCALAR_U64: u64 = - u64::from_be_bytes([0, DA_FOOTPRINT_GAS_SCALAR as u8, 0, 0, 0, 0, 0, 0]); - const DA_FOOTPRINT_GAS_SCALAR_SLOT_VALUE: U256 = - U256::from_limbs([0, 0, 0, DA_FOOTPRINT_GAS_SCALAR_U64]); + const OPERATOR_FEE_SCALAR: u8 = 5; + const OPERATOR_FEE_CONST: u8 = 6; + const DA_FOOTPRINT_GAS_SCALAR: u8 = 7; + let mut operator_fee_and_da_footprint = [0u8; 32]; + operator_fee_and_da_footprint[31] = OPERATOR_FEE_CONST; + operator_fee_and_da_footprint[23] = OPERATOR_FEE_SCALAR; + operator_fee_and_da_footprint[19] = DA_FOOTPRINT_GAS_SCALAR; + let operator_fee_and_da_footprint_u256 = U256::from_be_bytes(operator_fee_and_da_footprint); let mut db = InMemoryDB::default(); let l1_block_contract = db.load_account(L1_BLOCK_CONTRACT).unwrap(); @@ -790,12 +788,9 @@ mod tests { l1_block_contract .storage .insert(ECOTONE_L1_FEE_SCALARS_SLOT, L1_FEE_SCALARS); - l1_block_contract - .storage - .insert(OPERATOR_FEE_SCALARS_SLOT, OPERATOR_FEE); l1_block_contract.storage.insert( - DA_FOOTPRINT_GAS_SCALAR_SLOT, - DA_FOOTPRINT_GAS_SCALAR_SLOT_VALUE, + OPERATOR_FEE_SCALARS_SLOT, + operator_fee_and_da_footprint_u256, ); db.insert_account_info( Address::ZERO, @@ -849,7 +844,7 @@ mod tests { operator_fee_scalar: Some(U256::from(OPERATOR_FEE_SCALAR)), operator_fee_constant: Some(U256::from(OPERATOR_FEE_CONST)), tx_l1_cost: Some(U256::ZERO), - da_footprint_gas_scalar: Some(DA_FOOTPRINT_GAS_SCALAR), + da_footprint_gas_scalar: Some(DA_FOOTPRINT_GAS_SCALAR as u16), } ); } diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index c3a6dc2172..67f52b6b60 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -58,8 +58,8 @@ pub struct L1BlockInfo { } impl L1BlockInfo { - /// Try to fetch the L1 block info from the database, post-Jovian. - fn try_fetch_jovian(&mut self, db: &mut DB) -> Result<(), DB::Error> { + /// Fetch the DA footprint gas scalar from the database. + pub fn fetch_da_footprint_gas_scalar(db: &mut DB) -> Result { let da_footprint_gas_scalar_slot = db .storage(L1_BLOCK_CONTRACT, DA_FOOTPRINT_GAS_SCALAR_SLOT)? .to_be_bytes::<32>(); @@ -69,7 +69,12 @@ impl L1BlockInfo { da_footprint_gas_scalar_slot[DA_FOOTPRINT_GAS_SCALAR_OFFSET], da_footprint_gas_scalar_slot[DA_FOOTPRINT_GAS_SCALAR_OFFSET + 1], ]; - self.da_footprint_gas_scalar = Some(u16::from_be_bytes(bytes)); + Ok(u16::from_be_bytes(bytes)) + } + + /// Try to fetch the L1 block info from the database, post-Jovian. + fn try_fetch_jovian(&mut self, db: &mut DB) -> Result<(), DB::Error> { + self.da_footprint_gas_scalar = Some(Self::fetch_da_footprint_gas_scalar(db)?); Ok(()) } diff --git a/crates/op-revm/src/spec.rs b/crates/op-revm/src/spec.rs index 35b15c3c9a..e192847a0f 100644 --- a/crates/op-revm/src/spec.rs +++ b/crates/op-revm/src/spec.rs @@ -40,8 +40,8 @@ impl OpSpecId { Self::BEDROCK | Self::REGOLITH => SpecId::MERGE, Self::CANYON => SpecId::SHANGHAI, Self::ECOTONE | Self::FJORD | Self::GRANITE | Self::HOLOCENE => SpecId::CANCUN, - Self::ISTHMUS | Self::INTEROP => SpecId::PRAGUE, - Self::JOVIAN | Self::OSAKA => SpecId::OSAKA, + Self::ISTHMUS | Self::JOVIAN | Self::INTEROP => SpecId::PRAGUE, + Self::OSAKA => SpecId::OSAKA, } } @@ -201,7 +201,6 @@ mod tests { (SpecId::SHANGHAI, true), (SpecId::CANCUN, true), (SpecId::MERGE, true), - (SpecId::OSAKA, true), ], vec![ (OpSpecId::BEDROCK, true), From ce68f93c9acb77444f7f077d4cdcd7217714e645 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 23 Oct 2025 14:40:04 +0200 Subject: [PATCH 022/127] feat: JournaledAccount, a nice way to update and track changes (#3086) * JournaledAcccount * PoC: JournaledAccount, a nice way to update and track changes * cleanup * rm artifact * inline some of host fn * beneficiary refactor * nit * nits * fmt * rename and make old fn deprecated --- .../context/interface/src/journaled_state.rs | 63 +++++- .../interface/src/journaled_state/account.rs | 185 ++++++++++++++++++ .../src/journaled_state}/entry.rs | 0 crates/context/src/context.rs | 4 + crates/context/src/journal.rs | 28 ++- crates/context/src/journal/inner.rs | 87 ++++---- crates/handler/src/frame.rs | 15 +- crates/handler/src/handler.rs | 4 +- crates/handler/src/post_execution.rs | 30 +-- crates/handler/src/pre_execution.rs | 35 ++-- crates/op-revm/src/handler.rs | 58 +++--- crates/state/src/lib.rs | 8 + examples/cheatcode_inspector/src/main.rs | 23 ++- examples/erc20_gas/src/handler.rs | 12 +- 14 files changed, 410 insertions(+), 142 deletions(-) create mode 100644 crates/context/interface/src/journaled_state/account.rs rename crates/context/{src/journal => interface/src/journaled_state}/entry.rs (100%) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 511fad530a..3b9c8d837b 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -1,7 +1,12 @@ //! Journaled state trait [`JournalTr`] and related types. + +pub mod account; +pub mod entry; + use crate::{ context::{SStoreResult, SelfDestructResult}, host::LoadError, + journaled_state::{account::JournaledAccount, entry::JournalEntryTr}, }; use core::ops::{Deref, DerefMut}; use database_interface::Database; @@ -17,6 +22,8 @@ pub trait JournalTr { type Database: Database; /// State type that is returned by the journal after finalization. type State; + /// Journal Entry type that is used in the journal. + type JournalEntry: JournalEntryTr; /// Creates new Journaled state. /// @@ -143,13 +150,23 @@ pub trait JournalTr { fn load_account( &mut self, address: Address, - ) -> Result, ::Error>; + ) -> Result, ::Error>; - /// Loads the account code. + /// Loads the account code, use `load_account_with_code` instead. + #[inline] + #[deprecated(note = "Use `load_account_with_code` instead")] fn load_account_code( &mut self, address: Address, - ) -> Result, ::Error>; + ) -> Result, ::Error> { + self.load_account_with_code(address) + } + + /// Loads the account with code. + fn load_account_with_code( + &mut self, + address: Address, + ) -> Result, ::Error>; /// Loads the account delegated. fn load_account_delegated( @@ -157,6 +174,40 @@ pub trait JournalTr { address: Address, ) -> Result, ::Error>; + /// Loads the journaled account. + #[inline] + fn load_account_mut( + &mut self, + address: Address, + ) -> Result< + StateLoad>, + ::Error, + > { + self.load_account_mut_optional_code(address, false) + } + + /// Loads the journaled account. + #[inline] + fn load_account_with_code_mut( + &mut self, + address: Address, + ) -> Result< + StateLoad>, + ::Error, + > { + self.load_account_mut_optional_code(address, true) + } + + /// Loads the journaled account. + fn load_account_mut_optional_code( + &mut self, + address: Address, + load_code: bool, + ) -> Result< + StateLoad>, + ::Error, + >; + /// Sets bytecode with hash. Assume that account is warm. fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256); @@ -175,7 +226,7 @@ pub trait JournalTr { &mut self, address: Address, ) -> Result, ::Error> { - let a = self.load_account_code(address)?; + let a = self.load_account_with_code(address)?; // SAFETY: Safe to unwrap as load_code will insert code if it is empty. let code = a.info.code.as_ref().unwrap().original_bytes(); @@ -187,7 +238,7 @@ pub trait JournalTr { &mut self, address: Address, ) -> Result, ::Error> { - let acc = self.load_account_code(address)?; + let acc = self.load_account_with_code(address)?; if acc.is_empty() { return Ok(StateLoad::new(B256::ZERO, acc.is_cold)); } @@ -361,6 +412,7 @@ impl DerefMut for StateLoad { impl StateLoad { /// Returns a new [`StateLoad`] with the given data and cold load status. + #[inline] pub fn new(data: T, is_cold: bool) -> Self { Self { data, is_cold } } @@ -368,6 +420,7 @@ impl StateLoad { /// Maps the data of the [`StateLoad`] to a new value. /// /// Useful for transforming the data of the [`StateLoad`] without changing the cold load status. + #[inline] pub fn map(self, f: F) -> StateLoad where F: FnOnce(T) -> B, diff --git a/crates/context/interface/src/journaled_state/account.rs b/crates/context/interface/src/journaled_state/account.rs new file mode 100644 index 0000000000..4d42dd307e --- /dev/null +++ b/crates/context/interface/src/journaled_state/account.rs @@ -0,0 +1,185 @@ +//! This module contains [`JournaledAccount`] struct a wrapper around account and journal entries that +//! allow updates to the account and journal entries. +//! +//! Useful to encapsulate account and journal entries together. So when account gets changed, we can add a journal entry for it. + +use super::entry::JournalEntryTr; +use core::ops::Deref; +use primitives::{Address, B256, KECCAK_EMPTY, U256}; +use state::{Account, Bytecode}; +use std::vec::Vec; + +/// Journaled account contains both mutable account and journal entries. +/// +/// Useful to encapsulate account and journal entries together. So when account gets changed, we can add a journal entry for it. +#[derive(Debug, PartialEq, Eq)] +pub struct JournaledAccount<'a, ENTRY: JournalEntryTr> { + /// Address of the account. + address: Address, + /// Mutable account. + account: &'a mut Account, + /// Journal entries. + journal_entries: &'a mut Vec, +} + +impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { + /// Consumes the journaled account and returns the mutable account. + #[inline] + pub fn into_account_ref(self) -> &'a Account { + self.account + } + + /// Creates a new journaled account. + #[inline] + pub fn new( + address: Address, + account: &'a mut Account, + journal_entries: &'a mut Vec, + ) -> Self { + Self { + address, + account, + journal_entries, + } + } + + /// Returns the balance of the account. + #[inline] + pub fn balance(&self) -> &U256 { + &self.account.info.balance + } + + /// Returns the nonce of the account. + #[inline] + pub fn nonce(&self) -> u64 { + self.account.info.nonce + } + + /// Returns the code hash of the account. + #[inline] + pub fn code_hash(&self) -> &B256 { + &self.account.info.code_hash + } + + /// Returns the code of the account. + #[inline] + pub fn code(&self) -> Option<&Bytecode> { + self.account.info.code.as_ref() + } + + /// Touches the account. + #[inline] + pub fn touch(&mut self) { + if !self.account.status.is_touched() { + self.account.mark_touch(); + self.journal_entries + .push(ENTRY::account_touched(self.address)); + } + } + + /// Sets the balance of the account. + /// + /// If balance is the same, we don't add a journal entry. + /// + /// Touches the account in all cases. + #[inline] + pub fn set_balance(&mut self, balance: U256) { + self.touch(); + if self.account.info.balance != balance { + self.journal_entries.push(ENTRY::balance_changed( + self.address, + self.account.info.balance, + )); + self.account.info.set_balance(balance); + } + } + + /// Increments the balance of the account. + /// + /// Touches the account in all cases. + #[inline] + pub fn incr_balance(&mut self, balance: U256) -> bool { + self.touch(); + let Some(balance) = self.account.info.balance.checked_add(balance) else { + return false; + }; + self.set_balance(balance); + true + } + + /// Decrements the balance of the account. + /// + /// Touches the account in all cases. + #[inline] + pub fn decr_balance(&mut self, balance: U256) -> bool { + self.touch(); + let Some(balance) = self.account.info.balance.checked_sub(balance) else { + return false; + }; + self.set_balance(balance); + true + } + + /// Bumps the nonce of the account. + /// + /// Touches the account in all cases. + /// + /// Returns true if nonce was bumped, false if nonce is at the max value. + #[inline] + pub fn bump_nonce(&mut self) -> bool { + self.touch(); + let Some(nonce) = self.account.info.nonce.checked_add(1) else { + return false; + }; + self.account.info.set_nonce(nonce); + self.journal_entries + .push(ENTRY::nonce_changed(self.address)); + true + } + + /// Sets the code of the account. + /// + /// Touches the account in all cases. + #[inline] + pub fn set_code(&mut self, code_hash: B256, code: Bytecode) { + self.touch(); + self.account.info.set_code_hash(code_hash); + self.account.info.set_code(code); + self.journal_entries.push(ENTRY::code_changed(self.address)); + } + + /// Sets the code of the account. Calculates hash of the code. + /// + /// Touches the account in all cases. + #[inline] + pub fn set_code_and_hash_slow(&mut self, code: Bytecode) { + let code_hash = code.hash_slow(); + self.set_code(code_hash, code); + } + + /// Delegates the account to another address (EIP-7702). + /// + /// This touches the account, sets the code to the delegation designation, + /// and bumps the nonce. + #[inline] + pub fn delegate(&mut self, address: Address) { + let (bytecode, hash) = if address.is_zero() { + (Bytecode::default(), KECCAK_EMPTY) + } else { + let bytecode = Bytecode::new_eip7702(address); + let hash = bytecode.hash_slow(); + (bytecode, hash) + }; + self.touch(); + self.set_code(hash, bytecode); + self.bump_nonce(); + } +} + +impl<'a, ENTRY: JournalEntryTr> Deref for JournaledAccount<'a, ENTRY> { + type Target = Account; + + fn deref(&self) -> &Self::Target { + self.account + } +} diff --git a/crates/context/src/journal/entry.rs b/crates/context/interface/src/journaled_state/entry.rs similarity index 100% rename from crates/context/src/journal/entry.rs rename to crates/context/interface/src/journaled_state/entry.rs diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 66bef8f89f..a16849b478 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -521,6 +521,7 @@ impl< } /// Marks `address` to be deleted, with funds transferred to `target`. + #[inline] fn selfdestruct( &mut self, address: Address, @@ -534,6 +535,7 @@ impl< .ok() } + #[inline] fn sstore_skip_cold_load( &mut self, address: Address, @@ -552,6 +554,7 @@ impl< }) } + #[inline] fn sload_skip_cold_load( &mut self, address: Address, @@ -569,6 +572,7 @@ impl< }) } + #[inline] fn load_account_info_skip_cold_load( &mut self, address: Address, diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 7780d91299..c7e4630570 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -2,18 +2,18 @@ //! //! Entry submodule contains [`JournalEntry`] and [`JournalEntryTr`] traits. //! and inner submodule contains [`JournalInner`] struct that contains state. -pub mod entry; pub mod inner; pub mod warm_addresses; -pub use entry::{JournalEntry, JournalEntryTr}; +pub use context_interface::journaled_state::entry::{JournalEntry, JournalEntryTr}; pub use inner::JournalInner; use bytecode::Bytecode; use context_interface::{ context::{SStoreResult, SelfDestructResult, StateLoad}, journaled_state::{ - AccountInfoLoad, AccountLoad, JournalCheckpoint, JournalLoadError, JournalTr, TransferError, + account::JournaledAccount, AccountInfoLoad, AccountLoad, JournalCheckpoint, + JournalLoadError, JournalTr, TransferError, }, }; use core::ops::{Deref, DerefMut}; @@ -92,6 +92,7 @@ impl Journal { impl JournalTr for Journal { type Database = DB; type State = EvmState; + type JournalEntry = ENTRY; fn new(database: DB) -> Journal { Self { @@ -234,15 +235,29 @@ impl JournalTr for Journal { } #[inline] - fn load_account(&mut self, address: Address) -> Result, DB::Error> { + fn load_account(&mut self, address: Address) -> Result, DB::Error> { self.inner.load_account(&mut self.database, address) } #[inline] - fn load_account_code( + fn load_account_mut_optional_code( &mut self, address: Address, - ) -> Result, DB::Error> { + load_code: bool, + ) -> Result< + StateLoad>, + ::Error, + > { + self.inner + .load_account_mut_optional_code(&mut self.database, address, load_code, false) + .map_err(JournalLoadError::unwrap_db_error) + } + + #[inline] + fn load_account_with_code( + &mut self, + address: Address, + ) -> Result, DB::Error> { self.inner.load_code(&mut self.database, address) } @@ -334,6 +349,7 @@ impl JournalTr for Journal { .sstore(&mut self.database, address, key, value, skip_cold_load) } + #[inline] fn load_account_info_skip_cold_load( &mut self, address: Address, diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 4e89f74010..a478c4e2d0 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -1,10 +1,12 @@ //! Module containing the [`JournalInner`] that is part of [`crate::Journal`]. -use crate::{entry::SelfdestructionRevertStatus, warm_addresses::WarmAddresses}; - -use super::JournalEntryTr; +use super::warm_addresses::WarmAddresses; use bytecode::Bytecode; use context_interface::{ context::{SStoreResult, SelfDestructResult, StateLoad}, + journaled_state::{ + account::JournaledAccount, + entry::{JournalEntryTr, SelfdestructionRevertStatus}, + }, journaled_state::{AccountLoad, JournalCheckpoint, JournalLoadError, TransferError}, }; use core::mem; @@ -293,19 +295,8 @@ impl JournalInner { address: Address, balance: U256, ) -> Result<(), DB::Error> { - let account = self.load_account(db, address)?.data; - let old_balance = account.info.balance; - account.info.balance = account.info.balance.saturating_add(balance); - - // march account as touched. - if !account.is_touched() { - account.mark_touch(); - self.journal.push(ENTRY::account_touched(address)); - } - - // add journal entry for balance increment. - self.journal - .push(ENTRY::balance_changed(address, old_balance)); + let mut account = self.load_account_mut(db, address)?.data; + account.incr_balance(balance); Ok(()) } @@ -407,14 +398,6 @@ impl JournalInner { // Enter subroutine let checkpoint = self.checkpoint(); - // Fetch balance of caller. - let caller_balance = self.state.get(&caller).unwrap().info.balance; - // Check if caller has enough balance to send to the created contract. - if caller_balance < balance { - self.checkpoint_revert(checkpoint); - return Err(TransferError::OutOfFunds); - } - // Newly created account is present, as we just loaded it. let target_acc = self.state.get_mut(&target_address).unwrap(); let last_journal = &mut self.journal; @@ -474,7 +457,7 @@ impl JournalInner { /// Commits the checkpoint. #[inline] pub fn checkpoint_commit(&mut self) { - self.depth -= 1; + self.depth = self.depth.saturating_sub(1); } /// Reverts all changes to state until given checkpoint. @@ -483,7 +466,7 @@ impl JournalInner { let is_spurious_dragon_enabled = self.spec.is_enabled_in(SPURIOUS_DRAGON); let state = &mut self.state; let transient_storage = &mut self.transient_storage; - self.depth -= 1; + self.depth = self.depth.saturating_sub(1); self.logs.truncate(checkpoint.log_i); // iterate over last N journals sets and revert our global state @@ -585,7 +568,7 @@ impl JournalInner { &mut self, db: &mut DB, address: Address, - ) -> Result, DB::Error> { + ) -> Result, DB::Error> { self.load_account_optional(db, address, false, false) .map_err(JournalLoadError::unwrap_db_error) } @@ -641,20 +624,44 @@ impl JournalInner { &mut self, db: &mut DB, address: Address, - ) -> Result, DB::Error> { + ) -> Result, DB::Error> { self.load_account_optional(db, address, true, false) .map_err(JournalLoadError::unwrap_db_error) } + /// Loads account into memory. If account is already loaded it will be marked as warm. + #[inline] + pub fn load_account_optional( + &mut self, + db: &mut DB, + address: Address, + load_code: bool, + skip_cold_load: bool, + ) -> Result, JournalLoadError> { + let load = self.load_account_mut_optional_code(db, address, load_code, skip_cold_load)?; + Ok(load.map(|i| i.into_account_ref())) + } + + /// Loads account into memory. If account is already loaded it will be marked as warm. + #[inline] + pub fn load_account_mut( + &mut self, + db: &mut DB, + address: Address, + ) -> Result>, DB::Error> { + self.load_account_mut_optional_code(db, address, false, false) + .map_err(JournalLoadError::unwrap_db_error) + } + /// Loads account. If account is already loaded it will be marked as warm. #[inline(never)] - pub(crate) fn load_account_optional( + pub fn load_account_mut_optional_code( &mut self, db: &mut DB, address: Address, load_code: bool, skip_cold_load: bool, - ) -> Result, JournalLoadError> { + ) -> Result>, JournalLoadError> { let load = match self.state.entry(address) { Entry::Occupied(entry) => { let account = entry.into_mut(); @@ -713,18 +720,18 @@ impl JournalInner { if load.is_cold { self.journal.push(ENTRY::account_warmed(address)); } - if load_code { + + if load_code && load.data.info.code.is_none() { let info = &mut load.data.info; - if info.code.is_none() { - let code = if info.code_hash == KECCAK_EMPTY { - Bytecode::default() - } else { - db.code_by_hash(info.code_hash)? - }; - info.code = Some(code); - } + let code = if info.code_hash == KECCAK_EMPTY { + Bytecode::default() + } else { + db.code_by_hash(info.code_hash)? + }; + info.code = Some(code); } - Ok(load) + + Ok(load.map(|i| JournaledAccount::new(address, i, &mut self.journal))) } /// Loads storage slot. diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index ed71b69038..db10e07f75 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -209,7 +209,7 @@ impl EthFrame { // Load account and get its bytecode let account = ctx .journal_mut() - .load_account_code(inputs.bytecode_address)?; + .load_account_with_code(inputs.bytecode_address)?; ( account.info.code.clone().unwrap_or_default(), account.info.code_hash, @@ -270,22 +270,19 @@ impl EthFrame { } // Fetch balance of caller. - let caller_info = &mut context.journal_mut().load_account(inputs.caller)?.data.info; + let mut caller_info = context.journal_mut().load_account_mut(inputs.caller)?; // Check if caller has enough balance to send to the created contract. - if caller_info.balance < inputs.value { + // decrement of balance is done in the create_account_checkpoint. + if *caller_info.balance() < inputs.value { return return_error(InstructionResult::OutOfFunds); } // Increase nonce of caller and check if it overflows - let old_nonce = caller_info.nonce; - let Some(new_nonce) = old_nonce.checked_add(1) else { + let old_nonce = caller_info.nonce(); + if !caller_info.bump_nonce() { return return_error(InstructionResult::Return); }; - caller_info.nonce = new_nonce; - context - .journal_mut() - .nonce_bump_journal_entry(inputs.caller); // Create address let mut init_code_hash = None; diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 8b1d34f676..2c73f0e99c 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -302,11 +302,11 @@ pub trait Handler { let (tx, journal) = ctx.tx_journal_mut(); let bytecode = if let Some(&to) = tx.kind().to() { - let account = &journal.load_account_code(to)?.info; + let account = &journal.load_account_with_code(to)?.info; if let Some(Bytecode::Eip7702(eip7702_bytecode)) = &account.code { let delegated_address = eip7702_bytecode.delegated_address; - let account = &journal.load_account_code(delegated_address)?.info; + let account = &journal.load_account_with_code(delegated_address)?.info; Some(( account.code.clone().unwrap_or_default(), account.code_hash(), diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index b299831a23..bd0471d717 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -39,12 +39,15 @@ pub fn reimburse_caller( let effective_gas_price = context.tx().effective_gas_price(basefee); // Return balance of not spend gas. - context.journal_mut().balance_incr( - caller, - U256::from( - effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128), - ) + additional_refund, - )?; + context + .journal_mut() + .load_account_mut(caller)? + .incr_balance( + U256::from( + effective_gas_price + .saturating_mul((gas.remaining() + gas.refunded() as u64) as u128), + ) + additional_refund, + ); Ok(()) } @@ -55,23 +58,22 @@ pub fn reward_beneficiary( context: &mut CTX, gas: &Gas, ) -> Result<(), ::Error> { - let beneficiary = context.block().beneficiary(); - let basefee = context.block().basefee() as u128; - let effective_gas_price = context.tx().effective_gas_price(basefee); + let (block, tx, cfg, journal, _, _) = context.all_mut(); + let basefee = block.basefee() as u128; + let effective_gas_price = tx.effective_gas_price(basefee); // Transfer fee to coinbase/beneficiary. // EIP-1559 discard basefee for coinbase transfer. Basefee amount of gas is discarded. - let coinbase_gas_price = if context.cfg().spec().into().is_enabled_in(SpecId::LONDON) { + let coinbase_gas_price = if cfg.spec().into().is_enabled_in(SpecId::LONDON) { effective_gas_price.saturating_sub(basefee) } else { effective_gas_price }; // reward beneficiary - context.journal_mut().balance_incr( - beneficiary, - U256::from(coinbase_gas_price * gas.used() as u128), - )?; + journal + .load_account_mut(block.beneficiary())? + .incr_balance(U256::from(coinbase_gas_price * gas.used() as u128)); Ok(()) } diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index a4a9d4a65c..346b79ffc3 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -13,7 +13,7 @@ use context_interface::{ Block, Cfg, Database, }; use core::cmp::Ordering; -use primitives::{eip7702, hardfork::SpecId, KECCAK_EMPTY, U256}; +use primitives::{eip7702, hardfork::SpecId, U256}; use primitives::{Address, HashMap, HashSet, StorageKey}; use state::AccountInfo; @@ -69,7 +69,7 @@ pub fn load_accounts< /// Validates caller account nonce and code according to EIP-3607. #[inline] pub fn validate_account_nonce_and_code_with_components( - caller_info: &mut AccountInfo, + caller_info: &AccountInfo, tx: impl Transaction, cfg: impl Cfg, ) -> Result<(), InvalidTransaction> { @@ -84,7 +84,7 @@ pub fn validate_account_nonce_and_code_with_components( /// Validates caller account nonce and code according to EIP-3607. #[inline] pub fn validate_account_nonce_and_code( - caller_info: &mut AccountInfo, + caller_info: &AccountInfo, tx_nonce: u64, is_eip3607_disabled: bool, is_nonce_check_disabled: bool, @@ -167,15 +167,16 @@ pub fn validate_against_state_and_deduct_caller< let (block, tx, cfg, journal, _, _) = context.all_mut(); // Load caller's account. - let caller_account = journal.load_account_code(tx.caller())?.data; + let mut caller = journal.load_account_with_code_mut(tx.caller())?.data; - validate_account_nonce_and_code_with_components(&mut caller_account.info, tx, cfg)?; + validate_account_nonce_and_code_with_components(&caller.info, tx, cfg)?; - let new_balance = calculate_caller_fee(caller_account.info.balance, tx, block, cfg)?; + let new_balance = calculate_caller_fee(*caller.balance(), tx, block, cfg)?; - let old_balance = caller_account.caller_initial_modification(new_balance, tx.kind().is_call()); - - journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); + caller.set_balance(new_balance); + if tx.kind().is_call() { + caller.bump_nonce(); + } Ok(()) } @@ -217,7 +218,7 @@ pub fn apply_eip7702_auth_list< // warm authority account and check nonce. // 4. Add `authority` to `accessed_addresses` (as defined in [EIP-2929](./eip-2929.md).) - let mut authority_acc = journal.load_account_code(authority)?; + let mut authority_acc = journal.load_account_with_code_mut(authority)?; // 5. Verify the code of `authority` is either empty or already delegated. if let Some(bytecode) = &authority_acc.info.code { @@ -240,20 +241,8 @@ pub fn apply_eip7702_auth_list< // 8. Set the code of `authority` to be `0xef0100 || address`. This is a delegation designation. // * As a special case, if `address` is `0x0000000000000000000000000000000000000000` do not write the designation. // Clear the accounts code and reset the account's code hash to the empty hash `0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470`. - let address = authorization.address(); - let (bytecode, hash) = if address.is_zero() { - (Bytecode::default(), KECCAK_EMPTY) - } else { - let bytecode = Bytecode::new_eip7702(address); - let hash = bytecode.hash_slow(); - (bytecode, hash) - }; - authority_acc.info.code_hash = hash; - authority_acc.info.code = Some(bytecode); - // 9. Increase the nonce of `authority` by one. - authority_acc.info.nonce = authority_acc.info.nonce.saturating_add(1); - authority_acc.mark_touch(); + authority_acc.delegate(authorization.address()); } let refunded_gas = diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index cd9a3462cd..5f4f4ed16d 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -6,7 +6,7 @@ use crate::{ L1BlockInfo, OpHaltReason, OpSpecId, }; use revm::{ - context::{result::InvalidTransaction, LocalContextTr}, + context::{journaled_state::JournalCheckpoint, result::InvalidTransaction, LocalContextTr}, context_interface::{ context::ContextError, result::{EVMError, ExecutionResult, FromStringError}, @@ -109,7 +109,7 @@ where let blob_price = block.blob_gasprice().unwrap_or_default(); // deposit skips max fee check and just deducts the effective balance spending. - let caller_account = journal.load_account_code(tx.caller())?.data; + let mut caller = journal.load_account_with_code_mut(tx.caller())?.data; let effective_balance_spending = tx .effective_balance_spending(basefee, blob_price) @@ -117,9 +117,8 @@ where - tx.value(); // Mind value should be added first before subtracting the effective balance spending. - let mut new_balance = caller_account - .info - .balance + let mut new_balance = caller + .balance() .saturating_add(U256::from(tx.mint().unwrap_or_default())) .saturating_sub(effective_balance_spending); @@ -129,12 +128,11 @@ where new_balance = new_balance.max(tx.value()); } - let old_balance = - caller_account.caller_initial_modification(new_balance, tx.kind().is_call()); - - // NOTE: all changes to the caller account should journaled so in case of error - // we can revert the changes. - journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); + // set the new balance and bump the nonce if it is a call + caller.set_balance(new_balance); + if tx.kind().is_call() { + caller.bump_nonce(); + } return Ok(()); } @@ -145,10 +143,10 @@ where *chain = L1BlockInfo::try_fetch(journal.db_mut(), block.number(), spec)?; } - let caller_account = journal.load_account_code(tx.caller())?.data; + let mut caller_account = journal.load_account_with_code_mut(tx.caller())?.data; // validates account nonce and code - validate_account_nonce_and_code_with_components(&mut caller_account.info, tx, cfg)?; + validate_account_nonce_and_code_with_components(&caller_account.info, tx, cfg)?; // check additional cost and deduct it from the caller's balances let mut balance = caller_account.info.balance; @@ -167,10 +165,11 @@ where let balance = calculate_caller_fee(balance, tx, block, cfg)?; - let old_balance = caller_account.caller_initial_modification(balance, tx.kind().is_call()); - // NOTE: all changes to the caller account should journaled so in case of error - // we can revert the changes. - journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); + // make changes to the account + caller_account.set_balance(balance); + if tx.kind().is_call() { + caller_account.bump_nonce(); + } Ok(()) } @@ -382,9 +381,11 @@ where let mint = tx.mint(); let is_system_tx = tx.is_system_transaction(); let gas_limit = tx.gas_limit(); + let journal = evm.ctx().journal_mut(); // discard all changes of this transaction - evm.ctx().journal_mut().discard_tx(); + // Default JournalCheckpoint is the first checkpoint and will wipe all changes. + journal.checkpoint_revert(JournalCheckpoint::default()); // If the transaction is a deposit transaction and it failed // for any reason, the caller nonce must be bumped, and the @@ -395,23 +396,12 @@ where // Increment sender nonce and account balance for the mint amount. Deposits // always persist the mint amount, even if the transaction fails. - let acc: &mut revm::state::Account = evm.ctx().journal_mut().load_account(caller)?.data; + let mut acc = journal.load_account_mut(caller)?; + acc.bump_nonce(); + acc.incr_balance(U256::from(mint.unwrap_or_default())); - let old_balance = acc.info.balance; - - // decrement transaction id as it was incremented when we discarded the tx. - acc.transaction_id -= 1; - acc.info.nonce = acc.info.nonce.saturating_add(1); - acc.info.balance = acc - .info - .balance - .saturating_add(U256::from(mint.unwrap_or_default())); - acc.mark_touch(); - - // add journal entry for accounts - evm.ctx() - .journal_mut() - .caller_accounting_journal_entry(caller, old_balance, true); + // We can now commit the changes. + journal.commit_tx(); // The gas used of a failed deposit post-regolith is the gas // limit of the transaction. pre-regolith, it is the gas limit diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index a06534d56a..47b6b90112 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -343,6 +343,14 @@ bitflags! { } } +impl AccountStatus { + /// Returns true if the account status is touched. + #[inline] + pub fn is_touched(&self) -> bool { + self.contains(AccountStatus::Touched) + } +} + impl Default for AccountStatus { fn default() -> Self { AccountStatus::empty() diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index 269e7e8c68..6af6e70e7f 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -60,6 +60,7 @@ impl Backend { impl JournalTr for Backend { type Database = InMemoryDB; type State = EvmState; + type JournalEntry = JournalEntry; fn new(database: InMemoryDB) -> Self { Self::new(SpecId::default(), database) @@ -155,15 +156,15 @@ impl JournalTr for Backend { self.journaled_state.transfer_loaded(from, to, balance) } - fn load_account(&mut self, address: Address) -> Result, Infallible> { + fn load_account(&mut self, address: Address) -> Result, Infallible> { self.journaled_state.load_account(address) } - fn load_account_code( + fn load_account_with_code( &mut self, address: Address, - ) -> Result, Infallible> { - self.journaled_state.load_account_code(address) + ) -> Result, Infallible> { + self.journaled_state.load_account_with_code(address) } fn load_account_delegated( @@ -294,6 +295,20 @@ impl JournalTr for Backend { self.journaled_state .load_account_info_skip_cold_load(address, load_code, skip_cold_load) } + + fn load_account_mut_optional_code( + &mut self, + address: Address, + load_code: bool, + ) -> Result< + StateLoad< + revm::context::journaled_state::account::JournaledAccount<'_, Self::JournalEntry>, + >, + ::Error, + > { + self.journaled_state + .load_account_mut_optional_code(address, load_code) + } } impl JournalExt for Backend { diff --git a/examples/erc20_gas/src/handler.rs b/examples/erc20_gas/src/handler.rs index 8213164550..b1ff47d890 100644 --- a/examples/erc20_gas/src/handler.rs +++ b/examples/erc20_gas/src/handler.rs @@ -49,16 +49,18 @@ where let (block, tx, cfg, journal, _, _) = evm.ctx_mut().all_mut(); // load TOKEN contract - journal.load_account(TOKEN)?.data.mark_touch(); + journal.load_account_mut(TOKEN)?.touch(); // Load caller's account. - let caller_account = journal.load_account_code(tx.caller())?.data; + let mut caller_account = journal.load_account_with_code_mut(tx.caller())?; - validate_account_nonce_and_code_with_components(&mut caller_account.info, tx, cfg)?; + validate_account_nonce_and_code_with_components(&caller_account.info, tx, cfg)?; // make changes to the account. Account balance stays the same - caller_account - .caller_initial_modification(caller_account.info.balance, tx.kind().is_call()); + caller_account.touch(); + if tx.kind().is_call() { + caller_account.bump_nonce(); + } let account_balance_slot = erc_address_storage(tx.caller()); From 83bbccd696183db7d24e5204ffab2ca25ac30e37 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 28 Oct 2025 11:35:57 +0100 Subject: [PATCH 023/127] fix: hook up Cfg::memory_limit (#3129) --- crates/context/interface/src/cfg.rs | 3 +++ crates/context/src/cfg.rs | 10 ++++++++++ crates/handler/src/handler.rs | 3 ++- crates/interpreter/src/interpreter/shared_memory.rs | 9 +++++++++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/crates/context/interface/src/cfg.rs b/crates/context/interface/src/cfg.rs index 71755e5a64..c8792c47ec 100644 --- a/crates/context/interface/src/cfg.rs +++ b/crates/context/interface/src/cfg.rs @@ -64,6 +64,9 @@ pub trait Cfg { /// Returns whether the fee charge is disabled. fn is_fee_charge_disabled(&self) -> bool; + + /// Returns the limit in bytes for the memory buffer. + fn memory_limit(&self) -> u64; } /// What bytecode analysis to perform diff --git a/crates/context/src/cfg.rs b/crates/context/src/cfg.rs index 59d66901a7..2aea1efcf6 100644 --- a/crates/context/src/cfg.rs +++ b/crates/context/src/cfg.rs @@ -400,6 +400,16 @@ impl + Copy> Cfg for CfgEnv { } } } + + fn memory_limit(&self) -> u64 { + cfg_if::cfg_if! { + if #[cfg(feature = "memory_limit")] { + self.memory_limit + } else { + u64::MAX + } + } + } } impl Default for CfgEnv { diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 2c73f0e99c..01c7f56194 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -298,7 +298,8 @@ pub trait Handler { gas_limit: u64, ) -> Result { let ctx = evm.ctx_mut(); - let memory = SharedMemory::new_with_buffer(ctx.local().shared_memory_buffer().clone()); + let mut memory = SharedMemory::new_with_buffer(ctx.local().shared_memory_buffer().clone()); + memory.set_memory_limit(ctx.cfg().memory_limit()); let (tx, journal) = ctx.tx_journal_mut(); let bytecode = if let Some(&to) = tx.kind().to() { diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index deb0ffcd5e..9cebeddcf7 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -195,6 +195,15 @@ impl SharedMemory { } } + /// Sets the memory limit in bytes. + #[inline] + pub fn set_memory_limit(&mut self, limit: u64) { + #[cfg(feature = "memory_limit")] + { + self.memory_limit = limit; + } + } + #[inline] fn buffer(&self) -> &Rc>> { debug_assert!(self.buffer.is_some(), "cannot use SharedMemory::empty"); From 54c92240be12628d1b1e8318e0bf4476242d09ef Mon Sep 17 00:00:00 2001 From: Maximilian Hubert <64627729+gap-editor@users.noreply.github.com> Date: Thu, 30 Oct 2025 10:43:08 +0100 Subject: [PATCH 024/127] fix(context): avoid double reference in `Context::all()` (#3131) --- crates/context/src/context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index a16849b478..477618e011 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -70,7 +70,7 @@ impl< let block = &self.block; let tx = &self.tx; let cfg = &self.cfg; - let db = &self.journaled_state.db(); + let db = self.journaled_state.db(); let journal = &self.journaled_state; let chain = &self.chain; let local = &self.local; From e82894c827408e608e285e16b6a28fbf1dc8aa62 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 30 Oct 2025 22:06:15 +0100 Subject: [PATCH 025/127] chore: release (#3113) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 28 +++++++++++++------------- Cargo.toml | 26 ++++++++++++------------ bins/revme/CHANGELOG.md | 8 ++++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 6 ++++++ crates/bytecode/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 16 +++++++++++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 11 ++++++++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 6 ++++++ crates/database/Cargo.toml | 2 +- crates/database/interface/CHANGELOG.md | 6 ++++++ crates/database/interface/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 16 +++++++++++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 7 +++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 6 ++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 15 ++++++++++++++ crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 6 ++++++ crates/precompile/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 6 ++++++ crates/revm/Cargo.toml | 2 +- crates/state/CHANGELOG.md | 6 ++++++ crates/state/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 6 ++++++ crates/statetest-types/Cargo.toml | 2 +- 30 files changed, 162 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7ad44be63d..678992f791 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "11.2.0" +version = "12.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "30.2.0" +version = "30.2.1" dependencies = [ "revm-bytecode", "revm-context", @@ -3552,7 +3552,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.0.2" +version = "7.1.0" dependencies = [ "bitvec", "paste", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "10.1.2" +version = "11.0.0" dependencies = [ "bitvec", "cfg-if", @@ -3580,7 +3580,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "11.1.2" +version = "12.0.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3594,7 +3594,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.2" +version = "9.0.3" dependencies = [ "alloy-eips", "alloy-provider", @@ -3610,7 +3610,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.3" +version = "8.0.4" dependencies = [ "auto_impl", "either", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "11.2.0" +version = "11.3.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "11.2.0" +version = "11.2.1" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "28.0.0" +version = "28.0.1" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "28.1.1" +version = "29.0.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3724,7 +3724,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.0.2" +version = "8.1.0" dependencies = [ "bitflags", "revm-bytecode", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "10.2.0" +version = "10.2.1" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "8.3.0" +version = "8.3.1" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 10d511308c..ed005f3bed 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "30.2.0", default-features = false } +revm = { path = "crates/revm", version = "30.2.1", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.1", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.0.2", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "9.0.2", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.3", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "8.0.2", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "28.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.2.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "28.1.1", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.2.0", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "10.1.2", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "11.1.2", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "11.2.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "11.2.0", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.0", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "9.0.3", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.4", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "8.1.0", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "28.0.1", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.2.1", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.0.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.2.1", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "11.0.0", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.0.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "11.3.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.0.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 76741cdceb..129542660e 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.3.1](https://github.com/bluealloy/revm/compare/revme-v8.3.0...revme-v8.3.1) - 2025-10-30 + +### Other + +- consolidate revme imports ([#3088](https://github.com/bluealloy/revm/pull/3088)) +- Update blockchaintest.rs ([#3107](https://github.com/bluealloy/revm/pull/3107)) +- typo eip4788 ([#3111](https://github.com/bluealloy/revm/pull/3111)) + ## [8.3.0](https://github.com/bluealloy/revm/compare/revme-v8.2.2...revme-v8.3.0) - 2025-10-17 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index a1a7a10e32..09e47dfb6c 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "8.3.0" +version = "8.3.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index bc50b15a1c..8f1d0d3d09 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.1.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.0.2...revm-bytecode-v7.1.0) - 2025-10-30 + +### Added + +- impl `Sealable` for `Bytecode` ([#3118](https://github.com/bluealloy/revm/pull/3118)) + ## [7.0.2](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.0.1...revm-bytecode-v7.0.2) - 2025-10-15 ### Other diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index c69af45246..a69ab428c3 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "7.0.2" +version = "7.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 20c171b98f..5c57ee268a 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.0.0](https://github.com/bluealloy/revm/compare/revm-context-v10.1.2...revm-context-v11.0.0) - 2025-10-30 + +### Added + +- JournaledAccount, a nice way to update and track changes ([#3086](https://github.com/bluealloy/revm/pull/3086)) +- dont load access list immediately ([#3116](https://github.com/bluealloy/revm/pull/3116)) + +### Fixed + +- *(context)* avoid double reference in `Context::all()` ([#3131](https://github.com/bluealloy/revm/pull/3131)) +- hook up Cfg::memory_limit ([#3129](https://github.com/bluealloy/revm/pull/3129)) + +### Other + +- journal transfer fn cleanup ([#3085](https://github.com/bluealloy/revm/pull/3085)) + ## [10.1.2](https://github.com/bluealloy/revm/compare/revm-context-v10.1.1...revm-context-v10.1.2) - 2025-10-15 ### Other diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index f554eba269..dcbc859cc8 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "10.1.2" +version = "11.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index 318df1a825..d65928d1af 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v11.1.2...revm-context-interface-v12.0.0) - 2025-10-30 + +### Added + +- JournaledAccount, a nice way to update and track changes ([#3086](https://github.com/bluealloy/revm/pull/3086)) +- dont load access list immediately ([#3116](https://github.com/bluealloy/revm/pull/3116)) + +### Fixed + +- hook up Cfg::memory_limit ([#3129](https://github.com/bluealloy/revm/pull/3129)) + ## [11.1.2](https://github.com/bluealloy/revm/compare/revm-context-interface-v11.1.1...revm-context-interface-v11.1.2) - 2025-10-15 ### Other diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 8dd2962c88..753fc63b2a 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "11.1.2" +version = "12.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index debbba7d98..182e91dd72 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.3](https://github.com/bluealloy/revm/compare/revm-database-v9.0.2...revm-database-v9.0.3) - 2025-10-30 + +### Other + +- updated the following local packages: revm-bytecode, revm-state, revm-database-interface + ## [9.0.2](https://github.com/bluealloy/revm/compare/revm-database-v9.0.1...revm-database-v9.0.2) - 2025-10-15 ### Other diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 7173ba3d0e..9d96f60f23 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "9.0.2" +version = "9.0.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/interface/CHANGELOG.md b/crates/database/interface/CHANGELOG.md index 065a59891f..ac012d6fe0 100644 --- a/crates/database/interface/CHANGELOG.md +++ b/crates/database/interface/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.0.4](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.3...revm-database-interface-v8.0.4) - 2025-10-30 + +### Other + +- updated the following local packages: revm-state + ## [8.0.3](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.2...revm-database-interface-v8.0.3) - 2025-10-15 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index ddff4d8309..8029f19496 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database-interface" description = "Revm Database interface" -version = "8.0.3" +version = "8.0.4" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 12c47d51cf..62ce9c2f08 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.3.0](https://github.com/bluealloy/revm/compare/revm-handler-v11.2.0...revm-handler-v11.3.0) - 2025-10-30 + +### Added + +- JournaledAccount, a nice way to update and track changes ([#3086](https://github.com/bluealloy/revm/pull/3086)) +- dont load access list immediately ([#3116](https://github.com/bluealloy/revm/pull/3116)) + +### Fixed + +- hook up Cfg::memory_limit ([#3129](https://github.com/bluealloy/revm/pull/3129)) + +### Other + +- *(op)* use helper function in validate against state ([#3069](https://github.com/bluealloy/revm/pull/3069)) +- remove redundant alloy-eip7702 from handler dev-dependencies ([#3105](https://github.com/bluealloy/revm/pull/3105)) + ## [11.2.0](https://github.com/bluealloy/revm/compare/revm-handler-v11.1.2...revm-handler-v11.2.0) - 2025-10-17 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 429c42efa6..130b489523 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "11.2.0" +version = "11.3.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 6a4394c222..0a7040c359 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.2.1](https://github.com/bluealloy/revm/compare/revm-inspector-v11.2.0...revm-inspector-v11.2.1) - 2025-10-30 + +### Other + +- remove redundant alloy-eip7702 from handler dev-dependencies ([#3105](https://github.com/bluealloy/revm/pull/3105)) +- *(inspector)* remove redundant EthInterpreter import in either.rs ([#3093](https://github.com/bluealloy/revm/pull/3093)) + ## [11.2.0](https://github.com/bluealloy/revm/compare/revm-inspector-v11.1.2...revm-inspector-v11.2.0) - 2025-10-17 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 958b5859cd..7fab8ba807 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "11.2.0" +version = "11.2.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 63f77521d8..55143eafe1 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -51,6 +51,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [28.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v28.0.0...revm-interpreter-v28.0.1) - 2025-10-30 + +### Fixed + +- hook up Cfg::memory_limit ([#3129](https://github.com/bluealloy/revm/pull/3129)) + ## [28.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v27.0.2...revm-interpreter-v28.0.0) - 2025-10-17 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index faae0394c6..329f133c5f 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "28.0.0" +version = "28.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 75a997848c..fbef6c8736 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.0.0](https://github.com/bluealloy/revm/compare/op-revm-v11.2.0...op-revm-v12.0.0) - 2025-10-30 + +### Added + +- JournaledAccount, a nice way to update and track changes ([#3086](https://github.com/bluealloy/revm/pull/3086)) + +### Fixed + +- *(jovian)* fixes the DA footprint update storage slot. fix l1 fork associated with Jovian. ([#3120](https://github.com/bluealloy/revm/pull/3120)) +- *(op-revm)* add missing enveloped_tx validation in validate_env ([#3094](https://github.com/bluealloy/revm/pull/3094)) + +### Other + +- *(op)* use helper function in validate against state ([#3069](https://github.com/bluealloy/revm/pull/3069)) + ## [11.2.0](https://github.com/bluealloy/revm/compare/op-revm-v11.1.2...op-revm-v11.2.0) - 2025-10-17 ### Other diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index c952cb4e57..231bfe077a 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "11.2.0" +version = "12.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index fc0a5a5a9d..355edb768b 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [29.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v28.1.1...revm-precompile-v29.0.0) - 2025-10-30 + +### Other + +- *(precompile)* remove unused mainnet_address() function ([#3091](https://github.com/bluealloy/revm/pull/3091)) + ## [28.1.1](https://github.com/bluealloy/revm/compare/revm-precompile-v28.1.0...revm-precompile-v28.1.1) - 2025-10-15 ### Other diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 4a80c16d98..bedc3d88a0 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "28.1.1" +version = "29.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index fed5061f54..c3ae50a98c 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [30.2.1](https://github.com/bluealloy/revm/compare/revm-v30.2.0...revm-v30.2.1) - 2025-10-30 + +### Other + +- consolidate revme imports ([#3088](https://github.com/bluealloy/revm/pull/3088)) + ## [30.2.0](https://github.com/bluealloy/revm/compare/revm-v30.1.2...revm-v30.2.0) - 2025-10-17 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index c79b2f9d7f..bcdbb96827 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "30.2.0" +version = "30.2.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index e927e782c8..8ebebfe745 100644 --- a/crates/state/CHANGELOG.md +++ b/crates/state/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.1.0](https://github.com/bluealloy/revm/compare/revm-state-v8.0.2...revm-state-v8.1.0) - 2025-10-30 + +### Added + +- JournaledAccount, a nice way to update and track changes ([#3086](https://github.com/bluealloy/revm/pull/3086)) + ## [8.0.2](https://github.com/bluealloy/revm/compare/revm-state-v8.0.1...revm-state-v8.0.2) - 2025-10-15 ### Other diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 07649c32ed..70ec2b937a 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "8.0.2" +version = "8.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 43e85bac0f..5fcddabac9 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.2.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.2.0...revm-statetest-types-v10.2.1) - 2025-10-30 + +### Other + +- updated the following local packages: revm + ## [10.2.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.1.2...revm-statetest-types-v10.2.0) - 2025-10-17 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 8a6aac680f..7f2369d6a9 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "10.2.0" +version = "10.2.1" authors.workspace = true edition.workspace = true keywords.workspace = true From c2b6326f0fe02e337f86fafb8f96ba6513412daf Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 30 Oct 2025 22:49:26 +0100 Subject: [PATCH 026/127] feat(precompiles/jovian): add jovian precompiles to revm (#3128) (#3134) * feat(precompiles/jovian): add jovian precompiles to revm (#3128) * clippy fix --------- Co-authored-by: theo <80177219+theochap@users.noreply.github.com> --- .../src/interpreter/shared_memory.rs | 2 + crates/op-revm/src/precompiles.rs | 278 ++++++++++++++++-- crates/state/src/account_info.rs | 2 +- 3 files changed, 258 insertions(+), 24 deletions(-) diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index 9cebeddcf7..f83dde5e14 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -202,6 +202,8 @@ impl SharedMemory { { self.memory_limit = limit; } + // for clippy. + let _ = limit; } #[inline] diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index f27bf339b5..025a6afbad 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -34,7 +34,8 @@ impl OpPrecompiles { | OpSpecId::ECOTONE) => Precompiles::new(spec.into_eth_spec().into()), OpSpecId::FJORD => fjord(), OpSpecId::GRANITE | OpSpecId::HOLOCENE => granite(), - OpSpecId::ISTHMUS | OpSpecId::INTEROP | OpSpecId::OSAKA | OpSpecId::JOVIAN => isthmus(), + OpSpecId::ISTHMUS => isthmus(), + OpSpecId::INTEROP | OpSpecId::OSAKA | OpSpecId::JOVIAN => jovian(), }; Self { @@ -92,6 +93,34 @@ pub fn isthmus() -> &'static Precompiles { }) } +/// Returns precompiles for jovian spec. +pub fn jovian() -> &'static Precompiles { + static INSTANCE: OnceLock = OnceLock::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = isthmus().clone(); + + let mut to_remove = Precompiles::default(); + to_remove.extend([ + bn254::pair::ISTANBUL, + bls12_381::ISTHMUS_G1_MSM, + bls12_381::ISTHMUS_G2_MSM, + bls12_381::ISTHMUS_PAIRING, + ]); + + // Replace the 4 variable-input precompiles with Jovian versions (reduced limits) + precompiles.difference(&to_remove); + + precompiles.extend([ + bn254_pair::JOVIAN, + bls12_381::JOVIAN_G1_MSM, + bls12_381::JOVIAN_G2_MSM, + bls12_381::JOVIAN_PAIRING, + ]); + + precompiles + }) +} + impl PrecompileProvider for OpPrecompiles where CTX: ContextTr>, @@ -129,7 +158,7 @@ where impl Default for OpPrecompiles { fn default() -> Self { - Self::new_with_spec(OpSpecId::ISTHMUS) + Self::new_with_spec(OpSpecId::JOVIAN) } } @@ -140,11 +169,14 @@ pub mod bn254_pair { /// Max input size for the bn254 pair precompile. pub const GRANITE_MAX_INPUT_SIZE: usize = 112687; /// Bn254 pair precompile. - pub const GRANITE: Precompile = - Precompile::new(PrecompileId::Bn254Pairing, bn254::pair::ADDRESS, run_pair); + pub const GRANITE: Precompile = Precompile::new( + PrecompileId::Bn254Pairing, + bn254::pair::ADDRESS, + run_pair_granite, + ); /// Run the bn254 pair precompile with Optimism input limit. - pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + pub fn run_pair_granite(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > GRANITE_MAX_INPUT_SIZE { return Err(PrecompileError::Bn254PairLength); } @@ -155,6 +187,28 @@ pub mod bn254_pair { gas_limit, ) } + + /// Max input size for the bn254 pair precompile. + pub const JOVIAN_MAX_INPUT_SIZE: usize = 81_984; + /// Bn254 pair precompile. + pub const JOVIAN: Precompile = Precompile::new( + PrecompileId::Bn254Pairing, + bn254::pair::ADDRESS, + run_pair_jovian, + ); + + /// Run the bn254 pair precompile with Optimism input limit. + pub fn run_pair_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > JOVIAN_MAX_INPUT_SIZE { + return Err(PrecompileError::Bn254PairLength); + } + bn254::run_pair( + input, + bn254::pair::ISTANBUL_PAIR_PER_POINT, + bn254::pair::ISTANBUL_PAIR_BASE, + gas_limit, + ) + } } /// Bls12_381 precompile. @@ -167,33 +221,67 @@ pub mod bls12_381 { /// Max input size for the g1 msm precompile. pub const ISTHMUS_G1_MSM_MAX_INPUT_SIZE: usize = 513760; + + /// The maximum input size for the BLS12-381 g1 msm operation after the Jovian Hardfork. + pub const JOVIAN_G1_MSM_MAX_INPUT_SIZE: usize = 288_960; + /// Max input size for the g2 msm precompile. pub const ISTHMUS_G2_MSM_MAX_INPUT_SIZE: usize = 488448; + + /// Max input size for the g2 msm precompile after the Jovian Hardfork. + pub const JOVIAN_G2_MSM_MAX_INPUT_SIZE: usize = 278_784; + /// Max input size for the pairing precompile. pub const ISTHMUS_PAIRING_MAX_INPUT_SIZE: usize = 235008; + /// Max input size for the pairing precompile after the Jovian Hardfork. + pub const JOVIAN_PAIRING_MAX_INPUT_SIZE: usize = 156_672; + /// G1 msm precompile. pub const ISTHMUS_G1_MSM: Precompile = - Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, run_g1_msm); + Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, run_g1_msm_isthmus); /// G2 msm precompile. pub const ISTHMUS_G2_MSM: Precompile = - Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, run_g2_msm); + Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, run_g2_msm_isthmus); /// Pairing precompile. - pub const ISTHMUS_PAIRING: Precompile = - Precompile::new(PrecompileId::Bls12Pairing, PAIRING_ADDRESS, run_pair); + pub const ISTHMUS_PAIRING: Precompile = Precompile::new( + PrecompileId::Bls12Pairing, + PAIRING_ADDRESS, + run_pair_isthmus, + ); + + /// G1 msm precompile after the Jovian Hardfork. + pub const JOVIAN_G1_MSM: Precompile = + Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, run_g1_msm_jovian); + /// G2 msm precompile after the Jovian Hardfork. + pub const JOVIAN_G2_MSM: Precompile = + Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, run_g2_msm_jovian); + /// Pairing precompile after the Jovian Hardfork. + pub const JOVIAN_PAIRING: Precompile = + Precompile::new(PrecompileId::Bls12Pairing, PAIRING_ADDRESS, run_pair_jovian); /// Run the g1 msm precompile with Optimism input limit. - pub fn run_g1_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { + pub fn run_g1_msm_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > ISTHMUS_G1_MSM_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "G1MSM input length too long for OP Stack input size limitation".to_string(), + "G1MSM input length too long for OP Stack input size limitation after the Isthmus Hardfork".to_string(), + )); + } + precompile::bls12_381::g1_msm::g1_msm(input, gas_limit) + } + + /// Run the g1 msm precompile with Optimism input limit. + pub fn run_g1_msm_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > JOVIAN_G1_MSM_MAX_INPUT_SIZE { + return Err(PrecompileError::Other( + "G1MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".to_string(), )); } precompile::bls12_381::g1_msm::g1_msm(input, gas_limit) } /// Run the g2 msm precompile with Optimism input limit. - pub fn run_g2_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { + pub fn run_g2_msm_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > ISTHMUS_G2_MSM_MAX_INPUT_SIZE { return Err(PrecompileError::Other( "G2MSM input length too long for OP Stack input size limitation".to_string(), @@ -202,8 +290,18 @@ pub mod bls12_381 { precompile::bls12_381::g2_msm::g2_msm(input, gas_limit) } + /// Run the g2 msm precompile with Optimism input limit after the Jovian Hardfork. + pub fn run_g2_msm_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > JOVIAN_G2_MSM_MAX_INPUT_SIZE { + return Err(PrecompileError::Other( + "G2MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".to_string(), + )); + } + precompile::bls12_381::g2_msm::g2_msm(input, gas_limit) + } + /// Run the pairing precompile with Optimism input limit. - pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + pub fn run_pair_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > ISTHMUS_PAIRING_MAX_INPUT_SIZE { return Err(PrecompileError::Other( "Pairing input length too long for OP Stack input size limitation".to_string(), @@ -211,18 +309,30 @@ pub mod bls12_381 { } precompile::bls12_381::pairing::pairing(input, gas_limit) } + + /// Run the pairing precompile with Optimism input limit after the Jovian Hardfork. + pub fn run_pair_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > JOVIAN_PAIRING_MAX_INPUT_SIZE { + return Err(PrecompileError::Other( + "Pairing input length too long for OP Stack input size limitation after the Jovian Hardfork".to_string(), + )); + } + precompile::bls12_381::pairing::pairing(input, gas_limit) + } } #[cfg(test)] mod tests { use crate::precompiles::bls12_381::{ - run_g1_msm, run_g2_msm, ISTHMUS_G1_MSM_MAX_INPUT_SIZE, ISTHMUS_G2_MSM_MAX_INPUT_SIZE, - ISTHMUS_PAIRING_MAX_INPUT_SIZE, + run_g1_msm_isthmus, run_g1_msm_jovian, run_g2_msm_isthmus, run_g2_msm_jovian, + ISTHMUS_G1_MSM_MAX_INPUT_SIZE, ISTHMUS_G2_MSM_MAX_INPUT_SIZE, + ISTHMUS_PAIRING_MAX_INPUT_SIZE, JOVIAN_G1_MSM_MAX_INPUT_SIZE, JOVIAN_G2_MSM_MAX_INPUT_SIZE, + JOVIAN_PAIRING_MAX_INPUT_SIZE, }; use super::*; use revm::{ - precompile::PrecompileError, + precompile::{bls12_381_const, PrecompileError}, primitives::{hex, Bytes}, }; use std::vec; @@ -248,7 +358,7 @@ mod tests { let expected = hex::decode("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(); - let outcome = bn254_pair::run_pair(&input, 260_000).unwrap(); + let outcome = bn254_pair::run_pair_granite(&input, 260_000).unwrap(); assert_eq!(outcome.bytes, expected); // Invalid input length @@ -261,20 +371,91 @@ mod tests { ) .unwrap(); - let res = bn254_pair::run_pair(&input, 260_000); + let res = bn254_pair::run_pair_granite(&input, 260_000); assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); // Valid input length shorter than 112687 let input = vec![1u8; 586 * bn254::PAIR_ELEMENT_LEN]; - let res = bn254_pair::run_pair(&input, 260_000); + let res = bn254_pair::run_pair_granite(&input, 260_000); assert!(matches!(res, Err(PrecompileError::OutOfGas))); // Input length longer than 112687 let input = vec![1u8; 587 * bn254::PAIR_ELEMENT_LEN]; - let res = bn254_pair::run_pair(&input, 260_000); + let res = bn254_pair::run_pair_granite(&input, 260_000); assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); } + #[test] + fn test_accelerated_bn254_pairing_jovian() { + const TEST_INPUT: [u8; 384] = hex!( + "2cf44499d5d27bb186308b7af7af02ac5bc9eeb6a3d147c186b21fb1b76e18da2c0f001f52110ccfe69108924926e45f0b0c868df0e7bde1fe16d3242dc715f61fb19bb476f6b9e44e2a32234da8212f61cd63919354bc06aef31e3cfaff3ebc22606845ff186793914e03e21df544c34ffe2f2f3504de8a79d9159eca2d98d92bd368e28381e8eccb5fa81fc26cf3f048eea9abfdd85d7ed3ab3698d63e4f902fe02e47887507adf0ff1743cbac6ba291e66f59be6bd763950bb16041a0a85e000000000000000000000000000000000000000000000000000000000000000130644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd451971ff0471b09fa93caaf13cbf443c1aede09cc4328f5a62aad45f40ec133eb4091058a3141822985733cbdddfed0fd8d6c104e9e9eff40bf5abfef9ab163bc72a23af9a5ce2ba2796c1f4e453a370eb0af8c212d9dc9acd8fc02c2e907baea223a8eb0b0996252cb548a4487da97b02422ebc0e834613f954de6c7e0afdc1fc" + ); + const EXPECTED_OUTPUT: [u8; 32] = + hex!("0000000000000000000000000000000000000000000000000000000000000001"); + + let res = bn254_pair::run_pair_jovian(TEST_INPUT.as_ref(), u64::MAX); + assert!(matches!(res, Ok(outcome) if **outcome.bytes == EXPECTED_OUTPUT)); + } + + #[test] + fn test_accelerated_bn254_pairing_bad_input_len_jovian() { + let input = [0u8; bn254_pair::JOVIAN_MAX_INPUT_SIZE + 1]; + let res = bn254_pair::run_pair_jovian(&input, u64::MAX); + assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); + } + + #[test] + fn test_get_jovian_precompile_with_bad_input_len() { + let precompiles = OpPrecompiles::new_with_spec(OpSpecId::JOVIAN); + let bn254_pair_precompile = precompiles + .precompiles() + .get(&bn254::pair::ADDRESS) + .unwrap(); + + let mut bad_input_len = bn254_pair::JOVIAN_MAX_INPUT_SIZE + 1; + assert!(bad_input_len < bn254_pair::GRANITE_MAX_INPUT_SIZE); + let input = vec![0u8; bad_input_len]; + + let res = bn254_pair_precompile.execute(&input, u64::MAX); + assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); + + let bls12_381_g1_msm_precompile = precompiles + .precompiles() + .get(&bls12_381_const::G1_MSM_ADDRESS) + .unwrap(); + bad_input_len = bls12_381::JOVIAN_G1_MSM_MAX_INPUT_SIZE + 1; + assert!(bad_input_len < bls12_381::ISTHMUS_G1_MSM_MAX_INPUT_SIZE); + let input = vec![0u8; bad_input_len]; + let res = bls12_381_g1_msm_precompile.execute(&input, u64::MAX); + assert!( + matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) + ); + + let bls12_381_g2_msm_precompile = precompiles + .precompiles() + .get(&bls12_381_const::G2_MSM_ADDRESS) + .unwrap(); + bad_input_len = bls12_381::JOVIAN_G2_MSM_MAX_INPUT_SIZE + 1; + assert!(bad_input_len < bls12_381::ISTHMUS_G2_MSM_MAX_INPUT_SIZE); + let input = vec![0u8; bad_input_len]; + let res = bls12_381_g2_msm_precompile.execute(&input, u64::MAX); + assert!( + matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) + ); + + let bls12_381_pairing_precompile = precompiles + .precompiles() + .get(&bls12_381_const::PAIRING_ADDRESS) + .unwrap(); + bad_input_len = bls12_381::JOVIAN_PAIRING_MAX_INPUT_SIZE + 1; + assert!(bad_input_len < bls12_381::ISTHMUS_PAIRING_MAX_INPUT_SIZE); + let input = vec![0u8; bad_input_len]; + let res = bls12_381_pairing_precompile.execute(&input, u64::MAX); + assert!( + matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) + ); + } + #[test] fn test_cancun_precompiles_in_fjord() { // additional to cancun, fjord has p256verify @@ -296,6 +477,23 @@ mod tests { assert!(new_prague_precompiles.difference(isthmus()).is_empty()) } + #[test] + fn test_prague_precompiles_in_jovian() { + let new_prague_precompiles = Precompiles::prague().difference(Precompiles::cancun()); + + // jovian contains all precompiles that were new in prague, without modifications + assert!(new_prague_precompiles.difference(jovian()).is_empty()) + } + + /// All the addresses of the precompiles in isthmus should be in jovian + #[test] + fn test_isthmus_precompiles_in_jovian() { + let new_isthmus_precompiles = isthmus().difference(Precompiles::cancun()); + + // jovian contains all precompiles that were new in isthmus, without modifications + assert!(new_isthmus_precompiles.difference(jovian()).is_empty()) + } + #[test] fn test_default_precompiles_is_latest() { let latest = OpPrecompiles::new_with_spec(OpSpecId::default()) @@ -313,7 +511,19 @@ mod tests { let oversized_input = vec![0u8; ISTHMUS_G1_MSM_MAX_INPUT_SIZE + 1]; let input = Bytes::from(oversized_input); - let res = run_g1_msm(&input, 260_000); + let res = run_g1_msm_isthmus(&input, 260_000); + + assert!( + matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) + ); + } + + #[test] + fn test_g1_jovian_max_size() { + let oversized_input = vec![0u8; JOVIAN_G1_MSM_MAX_INPUT_SIZE + 1]; + let input = Bytes::from(oversized_input); + + let res = run_g1_msm_jovian(&input, u64::MAX); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) @@ -324,7 +534,18 @@ mod tests { let oversized_input = vec![0u8; ISTHMUS_G2_MSM_MAX_INPUT_SIZE + 1]; let input = Bytes::from(oversized_input); - let res = run_g2_msm(&input, 260_000); + let res = run_g2_msm_isthmus(&input, 260_000); + + assert!( + matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) + ); + } + #[test] + fn test_g2_jovian_max_size() { + let oversized_input = vec![0u8; JOVIAN_G2_MSM_MAX_INPUT_SIZE + 1]; + let input = Bytes::from(oversized_input); + + let res = run_g2_msm_jovian(&input, u64::MAX); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) @@ -335,7 +556,18 @@ mod tests { let oversized_input = vec![0u8; ISTHMUS_PAIRING_MAX_INPUT_SIZE + 1]; let input = Bytes::from(oversized_input); - let res = bls12_381::run_pair(&input, 260_000); + let res = bls12_381::run_pair_isthmus(&input, 260_000); + + assert!( + matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) + ); + } + #[test] + fn test_pair_jovian_max_size() { + let oversized_input = vec![0u8; JOVIAN_PAIRING_MAX_INPUT_SIZE + 1]; + let input = Bytes::from(oversized_input); + + let res = bls12_381::run_pair_jovian(&input, u64::MAX); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) diff --git a/crates/state/src/account_info.rs b/crates/state/src/account_info.rs index 11e39a0e09..8c2a41aea8 100644 --- a/crates/state/src/account_info.rs +++ b/crates/state/src/account_info.rs @@ -340,7 +340,7 @@ mod tests { "Set contains account2 (since equal)" ); - let mut accounts = vec![account2.clone(), account1.clone()]; + let mut accounts = [account2.clone(), account1.clone()]; accounts.sort(); assert_eq!(accounts[0], accounts[1], "Sorted vec treats them as equal"); } From 4e8be412f31ee7c04829c04d917ff1599e9db37e Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 30 Oct 2025 23:33:05 +0100 Subject: [PATCH 027/127] bump: tag v96 revm v31.0.0 (#3135) --- CHANGELOG.md | 35 ++++++++++++ Cargo.lock | 12 ++-- Cargo.toml | 10 ++-- MIGRATION_GUIDE.md | 22 ++++++++ bins/revme/CHANGELOG.md | 2 +- bins/revme/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 2 +- crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 86 ++++++++++++++--------------- crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 8 +++ crates/primitives/CHANGELOG.md | 52 +++++++++-------- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 2 +- crates/statetest-types/Cargo.toml | 2 +- 18 files changed, 154 insertions(+), 93 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d78c5c1437..b52e253dab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,40 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v96 +date 30.10.2025 + +Regular release. + +* `revm-bytecode`: 7.0.2 -> 7.1.0 (✓ API compatible changes) +* `revm-state`: 8.0.2 -> 8.1.0 (✓ API compatible changes) +* `revm-context-interface`: 11.1.2 -> 12.0.0 (⚠ API breaking changes) +* `revm-context`: 10.1.2 -> 11.0.0 (⚠ API breaking changes) +* `revm-interpreter`: 28.0.0 -> 28.0.1 (✓ API compatible changes) +* `revm-precompile`: 28.1.1 -> 29.0.0 (⚠ API breaking changes) +* `revm-handler`: 11.2.0 -> 11.3.0 (✓ API compatible changes) +* `revm-inspector`: 11.2.0 -> 11.2.1 (✓ API compatible changes) +* `revm`: 30.2.0 -> 30.2.1 (✓ API compatible changes) +* `revme`: 8.3.0 -> 8.3.1 (✓ API compatible changes) +* `op-revm`: 11.2.0 -> 12.0.0 (⚠ API breaking changes) +* `revm-ee-tests`: 0.1.0 +* `revm-database-interface`: 8.0.3 -> 8.0.4 +* `revm-database`: 9.0.2 -> 9.0.3 +* `revm-statetest-types`: 10.2.0 -> 10.2.1 + +# v95 +date: 29.10.2025 + +op-revm bump + +* `op-revm`: 11.2.0 -> 11.3.0 + +# v94 +date: 22.10.2025 + +op-revm bump. + +* `op-revm`: 11.1.2 -> 11.2.0 + # v93 date: 17.10.2025 diff --git a/Cargo.lock b/Cargo.lock index 678992f791..0cd0e3f35d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "30.2.1" +version = "31.0.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "11.3.0" +version = "12.0.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "11.2.1" +version = "12.0.0" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "28.0.1" +version = "29.0.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "10.2.1" +version = "11.0.0" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "8.3.1" +version = "9.0.0" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index ed005f3bed..93d9fe7bc7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,19 +41,19 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "30.2.1", default-features = false } +revm = { path = "crates/revm", version = "31.0.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.1", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.0", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.3", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.4", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.1.0", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "28.0.1", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "11.2.1", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "29.0.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "12.0.0", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "10.2.1", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "11.0.0", default-features = false } context = { path = "crates/context", package = "revm-context", version = "11.0.0", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.0.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "11.3.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "12.0.0", default-features = false } op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.0.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index f404fb31b2..c4445117f8 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,26 @@ +# v95 tag ( revm v31.0.0) + +* Cfg added `memory_limit()` function +* `JournaledAccount` have been added that wraps account changes, touching and creating journal entry. + * Past function that fetches account now return a ref and new function `load_account_mut` now return `JournaledAccount` + * `JournalEntry` type is added to `JournalTr` so JournaledAccount can create it. +* `JournalTr::load_account_code` is deprecated/renamed to `JournalTr::load_account_with_code` +* `JournalTr::warm_account_and_storage` and `JournalTr::warm_account` are removed as access list is now separate from the main + Journal EvmState. Function that imports access list to the Journal is `JournalTr::warm_access_list` + +# v94 tag ( op-revm ) + +No breaking changes + +# v93 tag ( op-revm ) + +No breaking changes + +# v93 tag ( revm v30.1.0) + +No breaking changes + # v92 tag ( revm v30.1.2) No breaking changes diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 129542660e..1331904d74 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [8.3.1](https://github.com/bluealloy/revm/compare/revme-v8.3.0...revme-v8.3.1) - 2025-10-30 +## [9.0.0](https://github.com/bluealloy/revm/compare/revme-v8.3.0...revme-v9.0.0) - 2025-10-30 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 09e47dfb6c..3098088259 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "8.3.1" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 62ce9c2f08..cb15ee3b63 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [11.3.0](https://github.com/bluealloy/revm/compare/revm-handler-v11.2.0...revm-handler-v11.3.0) - 2025-10-30 +## [12.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v11.2.0...revm-handler-v12.0.0) - 2025-10-30 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 130b489523..111cc4469b 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "11.3.0" +version = "12.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 0a7040c359..58df77ca34 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [11.2.1](https://github.com/bluealloy/revm/compare/revm-inspector-v11.2.0...revm-inspector-v11.2.1) - 2025-10-30 +## [12.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v11.2.0...revm-inspector-v12.0.0) - 2025-10-30 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 7fab8ba807..2513b63832 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "11.2.1" +version = "12.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 55143eafe1..022b7212d5 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,50 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [25.0.2](https://github.com/bluealloy/revm/compare/revm-interpreter-v25.0.1...revm-interpreter-v25.0.2) - 2025-08-23 - -### Fixed - -- *(interpreter)* correct CreateContractStartingWithEF halt mapping ([#2890](https://github.com/bluealloy/revm/pull/2890)) - -## [25.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v25.0.0...revm-interpreter-v25.0.1) - 2025-08-12 - -### Other - -- updated the following local packages: revm-primitives, revm-bytecode, revm-context-interface - -## [25.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v24.0.0...revm-interpreter-v25.0.0) - 2025-08-06 - -### Added - -- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) -- gastable, record static gas in Interpreter loop ([#2822](https://github.com/bluealloy/revm/pull/2822)) - -### Fixed - -- map new once and for all (+ci) ([#2852](https://github.com/bluealloy/revm/pull/2852)) - -### Other - -- *(deps)* bump ruint ([#2811](https://github.com/bluealloy/revm/pull/2811)) -- specialize halt, making instruction code very slightly smaller ([#2840](https://github.com/bluealloy/revm/pull/2840)) -- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) -- add debug assertions to set_action ([#2832](https://github.com/bluealloy/revm/pull/2832)) -- improve ExtBytecode hash handling ([#2826](https://github.com/bluealloy/revm/pull/2826)) -- fix inspector, cleanup loop ([#2797](https://github.com/bluealloy/revm/pull/2797)) -- start InstructionResult at 1 ([#2802](https://github.com/bluealloy/revm/pull/2802)) -- fix typos ([#2800](https://github.com/bluealloy/revm/pull/2800)) -- improve inspector loop ([#2776](https://github.com/bluealloy/revm/pull/2776)) -- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) -- collapse debug info for interpreter macros ([#2780](https://github.com/bluealloy/revm/pull/2780)) -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - ## [28.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v28.0.0...revm-interpreter-v28.0.1) - 2025-10-30 ### Fixed @@ -127,6 +83,48 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - updated the following local packages: revm-context-interface +## [25.0.2](https://github.com/bluealloy/revm/compare/revm-interpreter-v25.0.1...revm-interpreter-v25.0.2) - 2025-08-23 + +### Fixed + +- *(interpreter)* correct CreateContractStartingWithEF halt mapping ([#2890](https://github.com/bluealloy/revm/pull/2890)) + +## [25.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v25.0.0...revm-interpreter-v25.0.1) - 2025-08-12 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode, revm-context-interface + +## [25.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v24.0.0...revm-interpreter-v25.0.0) - 2025-08-06 + +### Added + +- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) +- gastable, record static gas in Interpreter loop ([#2822](https://github.com/bluealloy/revm/pull/2822)) + +### Fixed + +- map new once and for all (+ci) ([#2852](https://github.com/bluealloy/revm/pull/2852)) + +### Other + +- *(deps)* bump ruint ([#2811](https://github.com/bluealloy/revm/pull/2811)) +- specialize halt, making instruction code very slightly smaller ([#2840](https://github.com/bluealloy/revm/pull/2840)) +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add debug assertions to set_action ([#2832](https://github.com/bluealloy/revm/pull/2832)) +- improve ExtBytecode hash handling ([#2826](https://github.com/bluealloy/revm/pull/2826)) +- fix inspector, cleanup loop ([#2797](https://github.com/bluealloy/revm/pull/2797)) +- start InstructionResult at 1 ([#2802](https://github.com/bluealloy/revm/pull/2802)) +- fix typos ([#2800](https://github.com/bluealloy/revm/pull/2800)) +- improve inspector loop ([#2776](https://github.com/bluealloy/revm/pull/2776)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) +- collapse debug info for interpreter macros ([#2780](https://github.com/bluealloy/revm/pull/2780)) +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + ## [24.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v23.0.2...revm-interpreter-v24.0.0) - 2025-07-23 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 329f133c5f..a7b8d4bafe 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "28.0.1" +version = "29.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index fbef6c8736..25462fe9e0 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -22,6 +22,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - *(op)* use helper function in validate against state ([#3069](https://github.com/bluealloy/revm/pull/3069)) + +## [11.3.0](https://github.com/bluealloy/revm/compare/op-revm-v11.2.0...op-revm-v11.3.0) - 2025-10-28 + +### Added + +- *(precompiles/jovian)* add jovian precompiles to revm ([#3128](https://github.com/bluealloy/revm/pull/3128)) + + ## [11.2.0](https://github.com/bluealloy/revm/compare/op-revm-v11.1.2...op-revm-v11.2.0) - 2025-10-17 ### Other diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index 7555bd7110..a97836c7a1 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -7,33 +7,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [20.2.1](https://github.com/bluealloy/revm/compare/revm-primitives-v20.2.0...revm-primitives-v20.2.1) - 2025-08-12 - -### Other - -- small performance and safety improvements ([#2868](https://github.com/bluealloy/revm/pull/2868)) - -## [20.2.0](https://github.com/bluealloy/revm/compare/revm-primitives-v20.1.0...revm-primitives-v20.2.0) - 2025-08-06 - -### Added - -- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) - -### Other - -- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) -- improve primitives crate documentation and consistency ([#2829](https://github.com/bluealloy/revm/pull/2829)) -- reuse global crypto provide idea ([#2786](https://github.com/bluealloy/revm/pull/2786)) -- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) -- add OnceLock re-export with no_std support ([#2787](https://github.com/bluealloy/revm/pull/2787)) -# Changelog -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -## [Unreleased] - ## [21.0.1](https://github.com/bluealloy/revm/compare/revm-primitives-v21.0.0...revm-primitives-v21.0.1) - 2025-10-15 ### Other @@ -60,6 +33,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - *(cleanup)* Remove EIP-7918 related functions and EIP file ([#2925](https://github.com/bluealloy/revm/pull/2925)) - cargo update ([#2930](https://github.com/bluealloy/revm/pull/2930)) +## [20.2.1](https://github.com/bluealloy/revm/compare/revm-primitives-v20.2.0...revm-primitives-v20.2.1) - 2025-08-12 + +### Other + +- small performance and safety improvements ([#2868](https://github.com/bluealloy/revm/pull/2868)) + +## [20.2.0](https://github.com/bluealloy/revm/compare/revm-primitives-v20.1.0...revm-primitives-v20.2.0) - 2025-08-06 + +### Added + +- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- improve primitives crate documentation and consistency ([#2829](https://github.com/bluealloy/revm/pull/2829)) +- reuse global crypto provide idea ([#2786](https://github.com/bluealloy/revm/pull/2786)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) +- add OnceLock re-export with no_std support ([#2787](https://github.com/bluealloy/revm/pull/2787)) +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + ## [20.1.0](https://github.com/bluealloy/revm/compare/revm-primitives-v20.0.0...revm-primitives-v20.1.0) - 2025-07-23 ### Added diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index c3ae50a98c..cce586db27 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [30.2.1](https://github.com/bluealloy/revm/compare/revm-v30.2.0...revm-v30.2.1) - 2025-10-30 +## [31.0.0](https://github.com/bluealloy/revm/compare/revm-v30.2.0...revm-v31.0.0) - 2025-10-30 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index bcdbb96827..e31e1d847d 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "30.2.1" +version = "31.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 5fcddabac9..865bd5a169 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [10.2.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.2.0...revm-statetest-types-v10.2.1) - 2025-10-30 +## [11.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.2.0...revm-statetest-types-v11.0.0) - 2025-10-30 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 7f2369d6a9..2c6f8180b3 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "10.2.1" +version = "11.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true From 663dab691db1b1322104848c7ac0d34e6255855b Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 31 Oct 2025 00:08:24 +0100 Subject: [PATCH 028/127] fix(revme): use primitive hashmap in statetest (#3137) --- bins/revme/src/cmd/blockchaintest.rs | 6 +++--- crates/statetest-types/src/test_unit.rs | 7 +++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 763aeaf122..8f60690b3d 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -300,12 +300,12 @@ impl DebugInfo { fn capture_committed_state( state: &State, ) -> HashMap)> { - let mut committed_state = HashMap::new(); + let mut committed_state = HashMap::default(); // Access the cache state to get all accounts for (address, cache_account) in &state.cache.accounts { if let Some(plain_account) = &cache_account.account { - let mut storage = HashMap::new(); + let mut storage = HashMap::default(); for (key, value) in &plain_account.storage { storage.insert(*key, *value); } @@ -649,7 +649,7 @@ fn execute_blockchain_test( let mut state = State::builder().build(); // Capture pre-state for debug info - let mut pre_state_debug = HashMap::new(); + let mut pre_state_debug = HashMap::default(); // Insert genesis state into database let genesis_state = test_case.pre.clone().into_genesis_state(); diff --git a/crates/statetest-types/src/test_unit.rs b/crates/statetest-types/src/test_unit.rs index d02b6f1469..c877fe2bcd 100644 --- a/crates/statetest-types/src/test_unit.rs +++ b/crates/statetest-types/src/test_unit.rs @@ -1,13 +1,12 @@ -use serde::Deserialize; -use std::collections::{BTreeMap, HashMap}; - use crate::{AccountInfo, Env, SpecName, Test, TransactionParts}; use revm::{ context::{block::BlockEnv, cfg::CfgEnv}, database::CacheState, - primitives::{hardfork::SpecId, keccak256, Address, Bytes, B256}, + primitives::{hardfork::SpecId, keccak256, Address, Bytes, HashMap, B256}, state::Bytecode, }; +use serde::Deserialize; +use std::collections::BTreeMap; /// Single test unit struct #[derive(Debug, PartialEq, Eq, Deserialize)] From a1fdb9d9e98f9dd14b7577edbad49c139ab53b16 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 4 Nov 2025 14:10:32 +0100 Subject: [PATCH 029/127] feat: selfdestruct oog on cold load (#3140) --- crates/context/interface/src/host.rs | 8 +++++--- crates/context/interface/src/journaled_state.rs | 3 ++- crates/context/src/context.rs | 12 ++++++++---- crates/context/src/journal.rs | 7 +++++-- crates/context/src/journal/inner.rs | 5 +++-- crates/interpreter/src/instructions/host.rs | 17 +++++++++-------- examples/cheatcode_inspector/src/main.rs | 6 ++++-- 7 files changed, 36 insertions(+), 22 deletions(-) diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index 608edb53da..833346696a 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -72,7 +72,8 @@ pub trait Host { &mut self, address: Address, target: Address, - ) -> Option>; + skip_cold_load: bool, + ) -> Result, LoadError>; /// Log, calls `ContextTr::journal_mut().log(log)` fn log(&mut self, log: Log); @@ -263,8 +264,9 @@ impl Host for DummyHost { &mut self, _address: Address, _target: Address, - ) -> Option> { - None + _skip_cold_load: bool, + ) -> Result, LoadError> { + Err(LoadError::ColdLoadSkipped) } fn log(&mut self, _log: Log) {} diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 3b9c8d837b..6fc109ab72 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -92,7 +92,8 @@ pub trait JournalTr { &mut self, address: Address, target: Address, - ) -> Result, ::Error>; + skip_cold_load: bool, + ) -> Result, JournalLoadError<::Error>>; /// Sets access list inside journal. fn warm_access_list(&mut self, access_list: HashMap>); diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 477618e011..55baa11ccb 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -526,13 +526,17 @@ impl< &mut self, address: Address, target: Address, - ) -> Option> { + skip_cold_load: bool, + ) -> Result, LoadError> { self.journal_mut() - .selfdestruct(address, target) + .selfdestruct(address, target, skip_cold_load) .map_err(|e| { - *self.error() = Err(e.into()); + let (ret, err) = e.into_parts(); + if let Some(err) = err { + *self.error() = Err(err.into()); + } + ret }) - .ok() } #[inline] diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index c7e4630570..d2c04bdfaf 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -146,8 +146,11 @@ impl JournalTr for Journal { &mut self, address: Address, target: Address, - ) -> Result, DB::Error> { - self.inner.selfdestruct(&mut self.database, address, target) + skip_cold_load: bool, + ) -> Result, JournalLoadError<::Error>> + { + self.inner + .selfdestruct(&mut self.database, address, target, skip_cold_load) } #[inline] diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a478c4e2d0..30bc1bd31e 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -497,9 +497,10 @@ impl JournalInner { db: &mut DB, address: Address, target: Address, - ) -> Result, DB::Error> { + skip_cold_load: bool, + ) -> Result, JournalLoadError<::Error>> { let spec = self.spec; - let account_load = self.load_account(db, target)?; + let account_load = self.load_account_optional(db, target, false, skip_cold_load)?; let is_cold = account_load.is_cold; let is_empty = account_load.state_clear_aware_is_empty(spec); diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index b68f284e2e..b60a5c9c76 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -395,14 +395,15 @@ pub fn selfdestruct( // static gas gas!(context.interpreter, gas::static_selfdestruct_cost(spec)); - let Some(res) = context - .host - .selfdestruct(context.interpreter.input.target_address(), target) - else { - context - .interpreter - .halt(InstructionResult::FatalExternalError); - return; + let skip_cold = context.interpreter.gas.remaining() < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + let res = match context.host.selfdestruct( + context.interpreter.input.target_address(), + target, + skip_cold, + ) { + Ok(res) => res, + Err(LoadError::ColdLoadSkipped) => return context.interpreter.halt_oog(), + Err(LoadError::DBError) => return context.interpreter.halt_fatal(), }; gas!(context.interpreter, gas::dyn_selfdestruct_cost(spec, &res)); diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index 6af6e70e7f..fd71c70f9b 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -107,8 +107,10 @@ impl JournalTr for Backend { &mut self, address: Address, target: Address, - ) -> Result, Infallible> { - self.journaled_state.selfdestruct(address, target) + skip_cold_load: bool, + ) -> Result, JournalLoadError> { + self.journaled_state + .selfdestruct(address, target, skip_cold_load) } fn warm_access_list( From 3ac56c33db8e54426c8f0115d2c366972e0d36dc Mon Sep 17 00:00:00 2001 From: sashass1315 Date: Thu, 6 Nov 2025 15:00:09 +0200 Subject: [PATCH 030/127] chore(interpreter): deprecate public otry! macro (#3146) --- crates/interpreter/src/instructions/macros.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 7e675dc74c..791400643f 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -28,6 +28,10 @@ macro_rules! require_non_staticcall { /// Similar to the `?` operator but for use in instruction implementations. #[macro_export] #[collapse_debuginfo(yes)] +#[deprecated( + since = "29.0.0", + note = "Prefer `let Some(x) = expr else { return; };` for early return in instruction functions" +)] macro_rules! otry { ($expression: expr) => {{ let Some(value) = $expression else { From eee4dac977cf7e701e99474d441d0905e1d87f55 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 6 Nov 2025 14:56:23 +0100 Subject: [PATCH 031/127] chore: add eq/serde for InitialAndFloorGas (#3147) --- crates/interpreter/src/gas/calc.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 9ce3bea23b..89414c1294 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -361,7 +361,8 @@ pub const fn memory_gas(num_words: usize) -> u64 { } /// Init and floor gas from transaction -#[derive(Clone, Copy, Debug, Default)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct InitialAndFloorGas { /// Initial gas for transaction. pub initial_gas: u64, From 5d02c78cf90ec575daa69c13e0955f2f24a1e61c Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 7 Nov 2025 05:11:07 +0100 Subject: [PATCH 032/127] fix: use access list to decide if slot is cold (#3149) * fix: use access list to decide if slot is cold * add test --- crates/context/src/journal/inner.rs | 52 ++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 30bc1bd31e..d3137fbe2a 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -764,7 +764,10 @@ impl JournalInner { (slot.present_value, is_cold) } Entry::Vacant(vac) => { - if skip_cold_load { + // is storage cold + let is_cold = !self.warm_addresses.is_storage_warm(&address, &key); + + if is_cold && skip_cold_load { return Err(JournalLoadError::ColdLoadSkipped); } // if storage was cleared, we don't need to ping db. @@ -775,9 +778,6 @@ impl JournalInner { }; vac.insert(EvmStorageSlot::new(value, self.transaction_id)); - // is storage cold - let is_cold = !self.warm_addresses.is_storage_warm(&address, &key); - (value, is_cold) } }; @@ -890,3 +890,47 @@ impl JournalInner { self.logs.push(log); } } + +#[cfg(test)] +mod tests { + use super::*; + use context_interface::journaled_state::entry::JournalEntry; + use database_interface::EmptyDB; + use primitives::{address, HashSet, U256}; + use state::AccountInfo; + + #[test] + fn test_sload_skip_cold_load() { + let mut journal = JournalInner::::new(); + let test_address = address!("1000000000000000000000000000000000000000"); + let test_key = U256::from(1); + + // Insert account into state + let account_info = AccountInfo { + balance: U256::from(1000), + nonce: 1, + code_hash: KECCAK_EMPTY, + code: Some(Bytecode::default()), + }; + journal + .state + .insert(test_address, Account::from(account_info)); + + // Add storage slot to access list (make it warm) + let mut access_list = HashMap::default(); + let mut storage_keys = HashSet::default(); + storage_keys.insert(test_key); + access_list.insert(test_address, storage_keys); + journal.warm_addresses.set_access_list(access_list); + + // Try to sload with skip_cold_load=true - should succeed because slot is in access list + let mut db = EmptyDB::new(); + let result = journal.sload(&mut db, test_address, test_key, true); + + // Should succeed and return as warm + assert!(result.is_ok()); + let state_load = result.unwrap(); + assert!(!state_load.is_cold); // Should be warm + assert_eq!(state_load.data, U256::ZERO); // Empty slot + } +} From 1d00e142c484965669302e1d2ade103ed8ab0f5e Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Nov 2025 12:37:30 +0100 Subject: [PATCH 033/127] feat: add gas refund to PrecompileOutput (#3152) --- crates/handler/src/precompile_provider.rs | 1 + crates/precompile/src/interface.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index b6224c6a4e..98583d6a65 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -120,6 +120,7 @@ impl PrecompileProvider for EthPrecompiles { match exec_result { Ok(output) => { + result.gas.record_refund(output.gas_refunded); let underflow = result.gas.record_cost(output.gas_used); assert!(underflow, "Gas underflow is not possible"); result.result = if output.reverted { diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index f05cd83bf4..3fff76b743 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -29,6 +29,8 @@ pub type PrecompileResult = Result; pub struct PrecompileOutput { /// Gas used by the precompile pub gas_used: u64, + /// Gas refunded by the precompile. + pub gas_refunded: i64, /// Output bytes pub bytes: Bytes, /// Whether the precompile reverted @@ -40,6 +42,7 @@ impl PrecompileOutput { pub fn new(gas_used: u64, bytes: Bytes) -> Self { Self { gas_used, + gas_refunded: 0, bytes, reverted: false, } @@ -49,6 +52,7 @@ impl PrecompileOutput { pub fn new_reverted(gas_used: u64, bytes: Bytes) -> Self { Self { gas_used, + gas_refunded: 0, bytes, reverted: true, } From 46aad931143311c4a7fd52c2b965bf1704aeed4e Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Nov 2025 15:44:37 +0100 Subject: [PATCH 034/127] fix(op): Ensure L1Block account is always loaded (#3150) (#3154) * fix(op): Ensure L1Block account is always loaded * dont panic on State::storage fn * add test for pre regolit tx --- crates/database/src/states/state.rs | 55 +++--- crates/ee-tests/src/op_revm_tests.rs | 42 ++++- .../test_l1block_load_for_regolit.json | 165 ++++++++++++++++++ crates/op-revm/src/l1block.rs | 9 +- 4 files changed, 237 insertions(+), 34 deletions(-) create mode 100644 crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 22f8263343..d3feb3b488 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -258,33 +258,36 @@ impl Database for State { address: Address, index: StorageKey, ) -> Result { - // Account is guaranteed to be loaded. - // Note that storage from bundle is already loaded with account. - if let Some(account) = self.cache.accounts.get_mut(&address) { - // Account will always be some, but if it is not, StorageValue::ZERO will be returned. - let is_storage_known = account.status.is_storage_known(); - Ok(account - .account - .as_mut() - .map(|account| match account.storage.entry(index) { - hash_map::Entry::Occupied(entry) => Ok(*entry.get()), - hash_map::Entry::Vacant(entry) => { - // If account was destroyed or account is newly built - // we return zero and don't ask database. - let value = if is_storage_known { - StorageValue::ZERO - } else { - self.database.storage(address, index)? - }; - entry.insert(value); - Ok(value) - } - }) - .transpose()? - .unwrap_or_default()) + // If account is not found in cache, it will be loaded from database. + let account = if let Some(account) = self.cache.accounts.get_mut(&address) { + account } else { - unreachable!("For accessing any storage account is guaranteed to be loaded beforehand") - } + self.load_cache_account(address)?; + // safe to unwrap as account is loaded a line above. + self.cache.accounts.get_mut(&address).unwrap() + }; + + // Account will always be some, but if it is not, StorageValue::ZERO will be returned. + let is_storage_known = account.status.is_storage_known(); + Ok(account + .account + .as_mut() + .map(|account| match account.storage.entry(index) { + hash_map::Entry::Occupied(entry) => Ok(*entry.get()), + hash_map::Entry::Vacant(entry) => { + // If account was destroyed or account is newly built + // we return zero and don't ask database. + let value = if is_storage_known { + StorageValue::ZERO + } else { + self.database.storage(address, index)? + }; + entry.insert(value); + Ok(value) + } + }) + .transpose()? + .unwrap_or_default()) } fn block_hash(&mut self, number: u64) -> Result { diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index 2b53937f50..249714cf1c 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -12,14 +12,14 @@ use revm::{ BlockEnv, CfgEnv, TxEnv, }, context_interface::result::HaltReason, - database::{BenchmarkDB, EmptyDB, BENCH_CALLER, BENCH_CALLER_BALANCE, BENCH_TARGET}, + database::{BenchmarkDB, EmptyDB, State, BENCH_CALLER, BENCH_CALLER_BALANCE, BENCH_TARGET}, handler::system_call::SYSTEM_ADDRESS, interpreter::{ gas::{calculate_initial_tx_gas, InitialAndFloorGas}, Interpreter, InterpreterTypes, }, precompile::{bls12_381_const, bls12_381_utils, bn254, secp256r1, u64_to_address}, - primitives::{bytes, eip7825, Address, Bytes, Log, TxKind, U256}, + primitives::{address, bytes, eip7825, Address, Bytes, Log, TxKind, U256}, state::Bytecode, Context, ExecuteEvm, InspectEvm, Inspector, Journal, SystemCallEvm, }; @@ -947,6 +947,44 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas() { ); } +#[test] +fn test_l1block_load_for_pre_regolith() { + const SPEC_ID: OpSpecId = OpSpecId::REGOLITH; + + let ctx = Context::op() + .with_tx( + OpTransaction::builder() + .base( + TxEnv::builder() + .caller(BENCH_CALLER) + .kind(TxKind::Call(address!( + "0x0000000000000000000000000000000000100000" + ))) + .value(U256::from(1)) + .gas_limit(100_000), + ) + .build_fill(), + ) + .modify_chain_chained(|l1_block| { + l1_block.l2_block = None; + }) + .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + + let mut evm = ctx + .with_db( + State::builder() + .with_database(BenchmarkDB::default()) + .build(), + ) + .build_op(); + let output = evm.replay().unwrap(); + + // assert out of gas + assert!(output.result.is_success()); + + compare_or_save_op_testdata("test_l1block_load_for_pre_regolith.json", &output); +} + #[test] fn test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; diff --git a/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json new file mode 100644 index 0000000000..5dcc6cd143 --- /dev/null +++ b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json @@ -0,0 +1,165 @@ +{ + "result": { + "Success": { + "gas_refunded": 0, + "gas_used": 21000, + "logs": [], + "output": { + "Call": "0x" + }, + "reason": "Stop" + } + }, + "state": { + "0x0000000000000000000000000000000000000000": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000100000": { + "info": { + "balance": "0x1", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { + "info": { + "balance": "0x2386f26fc0ffff", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 + }, + "status": "Touched", + "storage": {}, + "transaction_id": 0 + } + } +} \ No newline at end of file diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index 67f52b6b60..d39dc52ffe 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -16,7 +16,7 @@ use revm::{ gas::{get_tokens_in_calldata, NON_ZERO_BYTE_MULTIPLIER_ISTANBUL, STANDARD_TOKEN_COST}, Gas, }, - primitives::{hardfork::SpecId, U256}, + primitives::U256, }; /// L1 block info @@ -138,11 +138,8 @@ impl L1BlockInfo { l2_block: U256, spec_id: OpSpecId, ) -> Result { - // Ensure the L1 Block account is loaded into the cache after Ecotone. With EIP-4788, it is no longer the case - // that the L1 block account is loaded into the cache prior to the first inquiry for the L1 block info. - if spec_id.into_eth_spec().is_enabled_in(SpecId::CANCUN) { - let _ = db.basic(L1_BLOCK_CONTRACT)?; - } + // Ensure the L1 Block account is loaded into the cache. + let _ = db.basic(L1_BLOCK_CONTRACT)?; let mut out = L1BlockInfo { l2_block: Some(l2_block), From 6f203632f8b460a233ebc525fa93c70ff0f6bdbb Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Nov 2025 15:51:22 +0100 Subject: [PATCH 035/127] chore: merge v98 versions bumps (#3155) --- CHANGELOG.md | 37 ++++++++++++++++++++++++++ Cargo.lock | 30 ++++++++++----------- Cargo.toml | 28 +++++++++---------- bins/revme/CHANGELOG.md | 12 +++++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 6 +++++ crates/bytecode/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 12 +++++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 6 +++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 12 +++++++++ crates/database/Cargo.toml | 2 +- crates/database/interface/CHANGELOG.md | 6 +++++ crates/database/interface/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 12 +++++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 12 +++++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 6 +++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 12 +++++++++ crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 6 +++++ crates/precompile/Cargo.toml | 2 +- crates/primitives/CHANGELOG.md | 6 +++++ crates/primitives/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 12 +++++++++ crates/revm/Cargo.toml | 2 +- crates/state/CHANGELOG.md | 6 +++++ crates/state/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 12 +++++++++ crates/statetest-types/Cargo.toml | 2 +- 33 files changed, 219 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b52e253dab..a3634d1e81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,42 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v98 +date: 10.11.2025 + +Patch for loading of account on storage fetch, needed for op-reth + +* `revm-database`: 9.0.4 -> 9.0.5 (✓ API compatible changes) +* `op-revm`: 12.0.1 -> 12.0.2 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-context`: 11.0.1 -> 11.0.2 +* `revm-handler`: 12.0.1 -> 12.0.2 +* `revm-inspector`: 12.0.1 -> 12.0.2 +* `revm`: 31.0.1 -> 31.0.2 +* `revm-statetest-types`: 11.0.1 -> 11.0.2 +* `revme`: 9.0.1 -> 9.0.2 + +# v97 +date 07.11.2025 + +Patch release for a bug fix. + +* `revm-primitives`: 21.0.1 -> 21.0.2 (✓ API compatible changes) +* `revm-context`: 11.0.0 -> 11.0.1 (✓ API compatible changes) +* `revm-statetest-types`: 11.0.0 -> 11.0.1 (✓ API compatible changes) +* `revme`: 9.0.0 -> 9.0.1 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-bytecode`: 7.1.0 -> 7.1.1 +* `revm-state`: 8.1.0 -> 8.1.1 +* `revm-database-interface`: 8.0.4 -> 8.0.5 +* `revm-context-interface`: 12.0.0 -> 12.0.1 +* `revm-database`: 9.0.3 -> 9.0.4 +* `revm-interpreter`: 29.0.0 -> 29.0.1 +* `revm-precompile`: 29.0.0 -> 29.0.1 +* `revm-handler`: 12.0.0 -> 12.0.1 +* `revm-inspector`: 12.0.0 -> 12.0.1 +* `revm`: 31.0.0 -> 31.0.1 +* `op-revm`: 12.0.0 -> 12.0.1 + # v96 date 30.10.2025 diff --git a/Cargo.lock b/Cargo.lock index 0cd0e3f35d..7a062aa1ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "12.0.0" +version = "12.0.2" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "31.0.0" +version = "31.0.2" dependencies = [ "revm-bytecode", "revm-context", @@ -3552,7 +3552,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.1.0" +version = "7.1.1" dependencies = [ "bitvec", "paste", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "11.0.0" +version = "11.0.2" dependencies = [ "bitvec", "cfg-if", @@ -3580,7 +3580,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "12.0.0" +version = "12.0.1" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3594,7 +3594,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.3" +version = "9.0.5" dependencies = [ "alloy-eips", "alloy-provider", @@ -3610,7 +3610,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.4" +version = "8.0.5" dependencies = [ "auto_impl", "either", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "12.0.0" +version = "12.0.2" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "12.0.0" +version = "12.0.2" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "29.0.0" +version = "29.0.1" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "29.0.0" +version = "29.0.1" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3714,7 +3714,7 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "21.0.1" +version = "21.0.2" dependencies = [ "alloy-primitives", "num_enum", @@ -3724,7 +3724,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.1.0" +version = "8.1.1" dependencies = [ "bitflags", "revm-bytecode", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "11.0.0" +version = "11.0.2" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "9.0.0" +version = "9.0.2" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 93d9fe7bc7..663b0f2ab3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "31.0.0", default-features = false } -primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.1", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.0", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "9.0.3", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.4", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "8.1.0", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "29.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "12.0.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "11.0.0", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "11.0.0", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.0.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "12.0.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.0.0", default-features = false } +revm = { path = "crates/revm", version = "31.0.2", default-features = false } +primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "9.0.5", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "29.0.1", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "12.0.2", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.0.1", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "11.0.2", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "11.0.2", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.0.1", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "12.0.2", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.0.2", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 1331904d74..021f8e955e 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.2](https://github.com/bluealloy/revm/compare/revme-v9.0.1...revme-v9.0.2) - 2025-11-10 + +### Other + +- updated the following local packages: revm, revm-statetest-types + +## [9.0.1](https://github.com/bluealloy/revm/compare/revme-v9.0.0...revme-v9.0.1) - 2025-11-07 + +### Fixed + +- *(revme)* use primitive hashmap in statetest ([#3137](https://github.com/bluealloy/revm/pull/3137)) + ## [9.0.0](https://github.com/bluealloy/revm/compare/revme-v8.3.0...revme-v9.0.0) - 2025-10-30 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 3098088259..7de3ee3f3d 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "9.0.0" +version = "9.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index 8f1d0d3d09..4dc5acdcca 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.1.1](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.1.0...revm-bytecode-v7.1.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives + ## [7.1.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.0.2...revm-bytecode-v7.1.0) - 2025-10-30 ### Added diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index a69ab428c3..5312108ef8 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "7.1.0" +version = "7.1.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 5c57ee268a..1a850ecbbf 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.0.2](https://github.com/bluealloy/revm/compare/revm-context-v11.0.1...revm-context-v11.0.2) - 2025-11-10 + +### Other + +- updated the following local packages: revm-database + +## [11.0.1](https://github.com/bluealloy/revm/compare/revm-context-v11.0.0...revm-context-v11.0.1) - 2025-11-07 + +### Other + +- add test + ## [11.0.0](https://github.com/bluealloy/revm/compare/revm-context-v10.1.2...revm-context-v11.0.0) - 2025-10-30 ### Added diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index dcbc859cc8..6959a6d49b 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "11.0.0" +version = "11.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index d65928d1af..44f1b1932a 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.0.1](https://github.com/bluealloy/revm/compare/revm-context-interface-v12.0.0...revm-context-interface-v12.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-state, revm-database-interface + ## [12.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v11.1.2...revm-context-interface-v12.0.0) - 2025-10-30 ### Added diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 753fc63b2a..4d1d09162d 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "12.0.0" +version = "12.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index 182e91dd72..bace082cf4 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.5](https://github.com/bluealloy/revm/compare/revm-database-v9.0.4...revm-database-v9.0.5) - 2025-11-10 + +### Fixed + +- *(op)* Ensure L1Block account is always loaded ([#3150](https://github.com/bluealloy/revm/pull/3150)) + +## [9.0.4](https://github.com/bluealloy/revm/compare/revm-database-v9.0.3...revm-database-v9.0.4) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode, revm-state, revm-database-interface + ## [9.0.3](https://github.com/bluealloy/revm/compare/revm-database-v9.0.2...revm-database-v9.0.3) - 2025-10-30 ### Other diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 9d96f60f23..ed5bf165ea 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "9.0.3" +version = "9.0.5" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/interface/CHANGELOG.md b/crates/database/interface/CHANGELOG.md index ac012d6fe0..7568716ac2 100644 --- a/crates/database/interface/CHANGELOG.md +++ b/crates/database/interface/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.0.5](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.4...revm-database-interface-v8.0.5) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-state + ## [8.0.4](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.3...revm-database-interface-v8.0.4) - 2025-10-30 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index 8029f19496..f553d82806 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database-interface" description = "Revm Database interface" -version = "8.0.4" +version = "8.0.5" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index cb15ee3b63..7a3d9e0960 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.0.2](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.1...revm-handler-v12.0.2) - 2025-11-10 + +### Other + +- updated the following local packages: revm-database, revm-context + +## [12.0.1](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.0...revm-handler-v12.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-context, revm-bytecode, revm-state, revm-database-interface, revm-context-interface, revm-database, revm-interpreter, revm-precompile + ## [12.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v11.2.0...revm-handler-v12.0.0) - 2025-10-30 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 111cc4469b..278a0e643b 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "12.0.0" +version = "12.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 58df77ca34..19aa50110b 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.0.2](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.1...revm-inspector-v12.0.2) - 2025-11-10 + +### Other + +- updated the following local packages: revm-database, revm-context, revm-handler + +## [12.0.1](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.0...revm-inspector-v12.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-context, revm-state, revm-database-interface, revm-database, revm-interpreter, revm-handler + ## [12.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v11.2.0...revm-inspector-v12.0.0) - 2025-10-30 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 2513b63832..5df48f72af 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "12.0.0" +version = "12.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 022b7212d5..098648fc89 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [29.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.0...revm-interpreter-v29.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode, revm-state, revm-context-interface + ## [28.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v28.0.0...revm-interpreter-v28.0.1) - 2025-10-30 ### Fixed diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index a7b8d4bafe..ff34e2a734 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "29.0.0" +version = "29.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 25462fe9e0..80d735ec38 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.0.2](https://github.com/bluealloy/revm/compare/op-revm-v12.0.1...op-revm-v12.0.2) - 2025-11-10 + +### Fixed + +- *(op)* Ensure L1Block account is always loaded ([#3150](https://github.com/bluealloy/revm/pull/3150)) + +## [12.0.1](https://github.com/bluealloy/revm/compare/op-revm-v12.0.0...op-revm-v12.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm + ## [12.0.0](https://github.com/bluealloy/revm/compare/op-revm-v11.2.0...op-revm-v12.0.0) - 2025-10-30 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 231bfe077a..4ad21a2eee 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "12.0.0" +version = "12.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index 355edb768b..77df9e83d3 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [29.0.1](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.0...revm-precompile-v29.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives + ## [29.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v28.1.1...revm-precompile-v29.0.0) - 2025-10-30 ### Other diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index bedc3d88a0..ec0ce2a1eb 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "29.0.0" +version = "29.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index a97836c7a1..2a39fc1765 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [21.0.2](https://github.com/bluealloy/revm/compare/revm-primitives-v21.0.1...revm-primitives-v21.0.2) - 2025-11-07 + +### Other + +- tag v96 revm v31.0.0 ([#3135](https://github.com/bluealloy/revm/pull/3135)) + ## [21.0.1](https://github.com/bluealloy/revm/compare/revm-primitives-v21.0.0...revm-primitives-v21.0.1) - 2025-10-15 ### Other diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 57b4f1dfd0..044b3eb21c 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-primitives" description = "Revm primitives types" -version = "21.0.1" +version = "21.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index cce586db27..cb024fd510 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [31.0.2](https://github.com/bluealloy/revm/compare/revm-v31.0.1...revm-v31.0.2) - 2025-11-10 + +### Other + +- updated the following local packages: revm-database, revm-context, revm-handler, revm-inspector + +## [31.0.1](https://github.com/bluealloy/revm/compare/revm-v31.0.0...revm-v31.0.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-context, revm-bytecode, revm-state, revm-database-interface, revm-context-interface, revm-database, revm-interpreter, revm-precompile, revm-handler, revm-inspector + ## [31.0.0](https://github.com/bluealloy/revm/compare/revm-v30.2.0...revm-v31.0.0) - 2025-10-30 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index e31e1d847d..ad0048bcef 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "31.0.0" +version = "31.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index 8ebebfe745..63e4abe9c5 100644 --- a/crates/state/CHANGELOG.md +++ b/crates/state/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.1.1](https://github.com/bluealloy/revm/compare/revm-state-v8.1.0...revm-state-v8.1.1) - 2025-11-07 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode + ## [8.1.0](https://github.com/bluealloy/revm/compare/revm-state-v8.0.2...revm-state-v8.1.0) - 2025-10-30 ### Added diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 70ec2b937a..ff57aa2044 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "8.1.0" +version = "8.1.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 865bd5a169..84b5df21d9 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.0.2](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.1...revm-statetest-types-v11.0.2) - 2025-11-10 + +### Other + +- updated the following local packages: revm + +## [11.0.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.0...revm-statetest-types-v11.0.1) - 2025-11-07 + +### Fixed + +- *(revme)* use primitive hashmap in statetest ([#3137](https://github.com/bluealloy/revm/pull/3137)) + ## [11.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v10.2.0...revm-statetest-types-v11.0.0) - 2025-10-30 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 2c6f8180b3..317ef16513 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "11.0.0" +version = "11.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true From eb1d49fb51e8cff8d6374f5639d52e26502be872 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Nov 2025 19:22:25 +0100 Subject: [PATCH 036/127] feat: process precompile logs to inspector (#3148) * feat: process precompile logs to inspector * ci nits * no_std * std import * add log and log_full * no_std * doc * revert &Log to Log * nits rm clones --- book/src/inspector.md | 5 +- .../context/interface/src/journaled_state.rs | 9 +- crates/context/src/journal.rs | 15 +- crates/ee-tests/src/op_revm_tests.rs | 6 +- crates/handler/src/frame.rs | 11 +- crates/inspector/src/count_inspector.rs | 9 +- crates/inspector/src/either.rs | 14 +- crates/inspector/src/handler.rs | 4 +- crates/inspector/src/inspector.rs | 34 ++- crates/inspector/src/inspector_tests.rs | 2 +- crates/inspector/src/traits.rs | 21 +- .../src/interpreter_action/call_outcome.rs | 11 +- crates/op-revm/src/handler.rs | 8 +- examples/cheatcode_inspector/src/main.rs | 8 +- .../src/custom_evm.rs | 250 ++++++++++++++++++ .../src/precompile_provider.rs | 25 +- 16 files changed, 379 insertions(+), 53 deletions(-) diff --git a/book/src/inspector.md b/book/src/inspector.md index 8388132e0f..a3005bad00 100644 --- a/book/src/inspector.md +++ b/book/src/inspector.md @@ -27,7 +27,10 @@ pub trait Inspector { fn create_end(&mut self, context: &mut CTX, inputs: &CreateInputs, outcome: &mut CreateOutcome) {} // Event tracing - fn log(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) {} + fn log(&mut self, context: &mut CTX, log: Log) {} + fn log_full(&mut self, interp: &mut Interpreter, context &mut CTX, log: Log) { + self.log(context, log) + } fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {} } ``` diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 6fc109ab72..8559699677 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -87,6 +87,12 @@ pub trait JournalTr { /// Logs the log in Journal state. fn log(&mut self, log: Log); + /// Take logs from journal. + fn take_logs(&mut self) -> Vec; + + /// Returns the logs from journal. + fn logs(&self) -> &[Log]; + /// Marks the account for selfdestruction and transfers all the balance to the target. fn selfdestruct( &mut self, @@ -274,9 +280,6 @@ pub trait JournalTr { /// Returns the depth of the journal. fn depth(&self) -> usize; - /// Take logs from journal. - fn take_logs(&mut self) -> Vec; - /// Commit current transaction journal and returns transaction logs. fn commit_tx(&mut self); diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index d2c04bdfaf..dd1a85b89c 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -142,6 +142,16 @@ impl JournalTr for Journal { self.inner.log(log) } + #[inline] + fn logs(&self) -> &[Log] { + &self.inner.logs + } + + #[inline] + fn take_logs(&mut self) -> Vec { + self.inner.take_logs() + } + fn selfdestruct( &mut self, address: Address, @@ -306,11 +316,6 @@ impl JournalTr for Journal { .create_account_checkpoint(caller, address, balance, spec_id) } - #[inline] - fn take_logs(&mut self) -> Vec { - self.inner.take_logs() - } - #[inline] fn commit_tx(&mut self) { self.inner.commit_tx() diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index 249714cf1c..ecab88cd09 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -16,7 +16,7 @@ use revm::{ handler::system_call::SYSTEM_ADDRESS, interpreter::{ gas::{calculate_initial_tx_gas, InitialAndFloorGas}, - Interpreter, InterpreterTypes, + InterpreterTypes, }, precompile::{bls12_381_const, bls12_381_utils, bn254, secp256r1, u64_to_address}, primitives::{address, bytes, eip7825, Address, Bytes, Log, TxKind, U256}, @@ -1083,8 +1083,8 @@ struct LogInspector { } impl Inspector for LogInspector { - fn log(&mut self, _interp: &mut Interpreter, _context: &mut CTX, log: Log) { - self.logs.push(log) + fn log(&mut self, _context: &mut CTX, log: Log) { + self.logs.push(log); } } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index db10e07f75..a85ebed8a5 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -27,8 +27,7 @@ use primitives::{ }; use primitives::{keccak256, Address, Bytes, U256}; use state::Bytecode; -use std::borrow::ToOwned; -use std::boxed::Box; +use std::{borrow::ToOwned, boxed::Box, vec::Vec}; /// Frame implementation for Ethereum. #[derive_where(Clone, Debug; IW, @@ -155,6 +154,8 @@ impl EthFrame { output: Bytes::new(), }, memory_offset: inputs.return_memory_offset.clone(), + was_precompile_called: false, + precompile_call_logs: Vec::new(), }))) }; @@ -190,14 +191,20 @@ impl EthFrame { let gas_limit = inputs.gas_limit; if let Some(result) = precompiles.run(ctx, &inputs).map_err(ERROR::from_string)? { + let mut logs = Vec::new(); if result.result.is_ok() { ctx.journal_mut().checkpoint_commit(); } else { + // clone logs that precompile created, only possible with custom precompiles. + // checkpoint.log_i will be always correct. + logs = ctx.journal_mut().logs()[checkpoint.log_i..].to_vec(); ctx.journal_mut().checkpoint_revert(checkpoint); } return Ok(ItemOrResult::Result(FrameResult::Call(CallOutcome { result, memory_offset: inputs.return_memory_offset.clone(), + was_precompile_called: true, + precompile_call_logs: logs, }))); } diff --git a/crates/inspector/src/count_inspector.rs b/crates/inspector/src/count_inspector.rs index 37a99832c5..7e3612fc1f 100644 --- a/crates/inspector/src/count_inspector.rs +++ b/crates/inspector/src/count_inspector.rs @@ -1,7 +1,7 @@ //! CountInspector - Inspector that counts all opcodes that were called. use crate::inspector::Inspector; use interpreter::{interpreter_types::Jumps, InterpreterTypes}; -use primitives::HashMap; +use primitives::{HashMap, Log}; /// Inspector that counts all opcodes that were called during execution. #[derive(Clone, Debug, Default)] @@ -133,12 +133,7 @@ impl Inspector for CountInspector { self.step_end_count += 1; } - fn log( - &mut self, - _interp: &mut interpreter::Interpreter, - _context: &mut CTX, - _log: primitives::Log, - ) { + fn log(&mut self, _context: &mut CTX, _log: Log) { self.log_count += 1; } diff --git a/crates/inspector/src/either.rs b/crates/inspector/src/either.rs index 239d76bb38..8f3c8c5ca6 100644 --- a/crates/inspector/src/either.rs +++ b/crates/inspector/src/either.rs @@ -35,10 +35,18 @@ where } #[inline] - fn log(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) { + fn log(&mut self, context: &mut CTX, log: Log) { match self { - Either::Left(inspector) => inspector.log(interp, context, log), - Either::Right(inspector) => inspector.log(interp, context, log), + Either::Left(inspector) => inspector.log(context, log), + Either::Right(inspector) => inspector.log(context, log), + } + } + + #[inline] + fn log_full(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) { + match self { + Either::Left(inspector) => inspector.log_full(interp, context, log), + Either::Right(inspector) => inspector.log_full(interp, context, log), } } diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index aad34460cc..73e26cff8c 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -1,5 +1,5 @@ use crate::{Inspector, InspectorEvmTr, JournalExt}; -use context::{result::ExecutionResult, ContextTr, JournalEntry, Transaction}; +use context::{result::ExecutionResult, ContextTr, JournalEntry, JournalTr, Transaction}; use handler::{evm::FrameTr, EvmTr, FrameResult, Handler, ItemOrResult}; use interpreter::{ instructions::InstructionTable, @@ -260,7 +260,7 @@ fn inspect_log( } let log = context.journal_mut().logs().last().unwrap().clone(); - inspector.log(interpreter, context, log); + inspector.log(context, log); } #[inline(never)] diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 0df83be214..0c8dd19933 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -47,14 +47,23 @@ pub trait Inspector { let _ = context; } - /// Called when a log is emitted. + /// Called when a log is emitted, called on every new log. + /// If there is a needs for Interpreter context, use [`Inspector::log_full`] instead. #[inline] - fn log(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) { - let _ = interp; + fn log(&mut self, context: &mut CTX, log: Log) { let _ = context; let _ = log; } + /// Called when a log is emitted with the interpreter context. + /// + /// This will not happen only if custom precompiles where logs will be + /// gethered after precompile call. + fn log_full(&mut self, interpreter: &mut Interpreter, context: &mut CTX, log: Log) { + let _ = interpreter; + self.log(context, log); + } + /// Called whenever a call to a contract is about to start. /// /// Returning `CallOutcome` will override the result of the call. @@ -133,9 +142,14 @@ where self.1.step_end(interp, context); } - fn log(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) { - self.0.log(interp, context, log.clone()); - self.1.log(interp, context, log); + fn log(&mut self, context: &mut CTX, log: Log) { + self.0.log(context, log.clone()); + self.1.log(context, log); + } + + fn log_full(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) { + self.0.log_full(interp, context, log.clone()); + self.1.log_full(interp, context, log); } fn call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option { @@ -174,9 +188,6 @@ where /// Extends the journal with additional methods that are used by the inspector. #[auto_impl(&mut, Box)] pub trait JournalExt { - /// Get all logs from the journal. - fn logs(&self) -> &[Log]; - /// Get the journal entries that are created from last checkpoint. /// new checkpoint is created when sub call is made. fn journal(&self) -> &[JournalEntry]; @@ -189,11 +200,6 @@ pub trait JournalExt { } impl JournalExt for Journal { - #[inline] - fn logs(&self) -> &[Log] { - &self.logs - } - #[inline] fn journal(&self) -> &[JournalEntry] { &self.journal diff --git a/crates/inspector/src/inspector_tests.rs b/crates/inspector/src/inspector_tests.rs index 5916a75c86..ad831d43f1 100644 --- a/crates/inspector/src/inspector_tests.rs +++ b/crates/inspector/src/inspector_tests.rs @@ -117,7 +117,7 @@ mod tests { } } - fn log(&mut self, _interp: &mut Interpreter, _ctx: &mut CTX, log: Log) { + fn log(&mut self, _ctx: &mut CTX, log: Log) { self.events.push(InspectorEvent::Log(log)); } diff --git a/crates/inspector/src/traits.rs b/crates/inspector/src/traits.rs index bcd395acfc..b55f66b0be 100644 --- a/crates/inspector/src/traits.rs +++ b/crates/inspector/src/traits.rs @@ -1,10 +1,12 @@ -use context::{ContextTr, FrameStack}; +use context::{ContextTr, FrameStack, JournalTr}; use handler::{ evm::{ContextDbError, FrameInitResult, FrameTr}, instructions::InstructionProvider, EthFrame, EvmTr, FrameInitOrResult, FrameResult, ItemOrResult, }; -use interpreter::{interpreter::EthInterpreter, interpreter_action::FrameInit, InterpreterTypes}; +use interpreter::{ + interpreter::EthInterpreter, interpreter_action::FrameInit, CallOutcome, InterpreterTypes, +}; use crate::{ handler::{frame_end, frame_start}, @@ -104,8 +106,23 @@ pub trait InspectorEvmTr: } let frame_input = frame_init.frame_input.clone(); + let logs_i = ctx.journal().logs().len(); if let ItemOrResult::Result(mut output) = self.frame_init(frame_init)? { let (ctx, inspector) = self.ctx_inspector(); + // for precompiles send logs to inspector. + if let FrameResult::Call(CallOutcome { + was_precompile_called, + precompile_call_logs, + .. + }) = &mut output + { + if *was_precompile_called { + let logs = ctx.journal_mut().logs()[logs_i..].to_vec(); + for log in logs.iter().chain(precompile_call_logs.iter()).cloned() { + inspector.log(ctx, log); + } + } + } frame_end(ctx, inspector, &frame_input, &mut output); return Ok(ItemOrResult::Result(output)); } diff --git a/crates/interpreter/src/interpreter_action/call_outcome.rs b/crates/interpreter/src/interpreter_action/call_outcome.rs index 55a69989f1..6ce0fadfd3 100644 --- a/crates/interpreter/src/interpreter_action/call_outcome.rs +++ b/crates/interpreter/src/interpreter_action/call_outcome.rs @@ -1,6 +1,7 @@ use crate::{Gas, InstructionResult, InterpreterResult}; use core::ops::Range; -use primitives::Bytes; +use primitives::{Bytes, Log}; +use std::vec::Vec; /// Represents the outcome of a call operation in a virtual machine. /// @@ -18,6 +19,12 @@ pub struct CallOutcome { pub result: InterpreterResult, /// The range in memory where the output data is located pub memory_offset: Range, + /// Flag to indicate if the call is precompile call. + /// Used by inspector so it can copy the logs for Inspector::logs call. + pub was_precompile_called: bool, + /// Precompile call logs. Needs as revert/halt would delete them from Journal. + /// So they can't be accessed by inspector. + pub precompile_call_logs: Vec, } impl CallOutcome { @@ -33,6 +40,8 @@ impl CallOutcome { Self { result, memory_offset, + was_precompile_called: false, + precompile_call_logs: Vec::new(), } } diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 5f4f4ed16d..925d9dc663 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -1279,14 +1279,14 @@ mod tests { assert_eq!( handler.execution_result( &mut evm, - FrameResult::Call(CallOutcome { - result: InterpreterResult { + FrameResult::Call(CallOutcome::new( + InterpreterResult { result: InstructionResult::OutOfGas, output: Default::default(), gas: Default::default(), }, - memory_offset: Default::default(), - }) + Default::default() + )) ), Err(EVMError::Transaction( OpTransactionError::HaltedDepositPostRegolith diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index fd71c70f9b..a40b0c5ca3 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -103,6 +103,10 @@ impl JournalTr for Backend { self.journaled_state.log(log) } + fn logs(&self) -> &[Log] { + self.journaled_state.logs() + } + fn selfdestruct( &mut self, address: Address, @@ -314,10 +318,6 @@ impl JournalTr for Backend { } impl JournalExt for Backend { - fn logs(&self) -> &[Log] { - self.journaled_state.logs() - } - fn journal(&self) -> &[JournalEntry] { self.journaled_state.journal() } diff --git a/examples/custom_precompile_journal/src/custom_evm.rs b/examples/custom_precompile_journal/src/custom_evm.rs index 47b1f59344..5a453abc34 100644 --- a/examples/custom_precompile_journal/src/custom_evm.rs +++ b/examples/custom_precompile_journal/src/custom_evm.rs @@ -150,3 +150,253 @@ where self.0.all_mut_inspector() } } + +#[cfg(test)] +mod tests { + use crate::{custom_evm::CustomEvm, precompile_provider::CUSTOM_PRECOMPILE_ADDRESS}; + use revm::{ + context::{Context, ContextSetters, TxEnv}, + context_interface::{result::EVMError, ContextTr}, + database::InMemoryDB, + handler::{Handler, MainnetHandler}, + inspector::{Inspector, JournalExt}, + interpreter::interpreter::EthInterpreter, + primitives::{address, Log, TxKind, U256}, + state::AccountInfo, + MainContext, + }; + use std::vec::Vec; + + /// Custom inspector that captures logs + #[derive(Debug, Default)] + struct LogCapturingInspector { + captured_logs: Vec, + } + + impl LogCapturingInspector { + fn new() -> Self { + Self { + captured_logs: Vec::new(), + } + } + + fn logs(&self) -> &[Log] { + &self.captured_logs + } + } + + impl Inspector for LogCapturingInspector + where + CTX: ContextTr + ContextSetters, + { + fn log(&mut self, _context: &mut CTX, log: Log) { + // Capture logs as they're created + self.captured_logs.push(log); + } + } + + #[test] + fn test_custom_precompile_creates_log() { + // Setup initial accounts + let user_address = address!("0000000000000000000000000000000000000001"); + let mut db = InMemoryDB::default(); + + // Give the user some ETH for gas + let user_balance = U256::from(10).pow(U256::from(18)); // 1 ETH + db.insert_account_info( + user_address, + AccountInfo { + balance: user_balance, + nonce: 0, + code_hash: revm::primitives::KECCAK_EMPTY, + code: None, + }, + ); + + // Give the precompile some initial balance for transfers + db.insert_account_info( + CUSTOM_PRECOMPILE_ADDRESS, + AccountInfo { + balance: U256::from(1000), // 1000 wei + nonce: 0, + code_hash: revm::primitives::KECCAK_EMPTY, + code: None, + }, + ); + + // Create custom EVM with log capturing inspector + let context = Context::mainnet().with_db(db); + let inspector = LogCapturingInspector::new(); + let mut evm = CustomEvm::new(context, inspector); + + // Write value 42 to storage (this should create a log) + let storage_value = U256::from(42); + evm.0.ctx.set_tx( + TxEnv::builder() + .caller(user_address) + .kind(TxKind::Call(CUSTOM_PRECOMPILE_ADDRESS)) + .data(storage_value.to_be_bytes_vec().into()) + .gas_limit(100_000) + .build() + .unwrap(), + ); + + let result: Result< + _, + EVMError, + > = MainnetHandler::default().run(&mut evm); + + // Verify transaction succeeded + assert!( + result.is_ok(), + "Transaction should succeed, got: {result:?}" + ); + + match result.unwrap() { + revm::context::result::ExecutionResult::Success { logs, .. } => { + // Transaction succeeded, now check logs from execution result + // Note: Inspector might not be called for precompile logs, + // so we check the execution result logs instead + + // Also check inspector logs (though they may be empty) + let inspector_logs = evm.0.inspector.logs(); + + // Combine both sources - use execution result logs if inspector logs are empty + let all_logs = if inspector_logs.is_empty() { + &logs + } else { + inspector_logs + }; + + // Verify that at least one log was captured + assert!( + !all_logs.is_empty(), + "Should have captured at least one log (either from inspector or execution result)" + ); + + // Find the log from our custom precompile + let precompile_log = all_logs + .iter() + .find(|log| log.address == CUSTOM_PRECOMPILE_ADDRESS); + + assert!( + precompile_log.is_some(), + "Should have a log from the custom precompile. Found {} total logs", + all_logs.len() + ); + + let log = precompile_log.unwrap(); + + // Verify log structure + assert_eq!(log.address, CUSTOM_PRECOMPILE_ADDRESS); + assert_eq!(log.data.topics().len(), 2, "Should have 2 topics"); + + // Topic 1 should be the caller address (left-padded to 32 bytes) + let topic1 = log.data.topics()[1]; + let mut expected_caller_bytes = [0u8; 32]; + expected_caller_bytes[12..32].copy_from_slice(user_address.as_slice()); + let expected_caller_topic = revm::primitives::B256::from(expected_caller_bytes); + assert_eq!( + topic1, expected_caller_topic, + "Second topic should be caller address" + ); + + // Data should contain the value that was written (42) + let log_data_bytes = &log.data.data; + let logged_value = U256::from_be_slice(log_data_bytes); + assert_eq!( + logged_value, + U256::from(42), + "Log data should contain the written value (42)" + ); + + println!("✅ Test passed! Log was successfully created and captured"); + println!(" Log address: {}", log.address); + println!(" Number of topics: {}", log.data.topics().len()); + println!(" Logged value: {logged_value}"); + println!( + " Inspector logs: {}, Execution result logs: {}", + inspector_logs.len(), + logs.len() + ); + } + revm::context::result::ExecutionResult::Revert { .. } => { + panic!("Transaction reverted unexpectedly"); + } + revm::context::result::ExecutionResult::Halt { reason, .. } => { + panic!("Transaction halted unexpectedly: {reason:?}"); + } + } + } + + #[test] + fn test_read_operation_does_not_create_log() { + // Setup initial accounts + let user_address = address!("0000000000000000000000000000000000000001"); + let mut db = InMemoryDB::default(); + + // Give the user some ETH for gas + let user_balance = U256::from(10).pow(U256::from(18)); // 1 ETH + db.insert_account_info( + user_address, + AccountInfo { + balance: user_balance, + nonce: 0, + code_hash: revm::primitives::KECCAK_EMPTY, + code: None, + }, + ); + + // Create custom EVM with log capturing inspector + let context = Context::mainnet().with_db(db); + let inspector = LogCapturingInspector::new(); + let mut evm = CustomEvm::new(context, inspector); + + // Read from storage (empty input - should not create a log) + evm.0.ctx.set_tx( + TxEnv::builder() + .caller(user_address) + .kind(TxKind::Call(CUSTOM_PRECOMPILE_ADDRESS)) + .data(revm::primitives::Bytes::new()) // Empty data for read operation + .gas_limit(100_000) + .build() + .unwrap(), + ); + + let result: Result< + _, + EVMError, + > = MainnetHandler::default().run(&mut evm); + + // Verify transaction succeeded + assert!( + result.is_ok(), + "Transaction should succeed, got: {result:?}" + ); + + match result.unwrap() { + revm::context::result::ExecutionResult::Success { .. } => { + // Transaction succeeded, check that no logs were created + let logs = evm.0.inspector.logs(); + + // Verify that no logs from the precompile were captured + let precompile_log = logs + .iter() + .find(|log| log.address == CUSTOM_PRECOMPILE_ADDRESS); + + assert!( + precompile_log.is_none(), + "Read operation should not create any logs" + ); + + println!("✅ Test passed! Read operation correctly did not create any logs"); + } + revm::context::result::ExecutionResult::Revert { .. } => { + panic!("Transaction reverted unexpectedly"); + } + revm::context::result::ExecutionResult::Halt { reason, .. } => { + panic!("Transaction halted unexpectedly: {reason:?}"); + } + } + } +} diff --git a/examples/custom_precompile_journal/src/precompile_provider.rs b/examples/custom_precompile_journal/src/precompile_provider.rs index 7e4214ff66..35e9705855 100644 --- a/examples/custom_precompile_journal/src/precompile_provider.rs +++ b/examples/custom_precompile_journal/src/precompile_provider.rs @@ -6,7 +6,7 @@ use revm::{ handler::{EthPrecompiles, PrecompileProvider}, interpreter::{CallInputs, Gas, InstructionResult, InterpreterResult}, precompile::{PrecompileError, PrecompileOutput, PrecompileResult}, - primitives::{address, hardfork::SpecId, Address, Bytes, U256}, + primitives::{address, hardfork::SpecId, Address, Bytes, Log, B256, U256}, }; use std::boxed::Box; use std::string::String; @@ -211,6 +211,29 @@ fn handle_write_storage( return Err(PrecompileError::Other(format!("Transfer error: {error:?}"))); } + // Create a log to record the storage write operation + // Topic 0: keccak256("StorageWritten(address,uint256)") + let topic0 = B256::from_slice(&[ + 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, + 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, + 0xde, 0xf0, + ]); + // Topic 1: caller address (indexed) - left-padded to 32 bytes + let mut topic1_bytes = [0u8; 32]; + topic1_bytes[12..32].copy_from_slice(caller.as_slice()); + let topic1 = B256::from(topic1_bytes); + // Data: the value that was written + let log_data = value.to_be_bytes_vec(); + + let log = Log::new( + CUSTOM_PRECOMPILE_ADDRESS, + vec![topic0, topic1], + log_data.into(), + ) + .expect("Failed to create log"); + + context.journal_mut().log(log); + // Return success with empty output Ok(PrecompileOutput::new(BASE_GAS + SSTORE_GAS, Bytes::new())) } From d762d4b68e555a9805def0fb94fe011978653bd4 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Nov 2025 19:38:33 +0100 Subject: [PATCH 037/127] feat(precompiles): add performant PrecompileError::OtherCowStr variant (#3144) * feat(precompiles): add performant PrecompileError::OtherStr variant * Apply suggestion from @rakita * use cow * rm Other(String) and use Other(Cow<'static,str>) * fn other_static * revert api change --- crates/op-revm/src/precompiles.rs | 15 ++++++--------- crates/precompile/src/interface.rs | 13 +++++++++---- .../src/precompile_provider.rs | 14 ++++++++------ 3 files changed, 23 insertions(+), 19 deletions(-) diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index 025a6afbad..3de2d0813d 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -216,9 +216,6 @@ pub mod bls12_381 { use super::*; use revm::precompile::bls12_381_const::{G1_MSM_ADDRESS, G2_MSM_ADDRESS, PAIRING_ADDRESS}; - #[cfg(not(feature = "std"))] - use crate::std::string::ToString; - /// Max input size for the g1 msm precompile. pub const ISTHMUS_G1_MSM_MAX_INPUT_SIZE: usize = 513760; @@ -264,7 +261,7 @@ pub mod bls12_381 { pub fn run_g1_msm_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > ISTHMUS_G1_MSM_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "G1MSM input length too long for OP Stack input size limitation after the Isthmus Hardfork".to_string(), + "G1MSM input length too long for OP Stack input size limitation after the Isthmus Hardfork".into(), )); } precompile::bls12_381::g1_msm::g1_msm(input, gas_limit) @@ -274,7 +271,7 @@ pub mod bls12_381 { pub fn run_g1_msm_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > JOVIAN_G1_MSM_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "G1MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".to_string(), + "G1MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".into(), )); } precompile::bls12_381::g1_msm::g1_msm(input, gas_limit) @@ -284,7 +281,7 @@ pub mod bls12_381 { pub fn run_g2_msm_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > ISTHMUS_G2_MSM_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "G2MSM input length too long for OP Stack input size limitation".to_string(), + "G2MSM input length too long for OP Stack input size limitation".into(), )); } precompile::bls12_381::g2_msm::g2_msm(input, gas_limit) @@ -294,7 +291,7 @@ pub mod bls12_381 { pub fn run_g2_msm_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > JOVIAN_G2_MSM_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "G2MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".to_string(), + "G2MSM input length too long for OP Stack input size limitation after the Jovian Hardfork".into(), )); } precompile::bls12_381::g2_msm::g2_msm(input, gas_limit) @@ -304,7 +301,7 @@ pub mod bls12_381 { pub fn run_pair_isthmus(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > ISTHMUS_PAIRING_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "Pairing input length too long for OP Stack input size limitation".to_string(), + "Pairing input length too long for OP Stack input size limitation".into(), )); } precompile::bls12_381::pairing::pairing(input, gas_limit) @@ -314,7 +311,7 @@ pub mod bls12_381 { pub fn run_pair_jovian(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > JOVIAN_PAIRING_MAX_INPUT_SIZE { return Err(PrecompileError::Other( - "Pairing input length too long for OP Stack input size limitation after the Jovian Hardfork".to_string(), + "Pairing input length too long for OP Stack input size limitation after the Jovian Hardfork".into(), )); } precompile::bls12_381::pairing::pairing(input, gas_limit) diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index 3fff76b743..618a275d1c 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -2,7 +2,7 @@ //! the precompile output type, and the precompile error type. use core::fmt::{self, Debug}; use primitives::{Bytes, OnceLock}; -use std::{boxed::Box, string::String, vec::Vec}; +use std::{borrow::Cow, boxed::Box, string::String, vec::Vec}; use crate::bls12_381::{G1Point, G1PointScalar, G2Point, G2PointScalar}; @@ -275,14 +275,19 @@ pub enum PrecompileError { Secp256k1RecoverFailed, /// Fatal error with a custom error message Fatal(String), - /// Catch-all variant for other errors - Other(String), + /// Catch-all variant with a custom error message + Other(Cow<'static, str>), } impl PrecompileError { /// Returns another error with the given message. pub fn other(err: impl Into) -> Self { - Self::Other(err.into()) + Self::Other(Cow::Owned(err.into())) + } + + /// Returns another error with the given static string. + pub const fn other_static(err: &'static str) -> Self { + Self::Other(Cow::Borrowed(err)) } /// Returns `true` if the error is out of gas. diff --git a/examples/custom_precompile_journal/src/precompile_provider.rs b/examples/custom_precompile_journal/src/precompile_provider.rs index 35e9705855..8e2fd5f339 100644 --- a/examples/custom_precompile_journal/src/precompile_provider.rs +++ b/examples/custom_precompile_journal/src/precompile_provider.rs @@ -105,7 +105,7 @@ fn run_custom_precompile( // Write storage operation handle_write_storage(context, &input_bytes, inputs.gas_limit) } else { - Err(PrecompileError::Other("Invalid input length".to_string())) + Err(PrecompileError::Other("Invalid input length".into())) }; match result { @@ -158,7 +158,7 @@ fn handle_read_storage(context: &mut CTX, gas_limit: u64) -> Pre let value = context .journal_mut() .sload(CUSTOM_PRECOMPILE_ADDRESS, STORAGE_KEY) - .map_err(|e| PrecompileError::Other(format!("Storage read failed: {e:?}")))? + .map_err(|e| PrecompileError::Other(format!("Storage read failed: {e:?}").into()))? .data; // Return the value as output @@ -189,7 +189,7 @@ fn handle_write_storage( context .journal_mut() .sstore(CUSTOM_PRECOMPILE_ADDRESS, STORAGE_KEY, value) - .map_err(|e| PrecompileError::Other(format!("Storage write failed: {e:?}")))?; + .map_err(|e| PrecompileError::Other(format!("Storage write failed: {e:?}").into()))?; // Get the caller address let caller = context.tx().caller(); @@ -199,16 +199,18 @@ fn handle_write_storage( context .journal_mut() .balance_incr(CUSTOM_PRECOMPILE_ADDRESS, U256::from(1)) - .map_err(|e| PrecompileError::Other(format!("Balance increment failed: {e:?}")))?; + .map_err(|e| PrecompileError::Other(format!("Balance increment failed: {e:?}").into()))?; // Then transfer to caller let transfer_result = context .journal_mut() .transfer(CUSTOM_PRECOMPILE_ADDRESS, caller, U256::from(1)) - .map_err(|e| PrecompileError::Other(format!("Transfer failed: {e:?}")))?; + .map_err(|e| PrecompileError::Other(format!("Transfer failed: {e:?}").into()))?; if let Some(error) = transfer_result { - return Err(PrecompileError::Other(format!("Transfer error: {error:?}"))); + return Err(PrecompileError::Other( + format!("Transfer error: {error:?}").into(), + )); } // Create a log to record the storage write operation From cd2f766cf3e6dba13921aea888820f62705e0859 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Tue, 11 Nov 2025 01:35:51 +0400 Subject: [PATCH 038/127] feat: generic Context::new (#3156) --- crates/context/src/context.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 55baa11ccb..f03ac49d19 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -131,14 +131,15 @@ impl< JOURNAL: JournalTr, CHAIN: Default, LOCAL: LocalContextTr + Default, - > Context + SPEC: Default + Copy + Into, + > Context, DB, JOURNAL, CHAIN, LOCAL> { /// Creates a new context with a new database type. /// /// This will create a new [`Journal`] object. - pub fn new(db: DB, spec: SpecId) -> Self { + pub fn new(db: DB, spec: SPEC) -> Self { let mut journaled_state = JOURNAL::new(db); - journaled_state.set_spec_id(spec); + journaled_state.set_spec_id(spec.into()); Self { tx: TX::default(), block: BLOCK::default(), From 28488a555ba6d1429bc82c3105472b17979a5c2c Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 23:38:11 +0100 Subject: [PATCH 039/127] chore: release (#3136) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 18 +++++++++--------- bins/revme/CHANGELOG.md | 6 ++++++ bins/revme/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 16 ++++++++++++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 11 +++++++++++ crates/context/interface/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 11 +++++++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 6 ++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 13 +++++++++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 7 +++++++ crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 11 +++++++++++ crates/precompile/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 6 ++++++ crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 6 ++++++ crates/statetest-types/Cargo.toml | 2 +- 22 files changed, 122 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a062aa1ac..c5cf17f15c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "12.0.2" +version = "12.1.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "31.0.2" +version = "31.0.3" dependencies = [ "revm-bytecode", "revm-context", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "11.0.2" +version = "11.1.0" dependencies = [ "bitvec", "cfg-if", @@ -3580,7 +3580,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "12.0.1" +version = "12.1.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "12.0.2" +version = "12.1.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "12.0.2" +version = "12.1.0" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "29.0.1" +version = "29.1.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "29.0.1" +version = "29.1.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "11.0.2" +version = "11.0.3" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "9.0.2" +version = "9.0.3" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 663b0f2ab3..e3cb53ceba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "31.0.2", default-features = false } +revm = { path = "crates/revm", version = "31.0.3", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.5", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "29.0.1", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "12.0.2", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.0.1", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "11.0.2", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "11.0.2", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.0.1", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "12.0.2", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.0.2", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "29.1.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "12.1.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.1.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "11.0.3", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "11.1.0", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.1.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "12.1.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.1.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 021f8e955e..a319853dfb 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.3](https://github.com/bluealloy/revm/compare/revme-v9.0.2...revme-v9.0.3) - 2025-11-10 + +### Other + +- updated the following local packages: revm, revm-statetest-types + ## [9.0.2](https://github.com/bluealloy/revm/compare/revme-v9.0.1...revme-v9.0.2) - 2025-11-10 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 7de3ee3f3d..f2481eef2e 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "9.0.2" +version = "9.0.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 1a850ecbbf..4f03b2af73 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.1.0](https://github.com/bluealloy/revm/compare/revm-context-v11.0.2...revm-context-v11.1.0) - 2025-11-10 + +### Added + +- generic Context::new ([#3156](https://github.com/bluealloy/revm/pull/3156)) +- process precompile logs to inspector ([#3148](https://github.com/bluealloy/revm/pull/3148)) +- selfdestruct oog on cold load ([#3140](https://github.com/bluealloy/revm/pull/3140)) + +### Fixed + +- use access list to decide if slot is cold ([#3149](https://github.com/bluealloy/revm/pull/3149)) + +### Other + +- merge v98 versions bumps ([#3155](https://github.com/bluealloy/revm/pull/3155)) + ## [11.0.2](https://github.com/bluealloy/revm/compare/revm-context-v11.0.1...revm-context-v11.0.2) - 2025-11-10 ### Other diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 6959a6d49b..a11df2541d 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "11.0.2" +version = "11.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index 44f1b1932a..2d8adef039 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.1.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v12.0.1...revm-context-interface-v12.1.0) - 2025-11-10 + +### Added + +- process precompile logs to inspector ([#3148](https://github.com/bluealloy/revm/pull/3148)) +- selfdestruct oog on cold load ([#3140](https://github.com/bluealloy/revm/pull/3140)) + +### Other + +- merge v98 versions bumps ([#3155](https://github.com/bluealloy/revm/pull/3155)) + ## [12.0.1](https://github.com/bluealloy/revm/compare/revm-context-interface-v12.0.0...revm-context-interface-v12.0.1) - 2025-11-07 ### Other diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 4d1d09162d..ac8bf01b16 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "12.0.1" +version = "12.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 7a3d9e0960..0defd57bbe 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.2...revm-handler-v12.1.0) - 2025-11-10 + +### Added + +- process precompile logs to inspector ([#3148](https://github.com/bluealloy/revm/pull/3148)) +- add gas refund to PrecompileOutput ([#3152](https://github.com/bluealloy/revm/pull/3152)) + +### Other + +- merge v98 versions bumps ([#3155](https://github.com/bluealloy/revm/pull/3155)) + ## [12.0.2](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.1...revm-handler-v12.0.2) - 2025-11-10 ### Other diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 278a0e643b..08370f8a73 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "12.0.2" +version = "12.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 19aa50110b..7e0b219bb9 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.2...revm-inspector-v12.1.0) - 2025-11-10 + +### Added + +- process precompile logs to inspector ([#3148](https://github.com/bluealloy/revm/pull/3148)) + ## [12.0.2](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.1...revm-inspector-v12.0.2) - 2025-11-10 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 5df48f72af..dd556f3433 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "12.0.2" +version = "12.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 098648fc89..3b2debac54 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [29.1.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.1...revm-interpreter-v29.1.0) - 2025-11-10 + +### Added + +- process precompile logs to inspector ([#3148](https://github.com/bluealloy/revm/pull/3148)) +- selfdestruct oog on cold load ([#3140](https://github.com/bluealloy/revm/pull/3140)) + +### Other + +- merge v98 versions bumps ([#3155](https://github.com/bluealloy/revm/pull/3155)) +- add eq/serde for InitialAndFloorGas ([#3147](https://github.com/bluealloy/revm/pull/3147)) +- *(interpreter)* deprecate public otry! macro ([#3146](https://github.com/bluealloy/revm/pull/3146)) + ## [29.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.0...revm-interpreter-v29.0.1) - 2025-11-07 ### Other diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index ff34e2a734..08ee65e04b 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "29.0.1" +version = "29.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 80d735ec38..ded8d99fa5 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.1.0](https://github.com/bluealloy/revm/compare/op-revm-v12.0.2...op-revm-v12.1.0) - 2025-11-10 + +### Added + +- *(precompiles)* add performant PrecompileError::OtherCowStr variant ([#3144](https://github.com/bluealloy/revm/pull/3144)) +- process precompile logs to inspector ([#3148](https://github.com/bluealloy/revm/pull/3148)) + ## [12.0.2](https://github.com/bluealloy/revm/compare/op-revm-v12.0.1...op-revm-v12.0.2) - 2025-11-10 ### Fixed diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 4ad21a2eee..fbd4915d3b 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "12.0.2" +version = "12.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index 77df9e83d3..4d4f994373 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [29.1.0](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.1...revm-precompile-v29.1.0) - 2025-11-10 + +### Added + +- *(precompiles)* add performant PrecompileError::OtherCowStr variant ([#3144](https://github.com/bluealloy/revm/pull/3144)) +- add gas refund to PrecompileOutput ([#3152](https://github.com/bluealloy/revm/pull/3152)) + +### Other + +- merge v98 versions bumps ([#3155](https://github.com/bluealloy/revm/pull/3155)) + ## [29.0.1](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.0...revm-precompile-v29.0.1) - 2025-11-07 ### Other diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index ec0ce2a1eb..1215862a0b 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "29.0.1" +version = "29.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index cb024fd510..2cdcf5482f 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [31.0.3](https://github.com/bluealloy/revm/compare/revm-v31.0.2...revm-v31.0.3) - 2025-11-10 + +### Other + +- updated the following local packages: revm-context-interface, revm-context, revm-interpreter, revm-precompile, revm-handler, revm-inspector + ## [31.0.2](https://github.com/bluealloy/revm/compare/revm-v31.0.1...revm-v31.0.2) - 2025-11-10 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index ad0048bcef..240a9ebc3d 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "31.0.2" +version = "31.0.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 84b5df21d9..e465e89440 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.0.3](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.2...revm-statetest-types-v11.0.3) - 2025-11-10 + +### Other + +- updated the following local packages: revm + ## [11.0.2](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.1...revm-statetest-types-v11.0.2) - 2025-11-10 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 317ef16513..2a0b664c14 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "11.0.2" +version = "11.0.3" authors.workspace = true edition.workspace = true keywords.workspace = true From 8a784a733c409b3c86782eb8b7bcd907286c5069 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 11 Nov 2025 00:07:13 +0100 Subject: [PATCH 040/127] bump: v99 revm v32.0.0 (#3157) * bump: v99 revm v32.0.0 * typo: --- CHANGELOG.md | 17 +++++++++++++++++ Cargo.lock | 16 ++++++++-------- Cargo.toml | 14 +++++++------- MIGRATION_GUIDE.md | 22 ++++++++++++++++++++++ bins/revme/CHANGELOG.md | 2 +- bins/revme/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 2 +- crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 2 +- crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 2 +- crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 2 +- crates/precompile/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 2 +- crates/statetest-types/Cargo.toml | 2 +- 20 files changed, 70 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a3634d1e81..446b32a3a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v99 +date 10.11.2025 + +Maintainance release. + +* `revm-context-interface`: 12.0.1 -> 12.1.0 (✓ API compatible changes) +* `revm-context`: 11.0.2 -> 11.1.0 (✓ API compatible changes) +* `revm-interpreter`: 29.0.1 -> 30.0.0 (✓ API compatible changes) +* `revm-precompile`: 29.0.1 -> 30.0.0 (✓ API compatible changes) +* `revm-handler`: 12.0.2 -> 13.0.0 (✓ API compatible changes) +* `revm-inspector`: 12.0.2 -> 13.0.0 (✓ API compatible changes) +* `op-revm`: 12.0.2 -> 13.0.0 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm`: 31.0.2 -> 32.0.0 +* `revm-statetest-types`: 11.0.2 -> 12.0.0 +* `revme`: 9.0.2 -> 9.1.0 + # v98 date: 10.11.2025 diff --git a/Cargo.lock b/Cargo.lock index c5cf17f15c..44df172537 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "12.1.0" +version = "13.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "31.0.3" +version = "32.0.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "12.1.0" +version = "13.0.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "12.1.0" +version = "13.0.0" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "29.1.0" +version = "30.0.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "29.1.0" +version = "30.0.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "11.0.3" +version = "12.0.0" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "9.0.3" +version = "9.1.0" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index e3cb53ceba..3219418693 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "31.0.3", default-features = false } +revm = { path = "crates/revm", version = "32.0.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.5", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "29.1.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "12.1.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "29.1.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "11.0.3", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "30.0.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "13.0.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "30.0.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "12.0.0", default-features = false } context = { path = "crates/context", package = "revm-context", version = "11.1.0", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.1.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "12.1.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "12.1.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "13.0.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "13.0.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index c4445117f8..291b5c21a4 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,26 @@ +# v99 tag ( revm v32.0.0 ) + +* Added support for transmitting Logs set from precompiles. + * `Inspector::log` function got renamed to `log` and `log_full` + * `log_full` default impl will call `log` + * difference is that `log_full` has `Interpreter` input while `log` does not + and `log` will be called in places where Interpreter is not found. +* `PrecompileError` now contains `Other` as `Cow<'static, str>` + * It allows allows setting both `&'static str` that is without perf penalty and `String` if needed. + +# v98 tag + +No breaking changes. + +# v97 tag + +No breaking changes. + +# v96 tag + +No breaking changes. + # v95 tag ( revm v31.0.0) * Cfg added `memory_limit()` function diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index a319853dfb..1e9c3ff62f 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [9.0.3](https://github.com/bluealloy/revm/compare/revme-v9.0.2...revme-v9.0.3) - 2025-11-10 +## [9.1.0](https://github.com/bluealloy/revm/compare/revme-v9.0.2...revme-v9.1.0) - 2025-11-10 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index f2481eef2e..cc49e55a7e 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "9.0.3" +version = "9.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 0defd57bbe..86058833f3 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [12.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.2...revm-handler-v12.1.0) - 2025-11-10 +## [13.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.2...revm-handler-v13.0.0) - 2025-11-10 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 08370f8a73..55d4d8a933 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "12.1.0" +version = "13.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 7e0b219bb9..5777d1cf5a 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [12.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.2...revm-inspector-v12.1.0) - 2025-11-10 +## [13.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.2...revm-inspector-v13.0.0) - 2025-11-10 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index dd556f3433..b853cef669 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "12.1.0" +version = "13.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 3b2debac54..7f5b2e49c3 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [29.1.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.1...revm-interpreter-v29.1.0) - 2025-11-10 +## [30.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.1...revm-interpreter-v30.0.0) - 2025-11-10 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 08ee65e04b..ba781dd95e 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "29.1.0" +version = "30.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index ded8d99fa5..45a1140d91 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [12.1.0](https://github.com/bluealloy/revm/compare/op-revm-v12.0.2...op-revm-v12.1.0) - 2025-11-10 +## [13.0.0](https://github.com/bluealloy/revm/compare/op-revm-v12.0.2...op-revm-v13.0.0) - 2025-11-10 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index fbd4915d3b..0596160be2 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "12.1.0" +version = "13.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index 4d4f994373..a43d8473a5 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [29.1.0](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.1...revm-precompile-v29.1.0) - 2025-11-10 +## [30.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.1...revm-precompile-v30.0.0) - 2025-11-10 ### Added diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 1215862a0b..c6f90aad5b 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "29.1.0" +version = "30.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 2cdcf5482f..0e1c1c1437 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [31.0.3](https://github.com/bluealloy/revm/compare/revm-v31.0.2...revm-v31.0.3) - 2025-11-10 +## [32.0.0](https://github.com/bluealloy/revm/compare/revm-v31.0.2...revm-v32.0.0) - 2025-11-10 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 240a9ebc3d..1886cf7991 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "31.0.3" +version = "32.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index e465e89440..956c45d542 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [11.0.3](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.2...revm-statetest-types-v11.0.3) - 2025-11-10 +## [12.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.2...revm-statetest-types-v12.0.0) - 2025-11-10 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 2a0b664c14..1893941012 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "11.0.3" +version = "12.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true From 5723170ea49f70d1cf8df64394a1235528864089 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 12 Nov 2025 01:55:05 +0100 Subject: [PATCH 041/127] bump: tag v100 revm v33.0.0 (#3161) --- CHANGELOG.md | 23 +++++++++++++++++++++++ Cargo.lock | 20 ++++++++++---------- Cargo.toml | 18 +++++++++--------- MIGRATION_GUIDE.md | 7 +++++++ bins/revme/CHANGELOG.md | 2 +- bins/revme/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 2 +- crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 2 +- crates/context/interface/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 2 +- crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 2 +- crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 2 +- crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 2 +- crates/precompile/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 2 +- crates/statetest-types/Cargo.toml | 2 +- 24 files changed, 69 insertions(+), 39 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 446b32a3a7..a8e364dbf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,26 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v100 +date: 12.11.2025 + +Bumping major version for `revm-context-interface` sa it is breaking change. +Host selfdestruct function got changed in v99 + +* `revm-context-interface`: 12.1.0 -> 13.0.0 (⚠ API breaking changes) +* `revm-context`: 11.1.0 -> 12.0.0 (✓ API compatible changes) +* `revm-interpreter`: 30.0.0 -> 31.0.0 (✓ API compatible changes) +* `revm-precompile`: 30.0.0 -> 31.0.0 (✓ API compatible changes) +* `revm-handler`: 13.0.0 -> 14.0.0 (✓ API compatible changes) +* `revm-inspector`: 13.0.0 -> 14.0.0 (✓ API compatible changes) +* `op-revm`: 13.0.0 -> 14.0.0 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm`: 32.0.0 -> 33.0.0 +* `revm-statetest-types`: 12.0.0 -> 13.0.0 +* `revme`: 9.1.0 -> 10.0.0 + +revm-context-interface@13.0.0 revm-context@12.0.0 revm-interpreter@31.0.0 revm-precompile@31.0.0 revm-handler@14.0.0 revm-inspector@14.0.0 +op-revm@14.0.0 revm@33.0.0 revm-statetest-types@13.0.0 revme@10.0.0 + # v99 date 10.11.2025 @@ -17,6 +38,8 @@ Maintainance release. * `revm-statetest-types`: 11.0.2 -> 12.0.0 * `revme`: 9.0.2 -> 9.1.0 + + # v98 date: 10.11.2025 diff --git a/Cargo.lock b/Cargo.lock index 44df172537..59b4803302 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "13.0.0" +version = "14.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "32.0.0" +version = "33.0.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "11.1.0" +version = "12.0.0" dependencies = [ "bitvec", "cfg-if", @@ -3580,7 +3580,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "12.1.0" +version = "13.0.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "13.0.0" +version = "14.0.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "13.0.0" +version = "14.0.0" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "30.0.0" +version = "31.0.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3686,7 +3686,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "30.0.0" +version = "31.0.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "12.0.0" +version = "13.0.0" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "9.1.0" +version = "10.0.0" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 3219418693..788a816333 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "32.0.0", default-features = false } +revm = { path = "crates/revm", version = "33.0.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.5", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "30.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "13.0.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "30.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "12.0.0", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "11.1.0", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "12.1.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "13.0.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "13.0.0", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "31.0.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.0.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "31.0.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "13.0.0", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "12.0.0", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "13.0.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "14.0.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.0.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 291b5c21a4..cc332df20d 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,6 +1,13 @@ +# v100 tag (revm v33.0.0) + +* Additionally to v99 version: + * `Host::selfdestruct` function got changed to support oog on cold load for target account. + # v99 tag ( revm v32.0.0 ) +(yanked version) + * Added support for transmitting Logs set from precompiles. * `Inspector::log` function got renamed to `log` and `log_full` * `log_full` default impl will call `log` diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 1e9c3ff62f..098ddbdcef 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [9.1.0](https://github.com/bluealloy/revm/compare/revme-v9.0.2...revme-v9.1.0) - 2025-11-10 +## [10.0.0](https://github.com/bluealloy/revm/compare/revme-v9.0.2...revme-v10.0.0) - 2025-11-10 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index cc49e55a7e..ca0b42adf1 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "9.1.0" +version = "10.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 4f03b2af73..5386dca18d 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [11.1.0](https://github.com/bluealloy/revm/compare/revm-context-v11.0.2...revm-context-v11.1.0) - 2025-11-10 +## [12.0.0](https://github.com/bluealloy/revm/compare/revm-context-v11.0.2...revm-context-v12.0.0) - 2025-11-10 ### Added diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index a11df2541d..69e8ff0c03 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "11.1.0" +version = "12.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index 2d8adef039..cce3b20c72 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [12.1.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v12.0.1...revm-context-interface-v12.1.0) - 2025-11-10 +## [13.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v12.0.1...revm-context-interface-v13.0.0) - 2025-11-10 ### Added diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index ac8bf01b16..5fbe25d503 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "12.1.0" +version = "13.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 86058833f3..73f0b561a2 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [13.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.2...revm-handler-v13.0.0) - 2025-11-10 +## [14.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.2...revm-handler-v14.0.0) - 2025-11-10 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 55d4d8a933..f2790b1cb1 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "13.0.0" +version = "14.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 5777d1cf5a..a40fc6e08a 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [13.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.2...revm-inspector-v13.0.0) - 2025-11-10 +## [14.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.2...revm-inspector-v14.0.0) - 2025-11-10 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index b853cef669..da4e851539 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "13.0.0" +version = "14.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 7f5b2e49c3..cab0eb8869 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [30.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.1...revm-interpreter-v30.0.0) - 2025-11-10 +## [31.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.1...revm-interpreter-v31.0.0) - 2025-11-10 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index ba781dd95e..974a453f2b 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "30.0.0" +version = "31.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 45a1140d91..c9f8dcdf65 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [13.0.0](https://github.com/bluealloy/revm/compare/op-revm-v12.0.2...op-revm-v13.0.0) - 2025-11-10 +## [14.0.0](https://github.com/bluealloy/revm/compare/op-revm-v12.0.2...op-revm-v14.0.0) - 2025-11-10 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 0596160be2..36c8956743 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "13.0.0" +version = "14.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index a43d8473a5..0b8341c99a 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [30.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.1...revm-precompile-v30.0.0) - 2025-11-10 +## [31.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.1...revm-precompile-v31.0.0) - 2025-11-10 ### Added diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index c6f90aad5b..b17b1b3dba 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "30.0.0" +version = "31.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 0e1c1c1437..35b5b241fb 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [32.0.0](https://github.com/bluealloy/revm/compare/revm-v31.0.2...revm-v32.0.0) - 2025-11-10 +## [33.0.0](https://github.com/bluealloy/revm/compare/revm-v31.0.2...revm-v33.0.0) - 2025-11-10 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 1886cf7991..5be12df1fc 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "32.0.0" +version = "33.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 956c45d542..138b1d5160 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [12.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.2...revm-statetest-types-v12.0.0) - 2025-11-10 +## [13.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.2...revm-statetest-types-v13.0.0) - 2025-11-10 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 1893941012..327d731148 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "12.0.0" +version = "13.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true From 1ab924b89f9bcc28b7b4dde8215e5391e87e55d0 Mon Sep 17 00:00:00 2001 From: Jonathan Yuen <5406198+jonathanykh@users.noreply.github.com> Date: Wed, 12 Nov 2025 18:04:19 +0800 Subject: [PATCH 042/127] fix: expose optional_priority_fee_check feature from context crate (#3159) The feature exists in the context crate but was not exposed in revm's Cargo.toml, making it inaccessible to users. --- crates/revm/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 5be12df1fc..e52aadfeaa 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -98,6 +98,7 @@ optional_eip3607 = ["context/optional_eip3607"] optional_eip7623 = ["context/optional_eip7623"] optional_no_base_fee = ["context/optional_no_base_fee"] optional_fee_charge = ["context/optional_fee_charge"] +optional_priority_fee_check = ["context/optional_priority_fee_check"] # Precompiles features: Please look at the comments in `precompile` crate for more information. From 9843e21eb42408c8655346e94486e748f76cbe1f Mon Sep 17 00:00:00 2001 From: Karl Bartel Date: Wed, 12 Nov 2025 11:04:37 +0100 Subject: [PATCH 043/127] feat(context): add mark_cold method to JournaledAccount (#3160) * feat(context): add mark_cold method to JournaledAccount Add a public `mark_cold()` method to `JournaledAccount` that delegates to the underlying `Account::mark_cold()`. This is analogous and provides a way to mark accounts as cold that was available in previous revm versions. This is used by celo-revm to provide backwards compatibility for the transfer precompile, which does not warm addresses in its initial implementation. * Declare mark_cold to be unsafe and add explanation. Co-authored-by: rakita --------- Co-authored-by: rakita --- .../context/interface/src/journaled_state/account.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/context/interface/src/journaled_state/account.rs b/crates/context/interface/src/journaled_state/account.rs index 4d42dd307e..6f00458523 100644 --- a/crates/context/interface/src/journaled_state/account.rs +++ b/crates/context/interface/src/journaled_state/account.rs @@ -77,6 +77,17 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { } } + /// Marks the account as cold without making a journal entry. + /// + /// Changing account without journal entry can be a footgun as reverting of the journal + /// would not happen without entry. It is the reason why this function has an `unsafe` prefix. + /// + /// If account is in access list, it would still be marked as warm if account get accessed again. + #[inline] + pub fn unsafe_mark_cold(&mut self) { + self.account.mark_cold(); + } + /// Sets the balance of the account. /// /// If balance is the same, we don't add a journal entry. From acdb49f8acdbbe7eee38547762ac1a0b5efae2c8 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Wed, 12 Nov 2025 18:06:00 +0400 Subject: [PATCH 044/127] call Inspector::log_full (#3164) --- crates/inspector/src/handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index 73e26cff8c..53bdf436db 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -260,7 +260,7 @@ fn inspect_log( } let log = context.journal_mut().logs().last().unwrap().clone(); - inspector.log(context, log); + inspector.log_full(interpreter, context, log); } #[inline(never)] From 72995318ece73f3b49beab7f18acdc3db4f16544 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 13 Nov 2025 02:42:13 +0100 Subject: [PATCH 045/127] feat: Add set_nonce journal entry and fn (#3163) --- .../interface/src/journaled_state/account.rs | 26 ++++++++++-- .../interface/src/journaled_state/entry.rs | 41 +++++++++++++++---- crates/context/src/journal/inner.rs | 4 +- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/crates/context/interface/src/journaled_state/account.rs b/crates/context/interface/src/journaled_state/account.rs index 6f00458523..2e219d4938 100644 --- a/crates/context/interface/src/journaled_state/account.rs +++ b/crates/context/interface/src/journaled_state/account.rs @@ -79,7 +79,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// Marks the account as cold without making a journal entry. /// - /// Changing account without journal entry can be a footgun as reverting of the journal + /// Changing account without journal entry can be a footgun as reverting of the state change /// would not happen without entry. It is the reason why this function has an `unsafe` prefix. /// /// If account is in access list, it would still be marked as warm if account get accessed again. @@ -143,11 +143,31 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { return false; }; self.account.info.set_nonce(nonce); - self.journal_entries - .push(ENTRY::nonce_changed(self.address)); + self.journal_entries.push(ENTRY::nonce_bumped(self.address)); true } + /// Set the nonce of the account and create a journal entry. + /// + /// Touches the account in all cases. + #[inline] + pub fn set_nonce(&mut self, nonce: u64) { + self.touch(); + let previous_nonce = self.account.info.nonce; + self.account.info.set_nonce(nonce); + self.journal_entries + .push(ENTRY::nonce_changed(self.address, previous_nonce)); + } + + /// Set the nonce of the account without creating a journal entry. + /// + /// Changing account without journal entry can be a footgun as reverting of the state change + /// would not happen without entry. It is the reason why this function has an `unsafe` prefix. + #[inline] + pub fn unsafe_set_nonce(&mut self, nonce: u64) { + self.account.info.set_nonce(nonce); + } + /// Sets the code of the account. /// /// Touches the account in all cases. diff --git a/crates/context/interface/src/journaled_state/entry.rs b/crates/context/interface/src/journaled_state/entry.rs index 00b5f17219..b6807fe07c 100644 --- a/crates/context/interface/src/journaled_state/entry.rs +++ b/crates/context/interface/src/journaled_state/entry.rs @@ -35,8 +35,11 @@ pub trait JournalEntryTr { /// Creates a journal entry for when an account's balance is changed. fn balance_changed(address: Address, old_balance: U256) -> Self; - /// Creates a journal entry for when an account's nonce is incremented. - fn nonce_changed(address: Address) -> Self; + /// Creates a journal entry for when an account's nonce is changed. + fn nonce_changed(address: Address, previous_nonce: u64) -> Self; + + /// Creates a journal entry for when an account's nonce is bumped. + fn nonce_bumped(address: Address) -> Self; /// Creates a journal entry for when a new account is created fn account_created(address: Address, is_created_globally: bool) -> Self; @@ -158,9 +161,19 @@ pub enum JournalEntry { to: Address, }, /// Increment nonce + /// Action: Set nonce + /// Revert: Revert to previous nonce + NonceChange { + /// Address of account that had its nonce changed. + /// Nonce is incremented by one. + address: Address, + /// Previous nonce of account. + previous_nonce: u64, + }, + /// Increment nonce /// Action: Increment nonce by one /// Revert: Decrement nonce by one - NonceChange { + NonceBump { /// Address of account that had its nonce changed. /// Nonce is incremented by one. address: Address, @@ -263,8 +276,15 @@ impl JournalEntryTr for JournalEntry { } } - fn nonce_changed(address: Address) -> Self { - JournalEntry::NonceChange { address } + fn nonce_changed(address: Address, previous_nonce: u64) -> Self { + JournalEntry::NonceChange { + address, + previous_nonce, + } + } + + fn nonce_bumped(address: Address) -> Self { + JournalEntry::NonceBump { address } } fn storage_warmed(address: Address, key: StorageKey) -> Self { @@ -346,8 +366,15 @@ impl JournalEntryTr for JournalEntry { let to = state.get_mut(&to).unwrap(); to.info.balance -= balance; } - JournalEntry::NonceChange { address } => { - state.get_mut(&address).unwrap().info.nonce -= 1; + JournalEntry::NonceChange { + address, + previous_nonce, + } => { + state.get_mut(&address).unwrap().info.nonce = previous_nonce; + } + JournalEntry::NonceBump { address } => { + let nonce = &mut state.get_mut(&address).unwrap().info.nonce; + *nonce = nonce.saturating_sub(1); } JournalEntry::AccountCreated { address, diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index d3137fbe2a..a5dd22549d 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -281,7 +281,7 @@ impl JournalInner { if bump_nonce { // nonce changed. - self.journal.push(ENTRY::nonce_changed(address)); + self.journal.push(ENTRY::nonce_bumped(address)); } } @@ -303,7 +303,7 @@ impl JournalInner { /// Increments the nonce of the account. #[inline] pub fn nonce_bump_journal_entry(&mut self, address: Address) { - self.journal.push(ENTRY::nonce_changed(address)); + self.journal.push(ENTRY::nonce_bumped(address)); } /// Transfers balance from two accounts. Returns error if sender balance is not enough. From 84d41bc0f8972e545c9b7a17df7f864d6326e1f4 Mon Sep 17 00:00:00 2001 From: Keemo Styler Date: Thu, 13 Nov 2025 09:20:44 +0700 Subject: [PATCH 046/127] fix(op-revm): return error when enveloped_tx is missing (#3143) * fix(op-revm): return error when enveloped_tx is missing * fmt * Remove unnecessary clone --- crates/op-revm/src/handler.rs | 6 +++++- crates/op-revm/src/l1block.rs | 10 +++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 925d9dc663..f444e6f420 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -152,7 +152,11 @@ where let mut balance = caller_account.info.balance; if !cfg.is_fee_charge_disabled() { - let additional_cost = chain.tx_cost_with_tx(tx, spec); + let Some(additional_cost) = chain.tx_cost_with_tx(tx, spec) else { + return Err(ERROR::from_string( + "[OPTIMISM] Failed to load enveloped transaction.".into(), + )); + }; let Some(new_balance) = balance.checked_sub(additional_cost) else { return Err(InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(additional_cost), diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index d39dc52ffe..cf61db7697 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -261,15 +261,11 @@ impl L1BlockInfo { /// Calculate additional transaction cost with OpTxTr. /// /// Internally calls [`L1BlockInfo::tx_cost`]. - #[track_caller] - pub fn tx_cost_with_tx(&mut self, tx: impl OpTxTr, spec: OpSpecId) -> U256 { + pub fn tx_cost_with_tx(&mut self, tx: impl OpTxTr, spec: OpSpecId) -> Option { // account for additional cost of l1 fee and operator fee - let enveloped_tx = tx - .enveloped_tx() - .expect("all not deposit tx have enveloped tx") - .clone(); + let enveloped_tx = tx.enveloped_tx()?; let gas_limit = U256::from(tx.gas_limit()); - self.tx_cost(&enveloped_tx, gas_limit, spec) + Some(self.tx_cost(enveloped_tx, gas_limit, spec)) } /// Calculate additional transaction cost. From 6a5f7183a3a1ad5cfc088ab008a3cf14029a39bf Mon Sep 17 00:00:00 2001 From: viktorking7 <140458814+viktorking7@users.noreply.github.com> Date: Thu, 13 Nov 2025 16:31:34 +0100 Subject: [PATCH 047/127] fix(database): return correct bytecode in BenchmarkDB::code_by_hash (#3170) --- crates/database/src/in_memory_db.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index 1437b8c024..86e44691f0 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -482,8 +482,12 @@ impl Database for BenchmarkDB { } /// Get account code by its hash - fn code_by_hash(&mut self, _code_hash: B256) -> Result { - Ok(Bytecode::default()) + fn code_by_hash(&mut self, code_hash: B256) -> Result { + if code_hash == self.1 { + Ok(self.0.clone()) + } else { + Ok(Bytecode::default()) + } } /// Get storage value of address at index. From 1100ac4db5504e3b1a69a7be795a172b67d7b470 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Fri, 14 Nov 2025 16:39:11 +0400 Subject: [PATCH 048/127] fix: correctly handle selfdestruct cold load (#3174) * fix: correctly handle selfdestruct cold load * add constantinople tests in script --- crates/interpreter/src/gas/calc.rs | 15 +++++++++++++-- crates/interpreter/src/instructions/host.rs | 7 ++++--- scripts/run-tests.sh | 5 ++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 89414c1294..8b41601c01 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -292,12 +292,23 @@ pub const fn dyn_selfdestruct_cost(spec_id: SpecId, res: &StateLoad u64 { + if spec_id.is_enabled_in(SpecId::BERLIN) { + COLD_ACCOUNT_ACCESS_COST + } else { + 0 + } +} + /// `SELFDESTRUCT` opcode cost calculation. #[inline] pub const fn selfdestruct_cost(spec_id: SpecId, res: StateLoad) -> u64 { diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index b60a5c9c76..e9d1c3645f 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -1,7 +1,8 @@ use crate::{ gas::{ - self, CALL_STIPEND, COLD_ACCOUNT_ACCESS_COST_ADDITIONAL, COLD_SLOAD_COST_ADDITIONAL, - ISTANBUL_SLOAD_GAS, WARM_STORAGE_READ_COST, + self, selfdestruct_cold_beneficiary_cost, CALL_STIPEND, + COLD_ACCOUNT_ACCESS_COST_ADDITIONAL, COLD_SLOAD_COST_ADDITIONAL, ISTANBUL_SLOAD_GAS, + WARM_STORAGE_READ_COST, }, instructions::utility::{IntoAddress, IntoU256}, interpreter_types::{InputsTr, InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}, @@ -395,7 +396,7 @@ pub fn selfdestruct( // static gas gas!(context.interpreter, gas::static_selfdestruct_cost(spec)); - let skip_cold = context.interpreter.gas.remaining() < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + let skip_cold = context.interpreter.gas.remaining() < selfdestruct_cold_beneficiary_cost(spec); let res = match context.host.selfdestruct( context.interpreter.input.target_address(), target, diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 4cc64460e5..402b93673f 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -148,9 +148,12 @@ run_tests() { echo "Running devnet statetests..." $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$DEVNET_DIR/state_tests" - echo "Running legacy tests..." + echo "Running legacy Cancun tests..." $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$LEGACY_DIR/Cancun/GeneralStateTests" + echo "Running legacy Constantinople tests..." + $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$LEGACY_DIR/Constantinople/GeneralStateTests" + echo "Running main develop blockchain tests..." $RUST_RUNNER run $CARGO_OPTS -p revme -- btest "$MAIN_DEVELOP_DIR/blockchain_tests" From 47d1ae263190cf3d54125596dca5a40f008166c8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 14 Nov 2025 14:17:38 +0100 Subject: [PATCH 049/127] chore: release (#3162) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 20 ++++++++++---------- Cargo.toml | 18 +++++++++--------- bins/revme/CHANGELOG.md | 6 ++++++ bins/revme/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 6 ++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 7 +++++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 6 ++++++ crates/database/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 6 ++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 6 ++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 6 ++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 6 ++++++ crates/op-revm/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 6 ++++++ crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 6 ++++++ crates/statetest-types/Cargo.toml | 2 +- 22 files changed, 90 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 59b4803302..d0b875ac86 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "14.0.0" +version = "14.0.1" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "33.0.0" +version = "33.0.1" dependencies = [ "revm-bytecode", "revm-context", @@ -3564,7 +3564,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "12.0.0" +version = "12.1.0" dependencies = [ "bitvec", "cfg-if", @@ -3580,7 +3580,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "13.0.0" +version = "13.1.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3594,7 +3594,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.5" +version = "9.0.6" dependencies = [ "alloy-eips", "alloy-provider", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "14.0.0" +version = "14.0.1" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "14.0.0" +version = "14.0.1" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "31.0.0" +version = "31.0.1" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "13.0.0" +version = "13.0.1" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "10.0.0" +version = "10.0.1" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 788a816333..5f363f66a9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "33.0.0", default-features = false } +revm = { path = "crates/revm", version = "33.0.1", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "9.0.5", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "9.0.6", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "31.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.0.0", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "31.0.1", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.0.1", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "31.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "13.0.0", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "12.0.0", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "13.0.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "14.0.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.0.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "13.0.1", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "12.1.0", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "13.1.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "14.0.1", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.0.1", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 098ddbdcef..91400bf3a3 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.0.1](https://github.com/bluealloy/revm/compare/revme-v10.0.0...revme-v10.0.1) - 2025-11-14 + +### Other + +- update Cargo.lock dependencies + ## [10.0.0](https://github.com/bluealloy/revm/compare/revme-v9.0.2...revme-v10.0.0) - 2025-11-10 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index ca0b42adf1..8fdd6bf360 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "10.0.0" +version = "10.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 5386dca18d..e1ee788814 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [12.1.0](https://github.com/bluealloy/revm/compare/revm-context-v12.0.0...revm-context-v12.1.0) - 2025-11-14 + +### Added + +- Add set_nonce journal entry and fn ([#3163](https://github.com/bluealloy/revm/pull/3163)) + ## [12.0.0](https://github.com/bluealloy/revm/compare/revm-context-v11.0.2...revm-context-v12.0.0) - 2025-11-10 ### Added diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 69e8ff0c03..26bce81389 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "12.0.0" +version = "12.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index cce3b20c72..380b0490df 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [13.1.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v13.0.0...revm-context-interface-v13.1.0) - 2025-11-14 + +### Added + +- Add set_nonce journal entry and fn ([#3163](https://github.com/bluealloy/revm/pull/3163)) +- *(context)* add mark_cold method to JournaledAccount ([#3160](https://github.com/bluealloy/revm/pull/3160)) + ## [13.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v12.0.1...revm-context-interface-v13.0.0) - 2025-11-10 ### Added diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 5fbe25d503..258df96e20 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "13.0.0" +version = "13.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index bace082cf4..bfa738a90b 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.6](https://github.com/bluealloy/revm/compare/revm-database-v9.0.5...revm-database-v9.0.6) - 2025-11-14 + +### Fixed + +- *(database)* return correct bytecode in BenchmarkDB::code_by_hash ([#3170](https://github.com/bluealloy/revm/pull/3170)) + ## [9.0.5](https://github.com/bluealloy/revm/compare/revm-database-v9.0.4...revm-database-v9.0.5) - 2025-11-10 ### Fixed diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index ed5bf165ea..6481ebaaaa 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "9.0.5" +version = "9.0.6" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 73f0b561a2..a95df85cb3 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.0.1](https://github.com/bluealloy/revm/compare/revm-handler-v14.0.0...revm-handler-v14.0.1) - 2025-11-14 + +### Other + +- updated the following local packages: revm-context-interface, revm-context, revm-database, revm-interpreter + ## [14.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v12.0.2...revm-handler-v14.0.0) - 2025-11-10 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index f2790b1cb1..3848dbd128 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "14.0.0" +version = "14.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index a40fc6e08a..8590b92293 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.0.1](https://github.com/bluealloy/revm/compare/revm-inspector-v14.0.0...revm-inspector-v14.0.1) - 2025-11-14 + +### Other + +- call Inspector::log_full ([#3164](https://github.com/bluealloy/revm/pull/3164)) + ## [14.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v12.0.2...revm-inspector-v14.0.0) - 2025-11-10 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index da4e851539..540ef6954f 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "14.0.0" +version = "14.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index cab0eb8869..f14fb072aa 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [31.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v31.0.0...revm-interpreter-v31.0.1) - 2025-11-14 + +### Fixed + +- correctly handle selfdestruct cold load ([#3174](https://github.com/bluealloy/revm/pull/3174)) + ## [31.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v29.0.1...revm-interpreter-v31.0.0) - 2025-11-10 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 974a453f2b..766b7f5ba8 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "31.0.0" +version = "31.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index c9f8dcdf65..30b342cd5f 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.0.1](https://github.com/bluealloy/revm/compare/op-revm-v14.0.0...op-revm-v14.0.1) - 2025-11-14 + +### Fixed + +- *(op-revm)* return error when enveloped_tx is missing ([#3143](https://github.com/bluealloy/revm/pull/3143)) + ## [14.0.0](https://github.com/bluealloy/revm/compare/op-revm-v12.0.2...op-revm-v14.0.0) - 2025-11-10 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 36c8956743..9649e0ecae 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "14.0.0" +version = "14.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 35b5b241fb..26e0c0213b 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [33.0.1](https://github.com/bluealloy/revm/compare/revm-v33.0.0...revm-v33.0.1) - 2025-11-14 + +### Fixed + +- expose optional_priority_fee_check feature from context crate ([#3159](https://github.com/bluealloy/revm/pull/3159)) + ## [33.0.0](https://github.com/bluealloy/revm/compare/revm-v31.0.2...revm-v33.0.0) - 2025-11-10 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index e52aadfeaa..31ca1cea0f 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "33.0.0" +version = "33.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 138b1d5160..63d743789e 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [13.0.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v13.0.0...revm-statetest-types-v13.0.1) - 2025-11-14 + +### Other + +- updated the following local packages: revm + ## [13.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v11.0.2...revm-statetest-types-v13.0.0) - 2025-11-10 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 327d731148..f14060d368 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "13.0.0" +version = "13.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true From 0d424ba11fd59d2a2a13988d61381e5b5cfccd22 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 14 Nov 2025 15:05:53 +0100 Subject: [PATCH 050/127] bump: tag v102 revm v33.1.0 (#3177) --- CHANGELOG.md | 29 +++++++++++++++++++++++++++++ Cargo.lock | 14 +++++++------- Cargo.toml | 12 ++++++------ MIGRATION_GUIDE.md | 8 ++++++++ bins/revme/CHANGELOG.md | 2 +- bins/revme/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 2 +- crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 2 +- crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 2 +- crates/op-revm/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 2 +- crates/statetest-types/Cargo.toml | 2 +- 18 files changed, 64 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8e364dbf6..8451e94b3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v102 +date: 14.11.2025 + +Fix for pre berlin selfdestruct oog introduced in v99/v100 tag (revm 32.0.0). + +* `revm-context-interface`: 13.0.0 -> 13.1.0 (✓ API compatible changes) +* `revm-context`: 12.0.0 -> 12.1.0 (✓ API compatible changes) +* `revm-database`: 9.0.5 -> 9.0.6 (✓ API compatible changes) +* `revm-interpreter`: 31.0.0 -> 31.1.0 (✓ API compatible changes) +* `revm-inspector`: 14.0.0 -> 14.1.0 (✓ API compatible changes) +* `revm`: 33.0.0 -> 33.1.0 (✓ API compatible changes) +* `revme`: 10.0.0 -> 10.0.2 (✓ API compatible changes) +* `op-revm`: 14.0.0 -> 14.1.0 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-handler`: 14.0.0 -> 14.1.0 +* `revm-statetest-types`: 13.0.0 -> 13.1.0 + +# v101 +date: 13.11.2025 + +Patch for Inspector so full_log will be called inside loop. + +* `revm-inspector`: 14.0.0 -> 14.0.1 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm`: 33.0.0 -> 33.0.1 +* `revm-statetest-types`: 13.0.0 -> 13.0.1 +* `revme`: 10.0.0 -> 10.0.1 +* `op-revm`: 14.0.0 -> 14.0.1 + # v100 date: 12.11.2025 diff --git a/Cargo.lock b/Cargo.lock index d0b875ac86..2bfea74c52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2922,7 +2922,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "14.0.1" +version = "14.1.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3533,7 +3533,7 @@ dependencies = [ [[package]] name = "revm" -version = "33.0.1" +version = "33.1.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3636,7 +3636,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "14.0.1" +version = "14.1.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3657,7 +3657,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "14.0.1" +version = "14.1.0" dependencies = [ "auto_impl", "either", @@ -3674,7 +3674,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "31.0.1" +version = "31.1.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3734,7 +3734,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "13.0.1" +version = "13.1.0" dependencies = [ "alloy-eips", "k256", @@ -3746,7 +3746,7 @@ dependencies = [ [[package]] name = "revme" -version = "10.0.1" +version = "10.0.2" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 5f363f66a9..e60b33f097 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "33.0.1", default-features = false } +revm = { path = "crates/revm", version = "33.1.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } database = { path = "crates/database", package = "revm-database", version = "9.0.6", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "31.0.1", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.0.1", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "31.1.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.1.0", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "31.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "13.0.1", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "13.1.0", default-features = false } context = { path = "crates/context", package = "revm-context", version = "12.1.0", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "13.1.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "14.0.1", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.0.1", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "14.1.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.1.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index cc332df20d..2f9751276e 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,12 @@ +# 102 tag ( revm v33.1.0) + +No breaking changes + +# 101 tag ( revm v33.1.0) + +No breaking changes + # v100 tag (revm v33.0.0) * Additionally to v99 version: diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 91400bf3a3..eb15baf5c0 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [10.0.1](https://github.com/bluealloy/revm/compare/revme-v10.0.0...revme-v10.0.1) - 2025-11-14 +## [10.0.2](https://github.com/bluealloy/revm/compare/revme-v10.0.0...revme-v10.0.2) - 2025-11-14 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 8fdd6bf360..fd6296161b 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "10.0.1" +version = "10.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index a95df85cb3..792f6dabd2 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [14.0.1](https://github.com/bluealloy/revm/compare/revm-handler-v14.0.0...revm-handler-v14.0.1) - 2025-11-14 +## [14.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v14.0.0...revm-handler-v14.1.0) - 2025-11-14 ### Other diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 3848dbd128..3631a310fa 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "14.0.1" +version = "14.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 8590b92293..355f7530f5 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [14.0.1](https://github.com/bluealloy/revm/compare/revm-inspector-v14.0.0...revm-inspector-v14.0.1) - 2025-11-14 +## [14.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v14.0.0...revm-inspector-v14.1.0) - 2025-11-14 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 540ef6954f..c0834aa95b 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "14.0.1" +version = "14.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index f14fb072aa..f9bcf99999 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [31.0.1](https://github.com/bluealloy/revm/compare/revm-interpreter-v31.0.0...revm-interpreter-v31.0.1) - 2025-11-14 +## [31.1.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v31.0.0...revm-interpreter-v31.1.0) - 2025-11-14 ### Fixed diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 766b7f5ba8..83de6d17ea 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "31.0.1" +version = "31.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index 30b342cd5f..e06472495d 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [14.0.1](https://github.com/bluealloy/revm/compare/op-revm-v14.0.0...op-revm-v14.0.1) - 2025-11-14 +## [14.1.0](https://github.com/bluealloy/revm/compare/op-revm-v14.0.0...op-revm-v14.1.0) - 2025-11-14 ### Fixed diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 9649e0ecae..767d0f7cf2 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "14.0.1" +version = "14.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 26e0c0213b..4b51b21947 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [33.0.1](https://github.com/bluealloy/revm/compare/revm-v33.0.0...revm-v33.0.1) - 2025-11-14 +## [33.1.0](https://github.com/bluealloy/revm/compare/revm-v33.0.0...revm-v33.1.0) - 2025-11-14 ### Fixed diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 31ca1cea0f..c2c5ef0aed 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "33.0.1" +version = "33.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 63d743789e..32bf941789 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [13.0.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v13.0.0...revm-statetest-types-v13.0.1) - 2025-11-14 +## [13.1.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v13.0.0...revm-statetest-types-v13.1.0) - 2025-11-14 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index f14060d368..61eb508318 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "13.0.1" +version = "13.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true From d0bb48ef6ebf6db67df0f9409408b2afc73241f2 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 17 Nov 2025 13:52:53 +0100 Subject: [PATCH 051/127] chore(test): rn unused folders to free space (#3180) * chore(test): rn tar after download * try with latest * print size,and rm unused files * rm du prints --- Cross.toml | 4 ++-- scripts/run-tests.sh | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/Cross.toml b/Cross.toml index d25de22494..5d1593b9e2 100644 --- a/Cross.toml +++ b/Cross.toml @@ -4,7 +4,7 @@ pre-build = [ ] [target.i686-unknown-linux-gnu] -image = "ghcr.io/cross-rs/i686-unknown-linux-gnu:main" +image = "ghcr.io/cross-rs/i686-unknown-linux-gnu:latest" [target.x86_64-unknown-linux-gnu] -image = "ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main" +image = "ghcr.io/cross-rs/x86_64-unknown-linux-gnu:latest" diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 402b93673f..3b53c88d57 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -95,20 +95,25 @@ download_and_extract() { # This is needed because when we extract the tar, it is placed under an # unnecessary "fixtures/" directory. tar -xzf "${FIXTURES_DIR}/${tar_file}" --strip-components=1 -C "$target_dir" + + # Remove the tar file + rm "${FIXTURES_DIR}/${tar_file}" + + # remove all unused folders + find "$target_dir" -depth -name blockchain_tests_engine -exec rm -rf {} \; + find "$target_dir" -depth -name blockchain_tests_engine_x -exec rm -rf {} \; + find "$target_dir" -depth -name blockchain_tests_sync -exec rm -rf {} \; } # Download all fixtures download_fixtures() { echo "Creating fixtures directory structure..." mkdir -p "$MAIN_STABLE_DIR" "$MAIN_DEVELOP_DIR" "$DEVNET_DIR" "$LEGACY_DIR" - + download_and_extract "$MAIN_STABLE_DIR" "$MAIN_STABLE_TAR" "main stable" "$MAIN_VERSION" download_and_extract "$MAIN_DEVELOP_DIR" "$MAIN_DEVELOP_TAR" "main develop" "$MAIN_VERSION" download_and_extract "$DEVNET_DIR" "$DEVNET_TAR" "devnet" "$DEVNET_VERSION" - echo "Cleaning up tar files..." - rm "${FIXTURES_DIR}/${MAIN_STABLE_TAR}" "${FIXTURES_DIR}/${MAIN_DEVELOP_TAR}" "${FIXTURES_DIR}/${DEVNET_TAR}" - # Clone legacytests repository echo "Cloning legacytests repository..." git clone --depth 1 "$LEGACY_REPO_URL" "$LEGACY_DIR" From 9f1faf93188e889373e17ed5f8fe22f19413d71d Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 20 Nov 2025 19:17:00 +0800 Subject: [PATCH 052/127] feat: sort accounts by address in blockchaintest output (#3182) --- bins/revme/src/cmd/blockchaintest.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 8f60690b3d..943dc81902 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -558,7 +558,10 @@ fn print_error_with_state( // Print state comparison eprintln!("\n💾 Pre-State (Initial):"); - for (address, (info, storage)) in &debug_info.pre_state { + // Sort accounts by address for consistent output + let mut sorted_accounts: Vec<_> = debug_info.pre_state.iter().collect(); + sorted_accounts.sort_by_key(|(addr, _)| *addr); + for (address, (info, storage)) in sorted_accounts { eprintln!(" Account {address:?}:"); eprintln!(" Balance: 0x{:x}", info.balance); eprintln!(" Nonce: {}", info.nonce); @@ -580,7 +583,10 @@ fn print_error_with_state( eprintln!("\n📝 Current State (Actual):"); let committed_state = DebugInfo::capture_committed_state(current_state); - for (address, (info, storage)) in &committed_state { + // Sort accounts by address for consistent output + let mut sorted_current: Vec<_> = committed_state.iter().collect(); + sorted_current.sort_by_key(|(addr, _)| *addr); + for (address, (info, storage)) in sorted_current { eprintln!(" Account {address:?}:"); eprintln!(" Balance: 0x{:x}", info.balance); eprintln!(" Nonce: {}", info.nonce); From 832818741ce832f9332ef35f0a924075b74e54f1 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 20 Nov 2025 16:36:35 +0100 Subject: [PATCH 053/127] chore(fmt): merge all imports (#3184) --- bins/revme/src/cmd/bench/burntpix.rs | 3 +-- bins/revme/src/cmd/blockchaintest.rs | 10 ++++++---- bins/revme/src/cmd/evmrunner.rs | 4 +--- bins/revme/src/cmd/statetest/merkle_trie.rs | 2 +- bins/revme/src/cmd/statetest/runner.rs | 3 +-- crates/context/interface/src/cfg.rs | 3 +-- crates/context/interface/src/transaction.rs | 3 +-- crates/context/src/evm.rs | 6 ++++-- crates/context/src/journal/inner.rs | 2 +- crates/database/interface/src/empty_db.rs | 3 +-- crates/ee-tests/src/op_revm_tests.rs | 3 +-- crates/handler/src/frame.rs | 19 +++++++++---------- crates/handler/src/handler.rs | 14 +++++++------- crates/handler/src/mainnet_builder.rs | 6 ++---- crates/handler/src/pre_execution.rs | 9 +++------ crates/handler/src/precompile_provider.rs | 9 +++++---- crates/inspector/src/eip3155.rs | 3 +-- .../src/interpreter/ext_bytecode/serde.rs | 3 +-- crates/interpreter/src/interpreter_types.rs | 6 ++++-- crates/interpreter/src/lib.rs | 3 +-- crates/op-revm/src/fast_lz.rs | 5 ++--- crates/op-revm/src/precompiles.rs | 3 +-- crates/precompile/bench/eip1962.rs | 3 +-- crates/precompile/src/bls12_381/g1_add.rs | 4 +--- crates/precompile/src/bls12_381/g1_msm.rs | 16 +++++++++------- crates/precompile/src/bls12_381/g2_add.rs | 4 +--- crates/precompile/src/bls12_381/g2_msm.rs | 10 +++++----- .../precompile/src/bls12_381/map_fp2_to_g2.rs | 6 +++--- .../precompile/src/bls12_381/map_fp_to_g1.rs | 2 +- crates/precompile/src/bls12_381/pairing.rs | 12 +++++++----- crates/precompile/src/bls12_381/utils.rs | 8 +++++--- crates/precompile/src/id.rs | 3 +-- .../src/kzg_point_evaluation/arkworks.rs | 7 ++++--- .../src/kzg_point_evaluation/blst.rs | 12 +++++++----- crates/primitives/src/lib.rs | 6 +++--- crates/revm/src/lib.rs | 6 ++++-- crates/state/src/lib.rs | 3 +-- .../statetest-types/src/test_authorization.rs | 3 +-- examples/block_traces/src/main.rs | 13 ++++++------- .../src/precompile_provider.rs | 3 +-- 40 files changed, 116 insertions(+), 127 deletions(-) diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index bbeaee7de5..8d1a0641b0 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -12,8 +12,7 @@ use revm::{ context::TxEnv, database::{CacheDB, BENCH_CALLER}, database_interface::EmptyDB, - primitives::{hex, keccak256, Address, Bytes, TxKind, B256, U256}, - primitives::{StorageKey, StorageValue}, + primitives::{hex, keccak256, Address, Bytes, StorageKey, StorageValue, TxKind, B256, U256}, state::{AccountInfo, Bytecode}, Context, ExecuteEvm, MainBuilder, MainContext, }; diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 943dc81902..f286a3ca85 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -18,10 +18,12 @@ use serde_json::json; use statetest_types::blockchain::{ Account, BlockchainTest, BlockchainTestCase, ForkSpec, Withdrawal, }; -use std::collections::BTreeMap; -use std::fs; -use std::path::{Path, PathBuf}; -use std::time::Instant; +use std::{ + collections::BTreeMap, + fs, + path::{Path, PathBuf}, + time::Instant, +}; use thiserror::Error; use walkdir::{DirEntry, WalkDir}; diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 7708f7a69f..2613007cc4 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -7,9 +7,7 @@ use revm::{ primitives::{hex, TxKind}, Context, Database, ExecuteEvm, MainBuilder, MainContext, }; -use std::path::PathBuf; -use std::{borrow::Cow, fs}; -use std::{io::Error as IoError, time::Instant}; +use std::{borrow::Cow, fs, io::Error as IoError, path::PathBuf, time::Instant}; #[derive(Debug, thiserror::Error)] pub enum Errors { diff --git a/bins/revme/src/cmd/statetest/merkle_trie.rs b/bins/revme/src/cmd/statetest/merkle_trie.rs index b8af986d7a..34ac105132 100644 --- a/bins/revme/src/cmd/statetest/merkle_trie.rs +++ b/bins/revme/src/cmd/statetest/merkle_trie.rs @@ -3,10 +3,10 @@ use std::convert::Infallible; use alloy_rlp::{RlpEncodable, RlpMaxEncodedLen}; use hash_db::Hasher; use plain_hasher::PlainHasher; -use revm::primitives::{keccak256, Address, Log, B256, U256}; use revm::{ context::result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, database::{EmptyDB, PlainAccount, State}, + primitives::{keccak256, Address, Log, B256, U256}, }; use triehash::sec_trie_root; diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 2ea90806c8..9303041496 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -9,8 +9,7 @@ use revm::{ database, database_interface::EmptyDB, inspector::{inspectors::TracerEip3155, InspectCommitEvm}, - primitives::U256, - primitives::{hardfork::SpecId, Bytes, B256}, + primitives::{hardfork::SpecId, Bytes, B256, U256}, Context, ExecuteCommitEvm, MainBuilder, MainContext, }; use serde_json::json; diff --git a/crates/context/interface/src/cfg.rs b/crates/context/interface/src/cfg.rs index c8792c47ec..11e5d99659 100644 --- a/crates/context/interface/src/cfg.rs +++ b/crates/context/interface/src/cfg.rs @@ -1,7 +1,6 @@ //! Configuration for the EVM. Containing [`SpecId`]. use auto_impl::auto_impl; -use core::fmt::Debug; -use core::hash::Hash; +use core::{fmt::Debug, hash::Hash}; use primitives::{hardfork::SpecId, Address, TxKind, U256}; /// Configuration for the EVM. diff --git a/crates/context/interface/src/transaction.rs b/crates/context/interface/src/transaction.rs index a1cd0a3097..6fd8dc5b7f 100644 --- a/crates/context/interface/src/transaction.rs +++ b/crates/context/interface/src/transaction.rs @@ -15,8 +15,7 @@ pub use transaction_type::TransactionType; use crate::result::InvalidTransaction; use auto_impl::auto_impl; -use core::cmp::min; -use core::fmt::Debug; +use core::{cmp::min, fmt::Debug}; use primitives::{eip4844::GAS_PER_BLOB, Address, Bytes, TxKind, B256, U256}; use std::boxed::Box; diff --git a/crates/context/src/evm.rs b/crates/context/src/evm.rs index 786505fdb7..283fa917b2 100644 --- a/crates/context/src/evm.rs +++ b/crates/context/src/evm.rs @@ -1,6 +1,8 @@ //! This module contains [`Evm`] struct. -use core::fmt::Debug; -use core::ops::{Deref, DerefMut}; +use core::{ + fmt::Debug, + ops::{Deref, DerefMut}, +}; use context_interface::FrameStack; diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a5dd22549d..a624a3e378 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -6,8 +6,8 @@ use context_interface::{ journaled_state::{ account::JournaledAccount, entry::{JournalEntryTr, SelfdestructionRevertStatus}, + AccountLoad, JournalCheckpoint, JournalLoadError, TransferError, }, - journaled_state::{AccountLoad, JournalCheckpoint, JournalLoadError, TransferError}, }; use core::mem; use database_interface::Database; diff --git a/crates/database/interface/src/empty_db.rs b/crates/database/interface/src/empty_db.rs index 455dcf35e6..ab7264c2ad 100644 --- a/crates/database/interface/src/empty_db.rs +++ b/crates/database/interface/src/empty_db.rs @@ -1,7 +1,6 @@ //! Empty database implementation. use crate::{DBErrorMarker, Database, DatabaseRef}; -use core::error::Error; -use core::{convert::Infallible, fmt, marker::PhantomData}; +use core::{convert::Infallible, error::Error, fmt, marker::PhantomData}; use primitives::{keccak256, Address, StorageKey, StorageValue, B256}; use state::{AccountInfo, Bytecode}; use std::string::ToString; diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index ecab88cd09..1e44ad1f67 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -23,8 +23,7 @@ use revm::{ state::Bytecode, Context, ExecuteEvm, InspectEvm, Inspector, Journal, SystemCallEvm, }; -use std::path::PathBuf; -use std::vec::Vec; +use std::{path::PathBuf, vec::Vec}; // Re-export the constant for testdata directory path const TESTS_TESTDATA: &str = "tests/op_revm_testdata"; diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index a85ebed8a5..aeecddd1a3 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -1,21 +1,20 @@ -use crate::evm::FrameTr; -use crate::item_or_result::FrameInitOrResult; -use crate::{precompile_provider::PrecompileProvider, ItemOrResult}; -use crate::{CallFrame, CreateFrame, FrameData, FrameResult}; +use crate::{ + evm::FrameTr, item_or_result::FrameInitOrResult, precompile_provider::PrecompileProvider, + CallFrame, CreateFrame, FrameData, FrameResult, ItemOrResult, +}; use context::result::FromStringError; -use context_interface::context::ContextError; -use context_interface::local::{FrameToken, OutFrame}; -use context_interface::ContextTr; use context_interface::{ + context::ContextError, journaled_state::{JournalCheckpoint, JournalTr}, - Cfg, Database, + local::{FrameToken, OutFrame}, + Cfg, ContextTr, Database, }; use core::cmp::min; use derive_where::derive_where; -use interpreter::interpreter_action::FrameInit; use interpreter::{ gas, interpreter::{EthInterpreter, ExtBytecode}, + interpreter_action::FrameInit, interpreter_types::ReturnData, CallInput, CallInputs, CallOutcome, CallValue, CreateInputs, CreateOutcome, CreateScheme, FrameInput, Gas, InputsImpl, InstructionResult, Interpreter, InterpreterAction, @@ -24,8 +23,8 @@ use interpreter::{ use primitives::{ constants::CALL_STACK_LIMIT, hardfork::SpecId::{self, HOMESTEAD, LONDON, SPURIOUS_DRAGON}, + keccak256, Address, Bytes, U256, }; -use primitives::{keccak256, Address, Bytes, U256}; use state::Bytecode; use std::{borrow::ToOwned, boxed::Box, vec::Vec}; diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 01c7f56194..253517cd95 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -2,16 +2,16 @@ use crate::{ evm::FrameTr, execution, post_execution, pre_execution, validation, EvmTr, FrameResult, ItemOrResult, }; -use context::result::{ExecutionResult, FromStringError}; -use context::LocalContextTr; -use context_interface::context::ContextError; -use context_interface::ContextTr; +use context::{ + result::{ExecutionResult, FromStringError}, + LocalContextTr, +}; use context_interface::{ + context::ContextError, result::{HaltReasonTr, InvalidHeader, InvalidTransaction}, - Cfg, Database, JournalTr, Transaction, + Cfg, ContextTr, Database, JournalTr, Transaction, }; -use interpreter::interpreter_action::FrameInit; -use interpreter::{Gas, InitialAndFloorGas, SharedMemory}; +use interpreter::{interpreter_action::FrameInit, Gas, InitialAndFloorGas, SharedMemory}; use primitives::U256; use state::Bytecode; diff --git a/crates/handler/src/mainnet_builder.rs b/crates/handler/src/mainnet_builder.rs index 69e981c530..a640da1aca 100644 --- a/crates/handler/src/mainnet_builder.rs +++ b/crates/handler/src/mainnet_builder.rs @@ -73,8 +73,7 @@ impl MainContext for Context, #[cfg(test)] mod test { - use crate::ExecuteEvm; - use crate::{MainBuilder, MainContext}; + use crate::{ExecuteEvm, MainBuilder, MainContext}; use alloy_signer::{Either, SignerSync}; use alloy_signer_local::PrivateKeySigner; use bytecode::{ @@ -84,8 +83,7 @@ mod test { use context::{Context, TxEnv}; use context_interface::transaction::Authorization; use database::{BenchmarkDB, EEADDRESS, FFADDRESS}; - use primitives::{hardfork::SpecId, TxKind, U256}; - use primitives::{StorageKey, StorageValue}; + use primitives::{hardfork::SpecId, StorageKey, StorageValue, TxKind, U256}; #[test] fn sanity_eip7702_tx() { diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 346b79ffc3..cf1f27124b 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -4,17 +4,14 @@ use crate::{EvmTr, PrecompileProvider}; use bytecode::Bytecode; -use context_interface::transaction::{AccessListItemTr, AuthorizationTr}; -use context_interface::ContextTr; use context_interface::{ journaled_state::JournalTr, result::InvalidTransaction, - transaction::{Transaction, TransactionType}, - Block, Cfg, Database, + transaction::{AccessListItemTr, AuthorizationTr, Transaction, TransactionType}, + Block, Cfg, ContextTr, Database, }; use core::cmp::Ordering; -use primitives::{eip7702, hardfork::SpecId, U256}; -use primitives::{Address, HashMap, HashSet, StorageKey}; +use primitives::{eip7702, hardfork::SpecId, Address, HashMap, HashSet, StorageKey, U256}; use state::AccountInfo; /// Loads and warms accounts for execution, including precompiles and access list. diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index 98583d6a65..c3ac4a3e0c 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -2,11 +2,12 @@ use auto_impl::auto_impl; use context::{Cfg, LocalContextTr}; use context_interface::{ContextTr, JournalTr}; use interpreter::{CallInput, CallInputs, Gas, InstructionResult, InterpreterResult}; -use precompile::PrecompileError; -use precompile::{PrecompileSpecId, Precompiles}; +use precompile::{PrecompileError, PrecompileSpecId, Precompiles}; use primitives::{hardfork::SpecId, Address, Bytes}; -use std::boxed::Box; -use std::string::{String, ToString}; +use std::{ + boxed::Box, + string::{String, ToString}, +}; /// Provider for precompiled contracts in the EVM. #[auto_impl(&mut, Box)] diff --git a/crates/inspector/src/eip3155.rs b/crates/inspector/src/eip3155.rs index 841e12eede..3d9c9d86a1 100644 --- a/crates/inspector/src/eip3155.rs +++ b/crates/inspector/src/eip3155.rs @@ -1,5 +1,4 @@ -use crate::inspectors::GasInspector; -use crate::Inspector; +use crate::{inspectors::GasInspector, Inspector}; use context::{Cfg, ContextTr, JournalTr, Transaction}; use interpreter::{ interpreter_types::{Jumps, LoopControl, MemoryTr, StackTr}, diff --git a/crates/interpreter/src/interpreter/ext_bytecode/serde.rs b/crates/interpreter/src/interpreter/ext_bytecode/serde.rs index 8c5457e361..0635f29a0d 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode/serde.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode/serde.rs @@ -2,8 +2,7 @@ use super::ExtBytecode; use crate::interpreter::Jumps; use primitives::B256; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::borrow::Cow; -use std::format; +use std::{borrow::Cow, format}; #[derive(Serialize, Deserialize)] struct ExtBytecodeSerde<'a> { diff --git a/crates/interpreter/src/interpreter_types.rs b/crates/interpreter/src/interpreter_types.rs index 3478be4ea2..0195ee93fa 100644 --- a/crates/interpreter/src/interpreter_types.rs +++ b/crates/interpreter/src/interpreter_types.rs @@ -1,6 +1,8 @@ use crate::{CallInput, InstructionResult, InterpreterAction}; -use core::cell::Ref; -use core::ops::{Deref, Range}; +use core::{ + cell::Ref, + ops::{Deref, Range}, +}; use primitives::{hardfork::SpecId, Address, Bytes, B256, U256}; /// Helper function to read immediates data from the bytecode diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 8c0a6b87b1..675554b623 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -28,9 +28,8 @@ pub mod interpreter_types; // Reexport primary types. pub use context_interface::{ context::{SStoreResult, SelfDestructResult, StateLoad}, - CreateScheme, + host, CreateScheme, Host, }; -pub use context_interface::{host, Host}; pub use gas::{Gas, InitialAndFloorGas}; pub use instruction_context::InstructionContext; pub use instruction_result::*; diff --git a/crates/op-revm/src/fast_lz.rs b/crates/op-revm/src/fast_lz.rs index a1a262a079..7d1f1c57a6 100644 --- a/crates/op-revm/src/fast_lz.rs +++ b/crates/op-revm/src/fast_lz.rs @@ -112,14 +112,13 @@ fn u24(input: &[u8], idx: u32) -> u32 { mod tests { use super::*; use crate::api::{builder::OpBuilder, default_ctx::DefaultOp}; - use alloy_sol_types::sol; - use alloy_sol_types::SolCall; + use alloy_sol_types::{sol, SolCall}; use revm::{ bytecode::Bytecode, database::{BenchmarkDB, EEADDRESS, FFADDRESS}, primitives::{bytes, Bytes, TxKind, U256}, + Context, ExecuteEvm, }; - use revm::{Context, ExecuteEvm}; use rstest::rstest; use std::vec::Vec; diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index 3de2d0813d..d234980164 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -11,8 +11,7 @@ use revm::{ }, primitives::{hardfork::SpecId, Address, OnceLock}, }; -use std::boxed::Box; -use std::string::String; +use std::{boxed::Box, string::String}; /// Optimism precompile provider #[derive(Debug, Clone)] diff --git a/crates/precompile/bench/eip1962.rs b/crates/precompile/bench/eip1962.rs index afcc0b77f4..1e3371fc8f 100644 --- a/crates/precompile/bench/eip1962.rs +++ b/crates/precompile/bench/eip1962.rs @@ -1,7 +1,6 @@ //! Benchmarks for the BN254 precompiles use criterion::{measurement::Measurement, BenchmarkGroup}; -use primitives::hex; -use primitives::Bytes; +use primitives::{hex, Bytes}; use revm_precompile::bn254::{ add::ISTANBUL_ADD_GAS_COST, mul::ISTANBUL_MUL_GAS_COST, diff --git a/crates/precompile/src/bls12_381/g1_add.rs b/crates/precompile/src/bls12_381/g1_add.rs index 07e0112321..facb6bc4a2 100644 --- a/crates/precompile/src/bls12_381/g1_add.rs +++ b/crates/precompile/src/bls12_381/g1_add.rs @@ -1,9 +1,7 @@ //! BLS12-381 G1 add precompile. More details in [`g1_add`] use super::utils::{pad_g1_point, remove_g1_padding}; -use crate::bls12_381_const::{ - G1_ADD_ADDRESS, G1_ADD_BASE_GAS_FEE, G1_ADD_INPUT_LENGTH, PADDED_G1_LENGTH, -}; use crate::{ + bls12_381_const::{G1_ADD_ADDRESS, G1_ADD_BASE_GAS_FEE, G1_ADD_INPUT_LENGTH, PADDED_G1_LENGTH}, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index 7a2d07505c..2651be2df7 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -1,12 +1,14 @@ //! BLS12-381 G1 msm precompile. More details in [`g1_msm`] -use crate::bls12_381::utils::{pad_g1_point, remove_g1_padding}; -use crate::bls12_381::G1Point; -use crate::bls12_381_const::{ - DISCOUNT_TABLE_G1_MSM, G1_MSM_ADDRESS, G1_MSM_BASE_GAS_FEE, G1_MSM_INPUT_LENGTH, - PADDED_G1_LENGTH, SCALAR_LENGTH, -}; -use crate::bls12_381_utils::msm_required_gas; use crate::{ + bls12_381::{ + utils::{pad_g1_point, remove_g1_padding}, + G1Point, + }, + bls12_381_const::{ + DISCOUNT_TABLE_G1_MSM, G1_MSM_ADDRESS, G1_MSM_BASE_GAS_FEE, G1_MSM_INPUT_LENGTH, + PADDED_G1_LENGTH, SCALAR_LENGTH, + }, + bls12_381_utils::msm_required_gas, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; diff --git a/crates/precompile/src/bls12_381/g2_add.rs b/crates/precompile/src/bls12_381/g2_add.rs index 63cb6b6a51..d0d909e172 100644 --- a/crates/precompile/src/bls12_381/g2_add.rs +++ b/crates/precompile/src/bls12_381/g2_add.rs @@ -1,9 +1,7 @@ //! BLS12-381 G2 add precompile. More details in [`g2_add`] use super::utils::{pad_g2_point, remove_g2_padding}; -use crate::bls12_381_const::{ - G2_ADD_ADDRESS, G2_ADD_BASE_GAS_FEE, G2_ADD_INPUT_LENGTH, PADDED_G2_LENGTH, -}; use crate::{ + bls12_381_const::{G2_ADD_ADDRESS, G2_ADD_BASE_GAS_FEE, G2_ADD_INPUT_LENGTH, PADDED_G2_LENGTH}, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index a37a7df623..78cc319028 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -1,11 +1,11 @@ //! BLS12-381 G2 msm precompile. More details in [`g2_msm`] use super::utils::{pad_g2_point, remove_g2_padding}; -use crate::bls12_381_const::{ - DISCOUNT_TABLE_G2_MSM, G2_MSM_ADDRESS, G2_MSM_BASE_GAS_FEE, G2_MSM_INPUT_LENGTH, - PADDED_G2_LENGTH, SCALAR_LENGTH, -}; -use crate::bls12_381_utils::msm_required_gas; use crate::{ + bls12_381_const::{ + DISCOUNT_TABLE_G2_MSM, G2_MSM_ADDRESS, G2_MSM_BASE_GAS_FEE, G2_MSM_INPUT_LENGTH, + PADDED_G2_LENGTH, SCALAR_LENGTH, + }, + bls12_381_utils::msm_required_gas, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; diff --git a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs index f16cb8cb99..02091c4972 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -1,9 +1,9 @@ //! BLS12-381 map fp2 to g2 precompile. More details in [`map_fp2_to_g2`] use super::utils::{pad_g2_point, remove_fp_padding}; -use crate::bls12_381_const::{ - MAP_FP2_TO_G2_ADDRESS, MAP_FP2_TO_G2_BASE_GAS_FEE, PADDED_FP2_LENGTH, PADDED_FP_LENGTH, -}; use crate::{ + bls12_381_const::{ + MAP_FP2_TO_G2_ADDRESS, MAP_FP2_TO_G2_BASE_GAS_FEE, PADDED_FP2_LENGTH, PADDED_FP_LENGTH, + }, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; diff --git a/crates/precompile/src/bls12_381/map_fp_to_g1.rs b/crates/precompile/src/bls12_381/map_fp_to_g1.rs index 1babc3ae8a..80e548ce14 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -1,7 +1,7 @@ //! BLS12-381 map fp to g1 precompile. More details in [`map_fp_to_g1`] use super::utils::{pad_g1_point, remove_fp_padding}; -use crate::bls12_381_const::{MAP_FP_TO_G1_ADDRESS, MAP_FP_TO_G1_BASE_GAS_FEE, PADDED_FP_LENGTH}; use crate::{ + bls12_381_const::{MAP_FP_TO_G1_ADDRESS, MAP_FP_TO_G1_BASE_GAS_FEE, PADDED_FP_LENGTH}, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index 654d0865f9..c598e1b2d6 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -1,11 +1,13 @@ //! BLS12-381 pairing precompile. More details in [`pairing`] -use super::utils::{remove_g1_padding, remove_g2_padding}; -use super::PairingPair; -use crate::bls12_381_const::{ - PADDED_G1_LENGTH, PADDED_G2_LENGTH, PAIRING_ADDRESS, PAIRING_INPUT_LENGTH, - PAIRING_MULTIPLIER_BASE, PAIRING_OFFSET_BASE, +use super::{ + utils::{remove_g1_padding, remove_g2_padding}, + PairingPair, }; use crate::{ + bls12_381_const::{ + PADDED_G1_LENGTH, PADDED_G2_LENGTH, PAIRING_ADDRESS, PAIRING_INPUT_LENGTH, + PAIRING_MULTIPLIER_BASE, PAIRING_OFFSET_BASE, + }, crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; use primitives::B256; diff --git a/crates/precompile/src/bls12_381/utils.rs b/crates/precompile/src/bls12_381/utils.rs index 335ceda278..74f91d2e92 100644 --- a/crates/precompile/src/bls12_381/utils.rs +++ b/crates/precompile/src/bls12_381/utils.rs @@ -1,8 +1,10 @@ //! BLS12-381 utilities for padding and unpadding of input. -use crate::bls12_381_const::{ - FP_LENGTH, FP_PAD_BY, G1_LENGTH, PADDED_FP_LENGTH, PADDED_G1_LENGTH, PADDED_G2_LENGTH, +use crate::{ + bls12_381_const::{ + FP_LENGTH, FP_PAD_BY, G1_LENGTH, PADDED_FP_LENGTH, PADDED_G1_LENGTH, PADDED_G2_LENGTH, + }, + PrecompileError, }; -use crate::PrecompileError; /// Removes zeros with which the precompile inputs are left padded to 64 bytes. pub(super) fn remove_fp_padding(input: &[u8]) -> Result<&[u8; FP_LENGTH], PrecompileError> { diff --git a/crates/precompile/src/id.rs b/crates/precompile/src/id.rs index 8c4077fee1..7ca8d624f2 100644 --- a/crates/precompile/src/id.rs +++ b/crates/precompile/src/id.rs @@ -1,5 +1,4 @@ -use std::borrow::Cow; -use std::fmt; +use std::{borrow::Cow, fmt}; use crate::{Precompile, PrecompileSpecId}; diff --git a/crates/precompile/src/kzg_point_evaluation/arkworks.rs b/crates/precompile/src/kzg_point_evaluation/arkworks.rs index fa30382100..8fa328f51b 100644 --- a/crates/precompile/src/kzg_point_evaluation/arkworks.rs +++ b/crates/precompile/src/kzg_point_evaluation/arkworks.rs @@ -1,7 +1,8 @@ //! KZG point evaluation precompile using Arkworks BLS12-381 implementation. -use crate::bls12_381::arkworks::pairing_check; -use crate::bls12_381_const::TRUSTED_SETUP_TAU_G2_BYTES; -use crate::PrecompileError; +use crate::{ + bls12_381::arkworks::pairing_check, bls12_381_const::TRUSTED_SETUP_TAU_G2_BYTES, + PrecompileError, +}; use ark_bls12_381::{Fr, G1Affine, G2Affine}; use ark_ec::{AffineRepr, CurveGroup}; use ark_ff::{BigInteger, PrimeField}; diff --git a/crates/precompile/src/kzg_point_evaluation/blst.rs b/crates/precompile/src/kzg_point_evaluation/blst.rs index 57377f8907..b8feafae2c 100644 --- a/crates/precompile/src/kzg_point_evaluation/blst.rs +++ b/crates/precompile/src/kzg_point_evaluation/blst.rs @@ -1,10 +1,12 @@ //! KZG point evaluation precompile using BLST BLS12-381 implementation. -use crate::bls12_381::blst::{ - p1_add_or_double, p1_from_affine, p1_scalar_mul, p1_to_affine, p2_add_or_double, - p2_from_affine, p2_scalar_mul, p2_to_affine, pairing_check, +use crate::{ + bls12_381::blst::{ + p1_add_or_double, p1_from_affine, p1_scalar_mul, p1_to_affine, p2_add_or_double, + p2_from_affine, p2_scalar_mul, p2_to_affine, pairing_check, + }, + bls12_381_const::TRUSTED_SETUP_TAU_G2_BYTES, + PrecompileError, }; -use crate::bls12_381_const::TRUSTED_SETUP_TAU_G2_BYTES; -use crate::PrecompileError; use ::blst::{ blst_p1_affine, blst_p1_affine_in_g1, blst_p1_affine_on_curve, blst_p2_affine, blst_scalar, blst_scalar_fr_check, blst_scalar_from_bendian, diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index d1b027b2ad..5f1b2e112b 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -31,10 +31,10 @@ pub use once_lock::OnceLock; // Reexport alloy primitives. -pub use alloy_primitives::map::{self, hash_map, hash_set, HashMap, HashSet}; pub use alloy_primitives::{ - self, address, b256, bytes, fixed_bytes, hex, hex_literal, keccak256, ruint, uint, Address, - Bytes, FixedBytes, Log, LogData, TxKind, B256, I128, I256, U128, U256, + self, address, b256, bytes, fixed_bytes, hex, hex_literal, keccak256, + map::{self, hash_map, hash_set, HashMap, HashSet}, + ruint, uint, Address, Bytes, FixedBytes, Log, LogData, TxKind, B256, I128, I256, U128, U256, }; /// Type alias for EVM storage keys (256-bit unsigned integers). diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 759af925ae..befcc553f7 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -28,8 +28,10 @@ pub use state; // Export items. -pub use context::journal::{Journal, JournalEntry}; -pub use context::Context; +pub use context::{ + journal::{Journal, JournalEntry}, + Context, +}; pub use database_interface::{Database, DatabaseCommit, DatabaseRef}; pub use handler::{ ExecuteCommitEvm, ExecuteEvm, MainBuilder, MainContext, MainnetEvm, SystemCallCommitEvm, diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 47b6b90112..fd7c6fd590 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -12,8 +12,7 @@ pub use primitives; pub use types::{EvmState, EvmStorage, TransientStorage}; use bitflags::bitflags; -use primitives::hardfork::SpecId; -use primitives::{HashMap, StorageKey, StorageValue, U256}; +use primitives::{hardfork::SpecId, HashMap, StorageKey, StorageValue, U256}; /// Account type used inside Journal to track changed to state. #[derive(Debug, Clone, PartialEq, Eq, Default)] diff --git a/crates/statetest-types/src/test_authorization.rs b/crates/statetest-types/src/test_authorization.rs index c71977c1d1..10f1239608 100644 --- a/crates/statetest-types/src/test_authorization.rs +++ b/crates/statetest-types/src/test_authorization.rs @@ -1,6 +1,5 @@ use revm::context_interface::transaction::SignedAuthorization; -use serde::de::Error; -use serde::{Deserialize, Deserializer, Serialize}; +use serde::{de::Error, Deserialize, Deserializer, Serialize}; /// Struct for test authorization #[derive(Debug, Clone, PartialEq, Eq, Serialize)] diff --git a/examples/block_traces/src/main.rs b/examples/block_traces/src/main.rs index af1b3f95e9..ce5f83b221 100644 --- a/examples/block_traces/src/main.rs +++ b/examples/block_traces/src/main.rs @@ -15,13 +15,12 @@ use revm::{ primitives::{TxKind, U256}, Context, MainBuilder, MainContext, }; -use std::fs::create_dir_all; -use std::fs::OpenOptions; -use std::io::BufWriter; -use std::io::Write; -use std::sync::Arc; -use std::sync::Mutex; -use std::time::Instant; +use std::{ + fs::{create_dir_all, OpenOptions}, + io::{BufWriter, Write}, + sync::{Arc, Mutex}, + time::Instant, +}; struct FlushWriter { writer: Arc>>, diff --git a/examples/custom_precompile_journal/src/precompile_provider.rs b/examples/custom_precompile_journal/src/precompile_provider.rs index 8e2fd5f339..1ffef4454b 100644 --- a/examples/custom_precompile_journal/src/precompile_provider.rs +++ b/examples/custom_precompile_journal/src/precompile_provider.rs @@ -8,8 +8,7 @@ use revm::{ precompile::{PrecompileError, PrecompileOutput, PrecompileResult}, primitives::{address, hardfork::SpecId, Address, Bytes, Log, B256, U256}, }; -use std::boxed::Box; -use std::string::String; +use std::{boxed::Box, string::String}; // Define our custom precompile address pub const CUSTOM_PRECOMPILE_ADDRESS: Address = address!("0000000000000000000000000000000000000100"); From 7f5a6a0d913cdf19b5705b946c2c9129bd966473 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 20 Nov 2025 16:46:20 +0100 Subject: [PATCH 054/127] chore(op-test): regenerate missing test fixture (#3185) --- .../test_l1block_load_for_pre_regolith.json | 165 ++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json diff --git a/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json new file mode 100644 index 0000000000..5dcc6cd143 --- /dev/null +++ b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json @@ -0,0 +1,165 @@ +{ + "result": { + "Success": { + "gas_refunded": 0, + "gas_used": 21000, + "logs": [], + "output": { + "Call": "0x" + }, + "reason": "Stop" + } + }, + "state": { + "0x0000000000000000000000000000000000000000": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x0000000000000000000000000000000000100000": { + "info": { + "balance": "0x1", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x4200000000000000000000000000000000000019": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001a": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0x420000000000000000000000000000000000001b": { + "info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, + "status": "Touched | LoadedAsNotExisting", + "storage": {}, + "transaction_id": 0 + }, + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { + "info": { + "balance": "0x2386f26fc0ffff", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 + }, + "status": "Touched", + "storage": {}, + "transaction_id": 0 + } + } +} \ No newline at end of file From 7d6e773f07ffef9b8aaf7f48e5a80364f85933b4 Mon Sep 17 00:00:00 2001 From: Rej Ect <99460023+rejected-l@users.noreply.github.com> Date: Mon, 24 Nov 2025 10:38:53 +0100 Subject: [PATCH 055/127] ci: bump actions/checkout to v6 (#3189) --- .github/workflows/bench.yml | 2 +- .github/workflows/book.yml | 6 +++--- .github/workflows/ci.yml | 18 +++++++++--------- .github/workflows/ethereum-tests.yml | 2 +- .github/workflows/release-plz.yml | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 58ca23373b..a0bb0fc5e7 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -13,7 +13,7 @@ jobs: codspeed: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: submodules: true - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/book.yml b/.github/workflows/book.yml index 919f41802f..7d5ebc6cad 100644 --- a/.github/workflows/book.yml +++ b/.github/workflows/book.yml @@ -17,7 +17,7 @@ jobs: name: test steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install mdbook run: | @@ -42,7 +42,7 @@ jobs: name: lint steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Install mdbook-linkcheck run: | @@ -58,7 +58,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 with: fetch-depth: 0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80d3608311..bb348ab25f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: rust: ["1.88", "stable", "nightly"] flags: ["--no-default-features", "", "--all-features"] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} @@ -41,7 +41,7 @@ jobs: target: ["riscv32imac-unknown-none-elf", "riscv64imac-unknown-none-elf"] features: [""] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: targets: ${{ matrix.target }} @@ -59,7 +59,7 @@ jobs: matrix: features: ["", "serde", "std", "std,map-foldhash"] steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - run: cargo check --no-default-features -p revm --features=${{ matrix.features }} @@ -68,7 +68,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable - uses: taiki-e/install-action@cargo-hack - uses: Swatinem/rust-cache@v2 @@ -82,7 +82,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: components: clippy @@ -95,7 +95,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: components: rust-docs @@ -108,7 +108,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt @@ -118,7 +118,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: run zepter run: | cargo install zepter -f --locked @@ -129,5 +129,5 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - uses: crate-ci/typos@v1 diff --git a/.github/workflows/ethereum-tests.yml b/.github/workflows/ethereum-tests.yml index c8d6f99f27..862c4345ec 100644 --- a/.github/workflows/ethereum-tests.yml +++ b/.github/workflows/ethereum-tests.yml @@ -20,7 +20,7 @@ jobs: target: [i686-unknown-linux-gnu, x86_64-unknown-linux-gnu] steps: - name: Checkout sources - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Install toolchain uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index 8390d785d2..1de762c943 100644 --- a/.github/workflows/release-plz.yml +++ b/.github/workflows/release-plz.yml @@ -16,7 +16,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Install Rust toolchain From 111f6d3d25763ccd02998ebe1c6fae1765d8e63c Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 24 Nov 2025 12:01:47 +0100 Subject: [PATCH 056/127] chore: apply_auth_list helper fn (#3187) --- crates/handler/src/handler.rs | 8 +++++--- crates/handler/src/pre_execution.rs | 30 +++++++++++++++++++++++------ 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 253517cd95..9c862d9b4b 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -1,6 +1,8 @@ use crate::{ - evm::FrameTr, execution, post_execution, pre_execution, validation, EvmTr, FrameResult, - ItemOrResult, + evm::FrameTr, + execution, post_execution, + pre_execution::{self, apply_eip7702_auth_list}, + validation, EvmTr, FrameResult, ItemOrResult, }; use context::{ result::{ExecutionResult, FromStringError}, @@ -274,7 +276,7 @@ pub trait Handler { /// Returns the gas refund amount specified by EIP-7702. #[inline] fn apply_eip7702_auth_list(&self, evm: &mut Self::Evm) -> Result { - pre_execution::apply_eip7702_auth_list(evm.ctx()) + apply_eip7702_auth_list(evm.ctx_mut()) } /// Deducts maximum possible fee and transfer value from caller's balance. diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index cf1f27124b..6d916083a2 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -178,6 +178,11 @@ pub fn validate_against_state_and_deduct_caller< } /// Apply EIP-7702 auth list and return number gas refund on already created accounts. +/// +/// Note that this function will do nothing if the transaction type is not EIP-7702. +/// If you need to apply auth list for other transaction types, use [`apply_auth_list`] function. +/// +/// Internally uses [`apply_auth_list`] function. #[inline] pub fn apply_eip7702_auth_list< CTX: ContextTr, @@ -185,17 +190,30 @@ pub fn apply_eip7702_auth_list< >( context: &mut CTX, ) -> Result { - let tx = context.tx(); - // Return if there is no auth list. + let chain_id = context.cfg().chain_id(); + let (tx, journal) = context.tx_journal_mut(); + + // Return if not EIP-7702 transaction. if tx.tx_type() != TransactionType::Eip7702 { return Ok(0); } + apply_auth_list(chain_id, tx.authorization_list(), journal) +} - let chain_id = context.cfg().chain_id(); - let (tx, journal) = context.tx_journal_mut(); - +/// Apply EIP-7702 style auth list and return number gas refund on already created accounts. +/// +/// It is more granular function from [`apply_eip7702_auth_list`] function as it takes only the list, journal and chain id. +#[inline] +pub fn apply_auth_list< + JOURNAL: JournalTr, + ERROR: From + From<::Error>, +>( + chain_id: u64, + auth_list: impl Iterator, + journal: &mut JOURNAL, +) -> Result { let mut refunded_accounts = 0; - for authorization in tx.authorization_list() { + for authorization in auth_list { // 1. Verify the chain id is either 0 or the chain's current ID. let auth_chain_id = authorization.chain_id(); if !auth_chain_id.is_zero() && auth_chain_id != U256::from(chain_id) { From d4e56ec8e8b1200865218ab6d027fb6e8c9654d6 Mon Sep 17 00:00:00 2001 From: jakevin Date: Wed, 26 Nov 2025 18:35:46 +0800 Subject: [PATCH 057/127] refactor: optimize vector initialization with size hints in state and precompile modules (#3191) Co-authored-by: megakabi --- crates/database/src/states/state.rs | 8 +++++--- crates/precompile/src/bls12_381/blst.rs | 10 ++++++---- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index d3feb3b488..0b90b8a807 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -122,9 +122,11 @@ impl State { addresses: impl IntoIterator, ) -> Result, DB::Error> { // Make transition and update cache state - let mut transitions = Vec::new(); - let mut balances = Vec::new(); - for address in addresses { + let addresses_iter = addresses.into_iter(); + let (lower, _) = addresses_iter.size_hint(); + let mut transitions = Vec::with_capacity(lower); + let mut balances = Vec::with_capacity(lower); + for address in addresses_iter { let original_account = self.load_cache_account(address)?; let (balance, transition) = original_account.drain_balance(); balances.push(balance); diff --git a/crates/precompile/src/bls12_381/blst.rs b/crates/precompile/src/bls12_381/blst.rs index d20c7af561..6200382a25 100644 --- a/crates/precompile/src/bls12_381/blst.rs +++ b/crates/precompile/src/bls12_381/blst.rs @@ -681,8 +681,9 @@ pub(crate) fn map_fp2_to_g2_bytes( pub(crate) fn p1_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G1_LENGTH], crate::PrecompileError> { - let mut g1_points = Vec::new(); - let mut scalars = Vec::new(); + let (lower, _) = point_scalar_pairs.size_hint(); + let mut g1_points = Vec::with_capacity(lower); + let mut scalars = Vec::with_capacity(lower); // Parse all points and scalars for pair_result in point_scalar_pairs { @@ -718,8 +719,9 @@ pub(crate) fn p1_msm_bytes( pub(crate) fn p2_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G2_LENGTH], crate::PrecompileError> { - let mut g2_points = Vec::new(); - let mut scalars = Vec::new(); + let (lower, _) = point_scalar_pairs.size_hint(); + let mut g2_points = Vec::with_capacity(lower); + let mut scalars = Vec::with_capacity(lower); // Parse all points and scalars for pair_result in point_scalar_pairs { From 77abd37dbd1280a131626cea00b40056a9d39cc1 Mon Sep 17 00:00:00 2001 From: maradini77 <140460067+maradini77@users.noreply.github.com> Date: Wed, 26 Nov 2025 11:42:38 +0100 Subject: [PATCH 058/127] state: deduplicate local/global flags setup (#3190) --- crates/state/src/lib.rs | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index fd7c6fd590..57ecb38c13 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -160,10 +160,7 @@ impl Account { /// Returns true if it is created globally for first time. #[inline] pub fn mark_created_locally(&mut self) -> bool { - self.status |= AccountStatus::CreatedLocal; - let is_created_globaly = !self.status.contains(AccountStatus::Created); - self.status |= AccountStatus::Created; - is_created_globaly + self.mark_local_and_global(AccountStatus::CreatedLocal, AccountStatus::Created) } /// Unmark account as locally created @@ -175,10 +172,22 @@ impl Account { /// Mark account as locally and globally selfdestructed #[inline] pub fn mark_selfdestructed_locally(&mut self) -> bool { - self.status |= AccountStatus::SelfDestructedLocal; - let is_global_selfdestructed = !self.status.contains(AccountStatus::SelfDestructed); - self.status |= AccountStatus::SelfDestructed; - is_global_selfdestructed + self.mark_local_and_global( + AccountStatus::SelfDestructedLocal, + AccountStatus::SelfDestructed, + ) + } + + #[inline] + fn mark_local_and_global( + &mut self, + local_flag: AccountStatus, + global_flag: AccountStatus, + ) -> bool { + self.status |= local_flag; + let is_global_first_time = !self.status.contains(global_flag); + self.status |= global_flag; + is_global_first_time } /// Unmark account as locally selfdestructed From a26666c172a3c346befbc9fb90a1f7bec2dfdd56 Mon Sep 17 00:00:00 2001 From: jakevin Date: Tue, 2 Dec 2025 18:15:56 +0800 Subject: [PATCH 059/127] opt: optimize precompile `extend()` (#3192) - Eliminated the unnecessary Vec allocation (collect::>) - avoiding an extra clone() `p.clone()` - pre-allocation: Added reserve calls based on size_hint Co-authored-by: megakabi --- crates/precompile/src/lib.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index effce60ae3..80bc406c99 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -263,18 +263,20 @@ impl Precompiles { /// Other precompiles with overwrite existing precompiles. #[inline] pub fn extend(&mut self, other: impl IntoIterator) { - let items: Vec = other.into_iter().collect::>(); - for item in items.iter() { - if let Some(short_address) = short_address(item.address()) { - self.optimized_access[short_address] = Some(item.clone()); + let iter = other.into_iter(); + let (lower, _) = iter.size_hint(); + self.addresses.reserve(lower); + self.inner.reserve(lower); + for item in iter { + let address = *item.address(); + if let Some(short_idx) = short_address(&address) { + self.optimized_access[short_idx] = Some(item.clone()); } else { self.all_short_addresses = false; } + self.addresses.insert(address); + self.inner.insert(address, item); } - - self.addresses.extend(items.iter().map(|p| *p.address())); - self.inner - .extend(items.into_iter().map(|p| (*p.address(), p.clone()))); } /// Returns complement of `other` in `self`. From a157e6b1da1d40bb2d97f4529cc8b4677a63db9f Mon Sep 17 00:00:00 2001 From: maradini77 <140460067+maradini77@users.noreply.github.com> Date: Tue, 2 Dec 2025 11:20:24 +0100 Subject: [PATCH 060/127] chore(example): Remove duplicate traces directory creation in block_traces example (#3193) --- examples/block_traces/src/main.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/block_traces/src/main.rs b/examples/block_traces/src/main.rs index ce5f83b221..68940c9d2b 100644 --- a/examples/block_traces/src/main.rs +++ b/examples/block_traces/src/main.rs @@ -108,9 +108,6 @@ async fn main() -> anyhow::Result<()> { let console_bar = Arc::new(ProgressBar::new(txs as u64)); let start = Instant::now(); - // Create the traces directory if it doesn't exist - std::fs::create_dir_all("traces").expect("Failed to create traces directory"); - // Fill in CfgEnv let BlockTransactions::Full(transactions) = block.transactions else { panic!("Wrong transaction type") From a3f5fd1070dd914893d52ed411cd3f2cc5f2f720 Mon Sep 17 00:00:00 2001 From: Keemo Styler Date: Tue, 2 Dec 2025 18:18:22 +0700 Subject: [PATCH 061/127] refactor: optimize vector initialization using size hints (#3200) --- crates/handler/src/api.rs | 3 ++- crates/precompile/src/bls12_381/arkworks.rs | 10 ++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/crates/handler/src/api.rs b/crates/handler/src/api.rs index a2faacf186..f6428781e3 100644 --- a/crates/handler/src/api.rs +++ b/crates/handler/src/api.rs @@ -90,7 +90,8 @@ pub trait ExecuteEvm { &mut self, txs: impl Iterator, ) -> Result, TransactionIndexedError> { - let mut outputs = Vec::new(); + let (lower, _) = txs.size_hint(); + let mut outputs = Vec::with_capacity(lower); for (index, tx) in txs.enumerate() { outputs.push( self.transact_one(tx) diff --git a/crates/precompile/src/bls12_381/arkworks.rs b/crates/precompile/src/bls12_381/arkworks.rs index dea815f156..7995a705fb 100644 --- a/crates/precompile/src/bls12_381/arkworks.rs +++ b/crates/precompile/src/bls12_381/arkworks.rs @@ -460,8 +460,9 @@ pub(crate) fn map_fp2_to_g2_bytes( pub(crate) fn p1_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G1_LENGTH], PrecompileError> { - let mut g1_points = Vec::new(); - let mut scalars = Vec::new(); + let (lower, _) = point_scalar_pairs.size_hint(); + let mut g1_points = Vec::with_capacity(lower); + let mut scalars = Vec::with_capacity(lower); // Parse all points and scalars for pair_result in point_scalar_pairs { @@ -497,8 +498,9 @@ pub(crate) fn p1_msm_bytes( pub(crate) fn p2_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G2_LENGTH], PrecompileError> { - let mut g2_points = Vec::new(); - let mut scalars = Vec::new(); + let (lower, _) = point_scalar_pairs.size_hint(); + let mut g2_points = Vec::with_capacity(lower); + let mut scalars = Vec::with_capacity(lower); // Parse all points and scalars for pair_result in point_scalar_pairs { From 6cf44ef19bab043d82cc6a9866790ffa75e34614 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 3 Dec 2025 02:43:09 +0100 Subject: [PATCH 062/127] feat: Restrict Database::Error. JournaledAccountTr (#3199) * feat: Restrict Database::Error. JournaledAccountTr * nits * nits std --- Cargo.lock | 1 + Cargo.toml | 2 +- .../context/interface/src/journaled_state.rs | 35 +++-- .../interface/src/journaled_state/account.rs | 132 ++++++++++++++---- crates/context/interface/src/lib.rs | 1 + crates/context/src/journal.rs | 10 +- crates/context/src/journal/inner.rs | 2 +- crates/database/interface/Cargo.toml | 9 +- crates/database/interface/src/async_db.rs | 6 +- crates/database/interface/src/empty_db.rs | 8 +- crates/database/interface/src/erased_error.rs | 21 +++ crates/database/interface/src/lib.rs | 13 +- crates/database/src/states/state_builder.rs | 2 +- crates/handler/src/frame.rs | 4 +- crates/handler/src/post_execution.rs | 1 + crates/handler/src/pre_execution.rs | 14 +- crates/op-revm/src/handler.rs | 12 +- examples/cheatcode_inspector/src/main.rs | 14 +- .../database_components/src/block_hash.rs | 6 +- examples/database_components/src/lib.rs | 19 ++- examples/database_components/src/state.rs | 6 +- examples/erc20_gas/src/handler.rs | 6 +- 22 files changed, 236 insertions(+), 88 deletions(-) create mode 100644 crates/database/interface/src/erased_error.rs diff --git a/Cargo.lock b/Cargo.lock index 2bfea74c52..fa8cef2155 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3617,6 +3617,7 @@ dependencies = [ "revm-primitives", "revm-state", "serde", + "thiserror", "tokio", ] diff --git a/Cargo.toml b/Cargo.toml index e60b33f097..f724c01f4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -123,7 +123,7 @@ indicatif = "0.18" plain_hasher = "0.2" rstest = "0.26.0" serde_derive = "1.0" -thiserror = "2.0" +thiserror = { version = "2.0", default-features = false } triehash = "0.8" walkdir = "2.5" diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 8559699677..0883be6b4b 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -6,7 +6,7 @@ pub mod entry; use crate::{ context::{SStoreResult, SelfDestructResult}, host::LoadError, - journaled_state::{account::JournaledAccount, entry::JournalEntryTr}, + journaled_state::account::JournaledAccountTr, }; use core::ops::{Deref, DerefMut}; use database_interface::Database; @@ -22,8 +22,10 @@ pub trait JournalTr { type Database: Database; /// State type that is returned by the journal after finalization. type State; - /// Journal Entry type that is used in the journal. - type JournalEntry: JournalEntryTr; + /// Journal account allows modification of account with all needed changes. + type JournaledAccount<'a>: JournaledAccountTr + where + Self: 'a; /// Creates new Journaled state. /// @@ -186,10 +188,7 @@ pub trait JournalTr { fn load_account_mut( &mut self, address: Address, - ) -> Result< - StateLoad>, - ::Error, - > { + ) -> Result>, ::Error> { self.load_account_mut_optional_code(address, false) } @@ -198,10 +197,7 @@ pub trait JournalTr { fn load_account_with_code_mut( &mut self, address: Address, - ) -> Result< - StateLoad>, - ::Error, - > { + ) -> Result>, ::Error> { self.load_account_mut_optional_code(address, true) } @@ -210,10 +206,7 @@ pub trait JournalTr { &mut self, address: Address, load_code: bool, - ) -> Result< - StateLoad>, - ::Error, - >; + ) -> Result>, ::Error>; /// Sets bytecode with hash. Assume that account is warm. fn set_code_with_hash(&mut self, address: Address, code: Bytecode, hash: B256); @@ -352,6 +345,18 @@ impl JournalLoadError { JournalLoadError::ColdLoadSkipped => (LoadError::ColdLoadSkipped, None), } } + + /// Maps the database error to a new error. + #[inline] + pub fn map(self, f: F) -> JournalLoadError + where + F: FnOnce(E) -> B, + { + match self { + JournalLoadError::DBError(e) => JournalLoadError::DBError(f(e)), + JournalLoadError::ColdLoadSkipped => JournalLoadError::ColdLoadSkipped, + } + } } impl From for JournalLoadError { diff --git a/crates/context/interface/src/journaled_state/account.rs b/crates/context/interface/src/journaled_state/account.rs index 2e219d4938..363b1feb31 100644 --- a/crates/context/interface/src/journaled_state/account.rs +++ b/crates/context/interface/src/journaled_state/account.rs @@ -3,17 +3,100 @@ //! //! Useful to encapsulate account and journal entries together. So when account gets changed, we can add a journal entry for it. +use crate::journaled_state::entry::JournalEntry; + use super::entry::JournalEntryTr; -use core::ops::Deref; +use auto_impl::auto_impl; use primitives::{Address, B256, KECCAK_EMPTY, U256}; use state::{Account, Bytecode}; use std::vec::Vec; +/// Trait that contains database and journal of all changes that were made to the account. +#[auto_impl(&mut, Box)] +pub trait JournaledAccountTr { + /// Returns the account. + fn account(&self) -> &Account; + + /// Returns the balance of the account. + fn balance(&self) -> &U256; + + /// Returns the nonce of the account. + fn nonce(&self) -> u64; + + /// Returns the code hash of the account. + fn code_hash(&self) -> &B256; + + /// Returns the code of the account. + fn code(&self) -> Option<&Bytecode>; + + /// Touches the account. + fn touch(&mut self); + + /// Marks the account as cold without making a journal entry. + /// + /// Changing account without journal entry can be a footgun as reverting of the state change + /// would not happen without entry. It is the reason why this function has an `unsafe` prefix. + /// + /// If account is in access list, it would still be marked as warm if account get accessed again. + fn unsafe_mark_cold(&mut self); + + /// Sets the balance of the account. + /// + /// If balance is the same, we don't add a journal entry. + /// + /// Touches the account in all cases. + fn set_balance(&mut self, balance: U256); + + /// Increments the balance of the account. + /// + /// Touches the account in all cases. + fn incr_balance(&mut self, balance: U256) -> bool; + + /// Decrements the balance of the account. + /// + /// Touches the account in all cases. + fn decr_balance(&mut self, balance: U256) -> bool; + + /// Bumps the nonce of the account. + /// + /// Touches the account in all cases. + /// + /// Returns true if nonce was bumped, false if nonce is at the max value. + fn bump_nonce(&mut self) -> bool; + + /// Set the nonce of the account and create a journal entry. + /// + /// Touches the account in all cases. + fn set_nonce(&mut self, nonce: u64); + + /// Set the nonce of the account without creating a journal entry. + /// + /// Changing account without journal entry can be a footgun as reverting of the state change + /// would not happen without entry. It is the reason why this function has an `unsafe` prefix. + fn unsafe_set_nonce(&mut self, nonce: u64); + + /// Sets the code of the account. + /// + /// Touches the account in all cases. + fn set_code(&mut self, code_hash: B256, code: Bytecode); + + /// Sets the code of the account. Calculates hash of the code. + /// + /// Touches the account in all cases. + fn set_code_and_hash_slow(&mut self, code: Bytecode); + + /// Delegates the account to another address (EIP-7702). + /// + /// This touches the account, sets the code to the delegation designation, + /// and bumps the nonce. + fn delegate(&mut self, address: Address); +} + /// Journaled account contains both mutable account and journal entries. /// /// Useful to encapsulate account and journal entries together. So when account gets changed, we can add a journal entry for it. #[derive(Debug, PartialEq, Eq)] -pub struct JournaledAccount<'a, ENTRY: JournalEntryTr> { +pub struct JournaledAccount<'a, ENTRY: JournalEntryTr = JournalEntry> { /// Address of the account. address: Address, /// Mutable account. @@ -42,34 +125,41 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { journal_entries, } } +} + +impl<'a, ENTRY: JournalEntryTr> JournaledAccountTr for JournaledAccount<'a, ENTRY> { + /// Returns the account. + fn account(&self) -> &Account { + self.account + } /// Returns the balance of the account. #[inline] - pub fn balance(&self) -> &U256 { + fn balance(&self) -> &U256 { &self.account.info.balance } /// Returns the nonce of the account. #[inline] - pub fn nonce(&self) -> u64 { + fn nonce(&self) -> u64 { self.account.info.nonce } /// Returns the code hash of the account. #[inline] - pub fn code_hash(&self) -> &B256 { + fn code_hash(&self) -> &B256 { &self.account.info.code_hash } /// Returns the code of the account. #[inline] - pub fn code(&self) -> Option<&Bytecode> { + fn code(&self) -> Option<&Bytecode> { self.account.info.code.as_ref() } /// Touches the account. #[inline] - pub fn touch(&mut self) { + fn touch(&mut self) { if !self.account.status.is_touched() { self.account.mark_touch(); self.journal_entries @@ -84,7 +174,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// If account is in access list, it would still be marked as warm if account get accessed again. #[inline] - pub fn unsafe_mark_cold(&mut self) { + fn unsafe_mark_cold(&mut self) { self.account.mark_cold(); } @@ -94,7 +184,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Touches the account in all cases. #[inline] - pub fn set_balance(&mut self, balance: U256) { + fn set_balance(&mut self, balance: U256) { self.touch(); if self.account.info.balance != balance { self.journal_entries.push(ENTRY::balance_changed( @@ -109,7 +199,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Touches the account in all cases. #[inline] - pub fn incr_balance(&mut self, balance: U256) -> bool { + fn incr_balance(&mut self, balance: U256) -> bool { self.touch(); let Some(balance) = self.account.info.balance.checked_add(balance) else { return false; @@ -122,7 +212,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Touches the account in all cases. #[inline] - pub fn decr_balance(&mut self, balance: U256) -> bool { + fn decr_balance(&mut self, balance: U256) -> bool { self.touch(); let Some(balance) = self.account.info.balance.checked_sub(balance) else { return false; @@ -137,7 +227,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Returns true if nonce was bumped, false if nonce is at the max value. #[inline] - pub fn bump_nonce(&mut self) -> bool { + fn bump_nonce(&mut self) -> bool { self.touch(); let Some(nonce) = self.account.info.nonce.checked_add(1) else { return false; @@ -151,7 +241,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Touches the account in all cases. #[inline] - pub fn set_nonce(&mut self, nonce: u64) { + fn set_nonce(&mut self, nonce: u64) { self.touch(); let previous_nonce = self.account.info.nonce; self.account.info.set_nonce(nonce); @@ -164,7 +254,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// Changing account without journal entry can be a footgun as reverting of the state change /// would not happen without entry. It is the reason why this function has an `unsafe` prefix. #[inline] - pub fn unsafe_set_nonce(&mut self, nonce: u64) { + fn unsafe_set_nonce(&mut self, nonce: u64) { self.account.info.set_nonce(nonce); } @@ -172,7 +262,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Touches the account in all cases. #[inline] - pub fn set_code(&mut self, code_hash: B256, code: Bytecode) { + fn set_code(&mut self, code_hash: B256, code: Bytecode) { self.touch(); self.account.info.set_code_hash(code_hash); self.account.info.set_code(code); @@ -183,7 +273,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// /// Touches the account in all cases. #[inline] - pub fn set_code_and_hash_slow(&mut self, code: Bytecode) { + fn set_code_and_hash_slow(&mut self, code: Bytecode) { let code_hash = code.hash_slow(); self.set_code(code_hash, code); } @@ -193,7 +283,7 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { /// This touches the account, sets the code to the delegation designation, /// and bumps the nonce. #[inline] - pub fn delegate(&mut self, address: Address) { + fn delegate(&mut self, address: Address) { let (bytecode, hash) = if address.is_zero() { (Bytecode::default(), KECCAK_EMPTY) } else { @@ -206,11 +296,3 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { self.bump_nonce(); } } - -impl<'a, ENTRY: JournalEntryTr> Deref for JournaledAccount<'a, ENTRY> { - type Target = Account; - - fn deref(&self) -> &Self::Target { - self.account - } -} diff --git a/crates/context/interface/src/lib.rs b/crates/context/interface/src/lib.rs index 0e66071368..dcb65e731d 100644 --- a/crates/context/interface/src/lib.rs +++ b/crates/context/interface/src/lib.rs @@ -17,6 +17,7 @@ pub mod transaction; pub use block::Block; pub use cfg::{Cfg, CreateScheme, TransactTo}; pub use context::{ContextError, ContextSetters, ContextTr}; +pub use database_interface::erased_error::ErasedError; pub use database_interface::{DBErrorMarker, Database}; pub use either; pub use host::{DummyHost, Host}; diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index dd1a85b89c..f9bde2ca74 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -92,7 +92,10 @@ impl Journal { impl JournalTr for Journal { type Database = DB; type State = EvmState; - type JournalEntry = ENTRY; + type JournaledAccount<'a> + = JournaledAccount<'a, ENTRY> + where + Self: 'a; fn new(database: DB) -> Journal { Self { @@ -257,10 +260,7 @@ impl JournalTr for Journal { &mut self, address: Address, load_code: bool, - ) -> Result< - StateLoad>, - ::Error, - > { + ) -> Result>, DB::Error> { self.inner .load_account_mut_optional_code(&mut self.database, address, load_code, false) .map_err(JournalLoadError::unwrap_db_error) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a624a3e378..a2255c6193 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -4,7 +4,7 @@ use bytecode::Bytecode; use context_interface::{ context::{SStoreResult, SelfDestructResult, StateLoad}, journaled_state::{ - account::JournaledAccount, + account::{JournaledAccount, JournaledAccountTr}, entry::{JournalEntryTr, SelfdestructionRevertStatus}, AccountLoad, JournalCheckpoint, JournalLoadError, TransferError, }, diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index f553d82806..d668da62f5 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -25,6 +25,7 @@ primitives.workspace = true # misc auto_impl.workspace = true either.workspace = true +thiserror.workspace = true # Optional serde = { workspace = true, features = ["derive", "rc"], optional = true } @@ -36,6 +37,12 @@ tokio = { workspace = true, optional = true } [features] default = ["std"] -std = ["serde?/std", "primitives/std", "state/std", "either/std"] +std = [ + "serde?/std", + "primitives/std", + "state/std", + "either/std", + "thiserror/std", +] serde = ["dep:serde", "primitives/serde", "state/serde", "either/serde"] asyncdb = ["dep:tokio", "tokio/rt-multi-thread"] diff --git a/crates/database/interface/src/async_db.rs b/crates/database/interface/src/async_db.rs index 5e42d0c9c1..7ae1ecd5f9 100644 --- a/crates/database/interface/src/async_db.rs +++ b/crates/database/interface/src/async_db.rs @@ -1,6 +1,6 @@ //! Async database interface. use crate::{DBErrorMarker, Database, DatabaseRef}; -use core::{error::Error, future::Future}; +use core::future::Future; use primitives::{Address, StorageKey, StorageValue, B256}; use state::{AccountInfo, Bytecode}; use tokio::runtime::{Handle, Runtime}; @@ -12,7 +12,7 @@ use tokio::runtime::{Handle, Runtime}; /// Use [WrapDatabaseAsync] to provide [Database] implementation for a type that only implements this trait. pub trait DatabaseAsync { /// The database error type - type Error: Send + DBErrorMarker + Error; + type Error: DBErrorMarker; /// Gets basic account information. fn basic_async( @@ -47,7 +47,7 @@ pub trait DatabaseAsync { /// Use [WrapDatabaseAsync] to provide [DatabaseRef] implementation for a type that only implements this trait. pub trait DatabaseAsyncRef { /// The database error type - type Error: Send + DBErrorMarker + Error; + type Error: DBErrorMarker; /// Gets basic account information. fn basic_async_ref( diff --git a/crates/database/interface/src/empty_db.rs b/crates/database/interface/src/empty_db.rs index ab7264c2ad..8898e7a4ed 100644 --- a/crates/database/interface/src/empty_db.rs +++ b/crates/database/interface/src/empty_db.rs @@ -1,6 +1,6 @@ //! Empty database implementation. use crate::{DBErrorMarker, Database, DatabaseRef}; -use core::{convert::Infallible, error::Error, fmt, marker::PhantomData}; +use core::{convert::Infallible, fmt, marker::PhantomData}; use primitives::{keccak256, Address, StorageKey, StorageValue, B256}; use state::{AccountInfo, Bytecode}; use std::string::ToString; @@ -54,7 +54,7 @@ impl EmptyDBTyped { } } -impl Database for EmptyDBTyped { +impl Database for EmptyDBTyped { type Error = E; #[inline] @@ -82,7 +82,9 @@ impl Database for EmptyDBTyped { } } -impl DatabaseRef for EmptyDBTyped { +impl DatabaseRef + for EmptyDBTyped +{ type Error = E; #[inline] diff --git a/crates/database/interface/src/erased_error.rs b/crates/database/interface/src/erased_error.rs new file mode 100644 index 0000000000..b5f6cf4cbd --- /dev/null +++ b/crates/database/interface/src/erased_error.rs @@ -0,0 +1,21 @@ +//! Erased error type. + +use std::boxed::Box; + +/// Erased error type. +#[derive(thiserror::Error, Debug)] +#[error(transparent)] +pub struct ErasedError(Box); + +impl ErasedError { + /// Creates a new erased error. + pub fn new(error: impl core::error::Error + Send + Sync + 'static) -> Self { + Self(Box::new(error)) + } + + /// Consumes the erased error and returns the inner error. + #[inline] + pub fn into_inner(self) -> Box { + self.0 + } +} diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index 76e816b3e2..3f8164e111 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -8,10 +8,8 @@ extern crate alloc as std; use core::convert::Infallible; use auto_impl::auto_impl; -use core::error::Error; use primitives::{address, Address, HashMap, StorageKey, StorageValue, B256, U256}; use state::{Account, AccountInfo, Bytecode}; -use std::string::String; /// Address with all `0xff..ff` in it. Used for testing. pub const FFADDRESS: Address = address!("0xffffffffffffffffffffffffffffffffffffffff"); @@ -32,26 +30,27 @@ pub const BENCH_CALLER_BALANCE: U256 = TEST_BALANCE; pub mod async_db; pub mod either; pub mod empty_db; +pub mod erased_error; pub mod try_commit; #[cfg(feature = "asyncdb")] pub use async_db::{DatabaseAsync, WrapDatabaseAsync}; pub use empty_db::{EmptyDB, EmptyDBTyped}; +pub use erased_error::ErasedError; pub use try_commit::{ArcUpgradeError, TryDatabaseCommit}; /// Database error marker is needed to implement From conversion for Error type. -pub trait DBErrorMarker {} +pub trait DBErrorMarker: core::error::Error + Send + Sync + 'static {} /// Implement marker for `()`. -impl DBErrorMarker for () {} impl DBErrorMarker for Infallible {} -impl DBErrorMarker for String {} +impl DBErrorMarker for ErasedError {} /// EVM database interface. #[auto_impl(&mut, Box)] pub trait Database { /// The database error type. - type Error: DBErrorMarker + Error; + type Error: DBErrorMarker; /// Gets basic account information. fn basic(&mut self, address: Address) -> Result, Self::Error>; @@ -83,7 +82,7 @@ pub trait DatabaseCommit { #[auto_impl(&, &mut, Box, Rc, Arc)] pub trait DatabaseRef { /// The database error type. - type Error: DBErrorMarker + Error; + type Error: DBErrorMarker; /// Gets basic account information. fn basic_ref(&self, address: Address) -> Result, Self::Error>; diff --git a/crates/database/src/states/state_builder.rs b/crates/database/src/states/state_builder.rs index c2047d490c..1b42990483 100644 --- a/crates/database/src/states/state_builder.rs +++ b/crates/database/src/states/state_builder.rs @@ -85,7 +85,7 @@ impl StateBuilder { } /// With boxed version of database. - pub fn with_database_boxed( + pub fn with_database_boxed( self, database: DBBox<'_, Error>, ) -> StateBuilder> { diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index aeecddd1a3..50c2c59533 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -2,7 +2,7 @@ use crate::{ evm::FrameTr, item_or_result::FrameInitOrResult, precompile_provider::PrecompileProvider, CallFrame, CreateFrame, FrameData, FrameResult, ItemOrResult, }; -use context::result::FromStringError; +use context::{journaled_state::account::JournaledAccountTr, result::FromStringError}; use context_interface::{ context::ContextError, journaled_state::{JournalCheckpoint, JournalTr}, @@ -301,6 +301,8 @@ impl EthFrame { CreateScheme::Custom { address } => address, }; + drop(caller_info); // Drop caller info to avoid borrow checker issues. + // warm load account. context.journal_mut().load_account(created_address)?; diff --git a/crates/handler/src/post_execution.rs b/crates/handler/src/post_execution.rs index bd0471d717..b5a8bef35d 100644 --- a/crates/handler/src/post_execution.rs +++ b/crates/handler/src/post_execution.rs @@ -1,4 +1,5 @@ use crate::FrameResult; +use context::journaled_state::account::JournaledAccountTr; use context_interface::{ journaled_state::JournalTr, result::{ExecutionResult, HaltReason, HaltReasonTr}, diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 6d916083a2..1112f81eb4 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -4,6 +4,7 @@ use crate::{EvmTr, PrecompileProvider}; use bytecode::Bytecode; +use context::journaled_state::account::JournaledAccountTr; use context_interface::{ journaled_state::JournalTr, result::InvalidTransaction, @@ -166,7 +167,7 @@ pub fn validate_against_state_and_deduct_caller< // Load caller's account. let mut caller = journal.load_account_with_code_mut(tx.caller())?.data; - validate_account_nonce_and_code_with_components(&caller.info, tx, cfg)?; + validate_account_nonce_and_code_with_components(&caller.account().info, tx, cfg)?; let new_balance = calculate_caller_fee(*caller.balance(), tx, block, cfg)?; @@ -234,9 +235,10 @@ pub fn apply_auth_list< // warm authority account and check nonce. // 4. Add `authority` to `accessed_addresses` (as defined in [EIP-2929](./eip-2929.md).) let mut authority_acc = journal.load_account_with_code_mut(authority)?; + let authority_acc_info = &authority_acc.account().info; // 5. Verify the code of `authority` is either empty or already delegated. - if let Some(bytecode) = &authority_acc.info.code { + if let Some(bytecode) = &authority_acc_info.code { // if it is not empty and it is not eip7702 if !bytecode.is_empty() && !bytecode.is_eip7702() { continue; @@ -244,12 +246,16 @@ pub fn apply_auth_list< } // 6. Verify the nonce of `authority` is equal to `nonce`. In case `authority` does not exist in the trie, verify that `nonce` is equal to `0`. - if authorization.nonce() != authority_acc.info.nonce { + if authorization.nonce() != authority_acc_info.nonce { continue; } // 7. Add `PER_EMPTY_ACCOUNT_COST - PER_AUTH_BASE_COST` gas to the global refund counter if `authority` exists in the trie. - if !(authority_acc.is_empty() && authority_acc.is_loaded_as_not_existing_not_touched()) { + if !(authority_acc_info.is_empty() + && authority_acc + .account() + .is_loaded_as_not_existing_not_touched()) + { refunded_accounts += 1; } diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index f444e6f420..ca86a3b72e 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -6,7 +6,11 @@ use crate::{ L1BlockInfo, OpHaltReason, OpSpecId, }; use revm::{ - context::{journaled_state::JournalCheckpoint, result::InvalidTransaction, LocalContextTr}, + context::{ + journaled_state::{account::JournaledAccountTr, JournalCheckpoint}, + result::InvalidTransaction, + LocalContextTr, + }, context_interface::{ context::ContextError, result::{EVMError, ExecutionResult, FromStringError}, @@ -146,10 +150,10 @@ where let mut caller_account = journal.load_account_with_code_mut(tx.caller())?.data; // validates account nonce and code - validate_account_nonce_and_code_with_components(&caller_account.info, tx, cfg)?; + validate_account_nonce_and_code_with_components(&caller_account.account().info, tx, cfg)?; // check additional cost and deduct it from the caller's balances - let mut balance = caller_account.info.balance; + let mut balance = caller_account.account().info.balance; if !cfg.is_fee_charge_disabled() { let Some(additional_cost) = chain.tx_cost_with_tx(tx, spec) else { @@ -404,6 +408,8 @@ where acc.bump_nonce(); acc.incr_balance(U256::from(mint.unwrap_or_default())); + drop(acc); // Drop acc to avoid borrow checker issues. + // We can now commit the changes. journal.commit_tx(); diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index a40b0c5ca3..7142ea03f4 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -8,7 +8,7 @@ use revm::{ context::{ - journaled_state::{AccountInfoLoad, JournalLoadError}, + journaled_state::{account::JournaledAccount, AccountInfoLoad, JournalLoadError}, result::InvalidTransaction, BlockEnv, Cfg, CfgEnv, ContextTr, Evm, LocalContext, TxEnv, }, @@ -60,7 +60,10 @@ impl Backend { impl JournalTr for Backend { type Database = InMemoryDB; type State = EvmState; - type JournalEntry = JournalEntry; + type JournaledAccount<'a> + = JournaledAccount<'a> + where + Self: 'a; fn new(database: InMemoryDB) -> Self { Self::new(SpecId::default(), database) @@ -306,12 +309,7 @@ impl JournalTr for Backend { &mut self, address: Address, load_code: bool, - ) -> Result< - StateLoad< - revm::context::journaled_state::account::JournaledAccount<'_, Self::JournalEntry>, - >, - ::Error, - > { + ) -> Result>, ::Error> { self.journaled_state .load_account_mut_optional_code(address, load_code) } diff --git a/examples/database_components/src/block_hash.rs b/examples/database_components/src/block_hash.rs index 449929d204..fe7d7213b5 100644 --- a/examples/database_components/src/block_hash.rs +++ b/examples/database_components/src/block_hash.rs @@ -1,7 +1,7 @@ //! BlockHash database component from [`revm::Database`] use auto_impl::auto_impl; -use core::{error::Error as StdError, ops::Deref}; +use core::ops::Deref; use revm::primitives::B256; use std::sync::Arc; @@ -11,7 +11,7 @@ use std::sync::Arc; #[auto_impl(&mut, Box)] pub trait BlockHash { /// Error type for block hash operations - type Error: StdError; + type Error: core::error::Error + Send + Sync + 'static; /// Gets block hash by block number. fn block_hash(&mut self, number: u64) -> Result; @@ -23,7 +23,7 @@ pub trait BlockHash { #[auto_impl(&, &mut, Box, Rc, Arc)] pub trait BlockHashRef { /// Error type for block hash operations - type Error: StdError; + type Error: core::error::Error + Send + Sync + 'static; /// Gets block hash by block number. fn block_hash(&self, number: u64) -> Result; diff --git a/examples/database_components/src/lib.rs b/examples/database_components/src/lib.rs index c683d19f0e..276bc32587 100644 --- a/examples/database_components/src/lib.rs +++ b/examples/database_components/src/lib.rs @@ -28,7 +28,10 @@ pub struct DatabaseComponents { /// Error type for database component operations. /// Wraps errors from both state and block hash components. #[derive(Debug, thiserror::Error)] -pub enum DatabaseComponentError { +pub enum DatabaseComponentError< + SE: core::error::Error + Send + Sync + 'static, + BHE: core::error::Error + Send + Sync + 'static, +> { /// Error from state component operations #[error(transparent)] State(SE), @@ -37,7 +40,19 @@ pub enum DatabaseComponentError { BlockHash(BHE), } -impl DBErrorMarker for DatabaseComponentError {} +impl< + SE: core::error::Error + Send + Sync + 'static, + BHE: core::error::Error + Send + Sync + 'static, + > DBErrorMarker for DatabaseComponentError +{ +} + +unsafe impl< + SE: core::error::Error + Send + Sync + 'static, + BHE: core::error::Error + Send + Sync + 'static, + > Send for DatabaseComponentError +{ +} impl Database for DatabaseComponents { type Error = DatabaseComponentError; diff --git a/examples/database_components/src/state.rs b/examples/database_components/src/state.rs index 35f8d40ed8..b9dd75f636 100644 --- a/examples/database_components/src/state.rs +++ b/examples/database_components/src/state.rs @@ -6,7 +6,7 @@ use revm::{ primitives::{Address, StorageKey, StorageValue, B256}, state::{AccountInfo, Bytecode}, }; -use std::{error::Error as StdError, sync::Arc}; +use std::sync::Arc; /// Trait for mutable access to state data including accounts, code, and storage. /// This is typically used for database implementations that may modify state @@ -14,7 +14,7 @@ use std::{error::Error as StdError, sync::Arc}; #[auto_impl(&mut, Box)] pub trait State { /// Error type for state operations - type Error: StdError; + type Error: core::error::Error + Send + Sync + 'static; /// Gets basic account information. fn basic(&mut self, address: Address) -> Result, Self::Error>; @@ -33,7 +33,7 @@ pub trait State { #[auto_impl(&, &mut, Box, Rc, Arc)] pub trait StateRef { /// Error type for state operations - type Error: StdError; + type Error: core::error::Error + Send + Sync + 'static; /// Gets basic account information. fn basic(&self, address: Address) -> Result, Self::Error>; diff --git a/examples/erc20_gas/src/handler.rs b/examples/erc20_gas/src/handler.rs index b1ff47d890..29b673aad4 100644 --- a/examples/erc20_gas/src/handler.rs +++ b/examples/erc20_gas/src/handler.rs @@ -1,5 +1,5 @@ use revm::{ - context::Cfg, + context::{journaled_state::account::JournaledAccountTr, Cfg}, context_interface::{result::HaltReason, Block, ContextTr, JournalTr, Transaction}, handler::{ pre_execution::{calculate_caller_fee, validate_account_nonce_and_code_with_components}, @@ -54,7 +54,7 @@ where // Load caller's account. let mut caller_account = journal.load_account_with_code_mut(tx.caller())?; - validate_account_nonce_and_code_with_components(&caller_account.info, tx, cfg)?; + validate_account_nonce_and_code_with_components(&caller_account.account().info, tx, cfg)?; // make changes to the account. Account balance stays the same caller_account.touch(); @@ -64,6 +64,8 @@ where let account_balance_slot = erc_address_storage(tx.caller()); + drop(caller_account); // Drop caller_account to avoid borrow checker issues. + // load account balance let account_balance = journal.sload(TOKEN, account_balance_slot)?.data; From d013bc281ef4fbbd9c16668c131d58cda7de58e8 Mon Sep 17 00:00:00 2001 From: jakevin Date: Wed, 3 Dec 2025 17:31:51 +0800 Subject: [PATCH 063/127] refactor: replace HashMap with fixed-size array for opcode counts in CountInspector (#3203) Co-authored-by: megakabi --- crates/inspector/src/count_inspector.rs | 46 ++++++++++++++++++------- 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/crates/inspector/src/count_inspector.rs b/crates/inspector/src/count_inspector.rs index 7e3612fc1f..2068cbc285 100644 --- a/crates/inspector/src/count_inspector.rs +++ b/crates/inspector/src/count_inspector.rs @@ -1,13 +1,13 @@ //! CountInspector - Inspector that counts all opcodes that were called. use crate::inspector::Inspector; use interpreter::{interpreter_types::Jumps, InterpreterTypes}; -use primitives::{HashMap, Log}; +use primitives::Log; /// Inspector that counts all opcodes that were called during execution. -#[derive(Clone, Debug, Default)] +#[derive(Clone, Debug)] pub struct CountInspector { - /// Map from opcode value to count of times it was executed. - opcode_counts: HashMap, + /// Fixed array keyed by opcode value to count executions. + opcode_counts: [u64; 256], /// Count of initialize_interp calls. initialize_interp_count: u64, /// Count of step calls. @@ -28,6 +28,23 @@ pub struct CountInspector { selfdestruct_count: u64, } +impl Default for CountInspector { + fn default() -> Self { + Self { + opcode_counts: [0; 256], + initialize_interp_count: 0, + step_count: 0, + step_end_count: 0, + log_count: 0, + call_count: 0, + call_end_count: 0, + create_count: 0, + create_end_count: 0, + selfdestruct_count: 0, + } + } +} + impl CountInspector { /// Create a new CountInspector. pub fn new() -> Self { @@ -36,27 +53,30 @@ impl CountInspector { /// Get the count for a specific opcode. pub fn get_count(&self, opcode: u8) -> u64 { - self.opcode_counts.get(&opcode).copied().unwrap_or_default() + self.opcode_counts[opcode as usize] } /// Get a reference to all opcode counts. - pub fn opcode_counts(&self) -> &HashMap { + pub fn opcode_counts(&self) -> &[u64; 256] { &self.opcode_counts } /// Get the total number of opcodes executed. pub fn total_opcodes(&self) -> u64 { - self.opcode_counts.values().sum() + self.opcode_counts.iter().copied().sum() } /// Get the number of unique opcodes executed. pub fn unique_opcodes(&self) -> usize { - self.opcode_counts.len() + self.opcode_counts + .iter() + .filter(|&&count| count > 0) + .count() } /// Clear all counts. pub fn clear(&mut self) { - self.opcode_counts.clear(); + self.opcode_counts = [0; 256]; self.initialize_interp_count = 0; self.step_count = 0; self.step_end_count = 0; @@ -126,7 +146,7 @@ impl Inspector for CountInspector { fn step(&mut self, interp: &mut interpreter::Interpreter, _context: &mut CTX) { self.step_count += 1; let opcode = interp.bytecode.opcode(); - *self.opcode_counts.entry(opcode).or_insert(0) += 1; + self.opcode_counts[opcode as usize] += 1; } fn step_end(&mut self, _interp: &mut interpreter::Interpreter, _context: &mut CTX) { @@ -253,8 +273,8 @@ mod tests { let mut inspector = CountInspector::new(); // Add some counts manually for testing - *inspector.opcode_counts.entry(opcode::PUSH1).or_insert(0) += 5; - *inspector.opcode_counts.entry(opcode::ADD).or_insert(0) += 3; + inspector.opcode_counts[opcode::PUSH1 as usize] += 5; + inspector.opcode_counts[opcode::ADD as usize] += 3; inspector.initialize_interp_count = 2; inspector.step_count = 10; inspector.step_end_count = 10; @@ -274,7 +294,6 @@ mod tests { inspector.clear(); assert_eq!(inspector.total_opcodes(), 0); assert_eq!(inspector.unique_opcodes(), 0); - assert!(inspector.opcode_counts().is_empty()); assert_eq!(inspector.initialize_interp_count(), 0); assert_eq!(inspector.step_count(), 0); assert_eq!(inspector.step_end_count(), 0); @@ -284,6 +303,7 @@ mod tests { assert_eq!(inspector.create_count(), 0); assert_eq!(inspector.create_end_count(), 0); assert_eq!(inspector.selfdestruct_count(), 0); + assert!(inspector.opcode_counts().iter().all(|&count| count == 0)); } #[test] From 049da177f341fc840c5aa056cb4daf45ba69beea Mon Sep 17 00:00:00 2001 From: Eric Woolsey Date: Wed, 3 Dec 2025 01:43:21 -0800 Subject: [PATCH 064/127] feat: DatabaseCommit::commit_iter (#3197) * feat: DatabaseCommit::commit_iter * feat: DatabaseCommit::commit_iter for State * revert: return Iterator for apply_evm_state * Apply suggestion from @rakita --------- Co-authored-by: rakita --- crates/database/interface/src/lib.rs | 10 +++++++++ crates/database/src/states/cache.rs | 22 +++++++++++-------- crates/database/src/states/state.rs | 20 +++++++++++++---- .../database/src/states/transition_state.rs | 6 +++-- 4 files changed, 43 insertions(+), 15 deletions(-) diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index 3f8164e111..8bce4c4296 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -71,6 +71,16 @@ pub trait Database { pub trait DatabaseCommit { /// Commit changes to the database. fn commit(&mut self, changes: HashMap); + + /// Commit changes to the database with an iterator. + /// + /// Implementors of [`DatabaseCommit`] should override this method when possible for efficiency. + /// + /// Callers should prefer using [`DatabaseCommit::commit`] when they already have a [`HashMap`]. + fn commit_iter(&mut self, changes: impl IntoIterator) { + let changes: HashMap = changes.into_iter().collect(); + self.commit(changes); + } } /// EVM database interface. diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index 7a345cc3bc..2d786dd893 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -3,7 +3,7 @@ use super::{ }; use bytecode::Bytecode; use primitives::{Address, HashMap, B256}; -use state::{Account, AccountInfo, EvmState}; +use state::{Account, AccountInfo}; use std::vec::Vec; /// Cache state contains both modified and original values @@ -89,14 +89,18 @@ impl CacheState { } /// Applies output of revm execution and create account transitions that are used to build BundleState. - pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> { - let mut transitions = Vec::with_capacity(evm_state.len()); - for (address, account) in evm_state { - if let Some(transition) = self.apply_account_state(address, account) { - transitions.push((address, transition)); - } - } - transitions + #[inline] + pub fn apply_evm_state( + &mut self, + evm_state: impl IntoIterator, + ) -> Vec<(Address, TransitionAccount)> { + evm_state + .into_iter() + .filter_map(|(address, account)| { + self.apply_account_state(address, account) + .map(|transition| (address, transition)) + }) + .collect() } /// Pretty print the cache state for debugging purposes. diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 0b90b8a807..7f4d68196a 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -166,7 +166,10 @@ impl State { } /// Applies evm transitions to transition state. - pub fn apply_transition(&mut self, transitions: Vec<(Address, TransitionAccount)>) { + pub fn apply_transition( + &mut self, + transitions: impl IntoIterator, + ) { // Add transition to transition state. if let Some(s) = self.transition_state.as_mut() { s.add_transitions(transitions) @@ -315,9 +318,18 @@ impl Database for State { } impl DatabaseCommit for State { - fn commit(&mut self, evm_state: HashMap) { - let transitions = self.cache.apply_evm_state(evm_state); - self.apply_transition(transitions); + fn commit(&mut self, changes: HashMap) { + let transitions = self.cache.apply_evm_state(changes); + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } + } + + fn commit_iter(&mut self, changes: impl IntoIterator) { + let transitions = self.cache.apply_evm_state(changes); + if let Some(s) = self.transition_state.as_mut() { + s.add_transitions(transitions) + } } } diff --git a/crates/database/src/states/transition_state.rs b/crates/database/src/states/transition_state.rs index a021f34534..78fdd40e73 100644 --- a/crates/database/src/states/transition_state.rs +++ b/crates/database/src/states/transition_state.rs @@ -1,6 +1,5 @@ use super::TransitionAccount; use primitives::{hash_map::Entry, Address, HashMap}; -use std::vec::Vec; /// State of accounts in transition between transaction executions. #[derive(Clone, Default, Debug, PartialEq, Eq)] @@ -29,7 +28,10 @@ impl TransitionState { /// /// This will insert new [`TransitionAccount`]s, or update existing ones via /// [`update`][TransitionAccount::update]. - pub fn add_transitions(&mut self, transitions: Vec<(Address, TransitionAccount)>) { + pub fn add_transitions( + &mut self, + transitions: impl IntoIterator, + ) { for (address, account) in transitions { match self.transitions.entry(address) { Entry::Occupied(entry) => { From 1cc86f711da997c8baa589002c7f4691c3131578 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 3 Dec 2025 16:43:50 +0100 Subject: [PATCH 065/127] fix: set transaction_id on new account (#3204) --- crates/context/src/journal/inner.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a2255c6193..36d1beb8db 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -704,8 +704,11 @@ impl JournalInner { if is_cold && skip_cold_load { return Err(JournalLoadError::ColdLoadSkipped); } + let account = if let Some(account) = db.basic(address)? { - account.into() + let mut account: Account = account.into(); + account.transaction_id = self.transaction_id; + account } else { Account::new_not_existing(self.transaction_id) }; From eb37a156898f27de6cf683f94766a05aeaa9379e Mon Sep 17 00:00:00 2001 From: Eric Woolsey Date: Wed, 3 Dec 2025 14:51:06 -0800 Subject: [PATCH 066/127] feat: DatabaseCommitExt + increment_balances (#3195) * feat: DatabaseCommitExt + increment_balances * fix: HashMap::with_capacity breaks features, use reserve instead * fix: remove check for if balance == 0 in increment_balances --- .../src/cmd/blockchaintest/post_block.rs | 2 +- crates/database/interface/src/lib.rs | 34 +++++++++++++++++++ crates/database/src/states/state.rs | 33 ------------------ 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest/post_block.rs b/bins/revme/src/cmd/blockchaintest/post_block.rs index f768e389e1..62617acc05 100644 --- a/bins/revme/src/cmd/blockchaintest/post_block.rs +++ b/bins/revme/src/cmd/blockchaintest/post_block.rs @@ -1,6 +1,6 @@ use revm::{ context::{Block, ContextTr}, - database::State, + database::{DatabaseCommitExt as _, State}, handler::EvmTr, primitives::{hardfork::SpecId, ONE_ETHER, ONE_GWEI}, Database, SystemCallCommitEvm, diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index 8bce4c4296..a3b42ae86f 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -181,3 +181,37 @@ impl DatabaseRef for WrapDatabaseRef { self.0.block_hash_ref(number) } } + +impl DatabaseCommitExt for T { + // default implementation +} + +/// EVM database commit interface. +pub trait DatabaseCommitExt: Database + DatabaseCommit { + /// Iterates over received balances and increment all account balances. + /// + /// Update will create transitions for all accounts that are updated. + fn increment_balances( + &mut self, + balances: impl IntoIterator, + ) -> Result<(), Self::Error> { + // Make transition and update cache state + let balances = balances.into_iter(); + let mut transitions: HashMap = HashMap::default(); + transitions.reserve(balances.size_hint().0); + for (address, balance) in balances { + let mut original_account = match self.basic(address)? { + Some(acc_info) => Account::from(acc_info), + None => Account::new_not_existing(0), + }; + original_account.info.balance = original_account + .info + .balance + .saturating_add(U256::from(balance)); + original_account.mark_touch(); + transitions.insert(address, original_account); + } + self.commit(transitions); + Ok(()) + } +} diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 7f4d68196a..fa15339253 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -81,39 +81,6 @@ impl State { self.bundle_state.size_hint() } - /// Iterates over received balances and increment all account balances. - /// - /// **Note**: If account is not found inside cache state it will be loaded from database. - /// - /// Update will create transitions for all accounts that are updated. - /// - /// If using this to implement withdrawals, zero balances must be filtered out before calling this function. - pub fn increment_balances( - &mut self, - balances: impl IntoIterator, - ) -> Result<(), DB::Error> { - // Make transition and update cache state - let balances = balances.into_iter(); - let mut transitions = Vec::with_capacity(balances.size_hint().0); - for (address, balance) in balances { - if balance == 0 { - continue; - } - let original_account = self.load_cache_account(address)?; - transitions.push(( - address, - original_account - .increment_balance(balance) - .expect("Balance is not zero"), - )) - } - // Append transition - if let Some(s) = self.transition_state.as_mut() { - s.add_transitions(transitions) - } - Ok(()) - } - /// Drains balances from given account and return those values. /// /// It is used for DAO hardfork state change to move values from given accounts. From 17011ca58f2dc1e082cb288fb55e78590ba20d57 Mon Sep 17 00:00:00 2001 From: Eric Woolsey Date: Mon, 8 Dec 2025 02:33:12 -0800 Subject: [PATCH 067/127] feat: DatabaseCommitExt::drain_balances (#3205) * feat: DatabaseCommitExt::drain_balances * fix: use std::vec::Vec * Apply suggestion from @rakita --- crates/database/interface/src/lib.rs | 63 +++++++++++++++++++++------- crates/database/src/states/state.rs | 26 ------------ 2 files changed, 47 insertions(+), 42 deletions(-) diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index a3b42ae86f..29d76df3eb 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -10,6 +10,7 @@ use core::convert::Infallible; use auto_impl::auto_impl; use primitives::{address, Address, HashMap, StorageKey, StorageValue, B256, U256}; use state::{Account, AccountInfo, Bytecode}; +use std::vec::Vec; /// Address with all `0xff..ff` in it. Used for testing. pub const FFADDRESS: Address = address!("0xffffffffffffffffffffffffffffffffffffffff"); @@ -196,22 +197,52 @@ pub trait DatabaseCommitExt: Database + DatabaseCommit { balances: impl IntoIterator, ) -> Result<(), Self::Error> { // Make transition and update cache state - let balances = balances.into_iter(); - let mut transitions: HashMap = HashMap::default(); - transitions.reserve(balances.size_hint().0); - for (address, balance) in balances { - let mut original_account = match self.basic(address)? { - Some(acc_info) => Account::from(acc_info), - None => Account::new_not_existing(0), - }; - original_account.info.balance = original_account - .info - .balance - .saturating_add(U256::from(balance)); - original_account.mark_touch(); - transitions.insert(address, original_account); - } - self.commit(transitions); + let transitions = balances + .into_iter() + .map(|(address, balance)| { + let mut original_account = match self.basic(address)? { + Some(acc_info) => Account::from(acc_info), + None => Account::new_not_existing(0), + }; + original_account.info.balance = original_account + .info + .balance + .saturating_add(U256::from(balance)); + original_account.mark_touch(); + Ok((address, original_account)) + }) + // Unfortunately must collect here to short circuit on error + .collect::, _>>()?; + + self.commit_iter(transitions); Ok(()) } + + /// Drains balances from given account and return those values. + /// + /// It is used for DAO hardfork state change to move values from given accounts. + fn drain_balances( + &mut self, + addresses: impl IntoIterator, + ) -> Result, Self::Error> { + // Make transition and update cache state + let addresses_iter = addresses.into_iter(); + let (lower, _) = addresses_iter.size_hint(); + let mut transitions = Vec::with_capacity(lower); + let balances = addresses_iter + .map(|address| { + let mut original_account = match self.basic(address)? { + Some(acc_info) => Account::from(acc_info), + None => Account::new_not_existing(0), + }; + let balance = core::mem::take(&mut original_account.info.balance); + original_account.mark_touch(); + transitions.push((address, original_account)); + Ok(balance.try_into().unwrap()) + }) + .collect::, _>>()?; + + self.commit_iter(transitions); + Ok(balances) + } } diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index fa15339253..e862d7d0fd 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -9,7 +9,6 @@ use state::{Account, AccountInfo}; use std::{ boxed::Box, collections::{btree_map, BTreeMap}, - vec::Vec, }; /// Database boxed with a lifetime and Send @@ -81,31 +80,6 @@ impl State { self.bundle_state.size_hint() } - /// Drains balances from given account and return those values. - /// - /// It is used for DAO hardfork state change to move values from given accounts. - pub fn drain_balances( - &mut self, - addresses: impl IntoIterator, - ) -> Result, DB::Error> { - // Make transition and update cache state - let addresses_iter = addresses.into_iter(); - let (lower, _) = addresses_iter.size_hint(); - let mut transitions = Vec::with_capacity(lower); - let mut balances = Vec::with_capacity(lower); - for address in addresses_iter { - let original_account = self.load_cache_account(address)?; - let (balance, transition) = original_account.drain_balance(); - balances.push(balance); - transitions.push((address, transition)) - } - // Append transition - if let Some(s) = self.transition_state.as_mut() { - s.add_transitions(transitions) - } - Ok(balances) - } - /// State clear EIP-161 is enabled in Spurious Dragon hardfork. pub fn set_state_clear_flag(&mut self, has_state_clear: bool) { self.cache.set_state_clear_flag(has_state_clear); From 99e6f34a6da28614caa3beb141c624d264509785 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C4=90=E1=BA=A1t=20Nguy=E1=BB=85n?= Date: Tue, 9 Dec 2025 00:01:16 +0700 Subject: [PATCH 068/127] feat: early return if the l1 fee scalar is zero (#3213) * feat: early return if the l1 fee scalar is zero * update code format --- crates/op-revm/src/l1block.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index cf61db7697..3c86904b47 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -345,6 +345,10 @@ impl L1BlockInfo { /// `estimatedSize*(baseFeeScalar*l1BaseFee*16 + blobFeeScalar*l1BlobBaseFee)/1e12` fn calculate_tx_l1_cost_fjord(&self, input: &[u8]) -> U256 { let l1_fee_scaled = self.calculate_l1_fee_scaled_ecotone(); + if l1_fee_scaled.is_zero() { + return U256::ZERO; + } + let estimated_size = self.tx_estimated_size_fjord(input); estimated_size From 708be4c51f554fa93fc74529bcaa0ca7e9b1c599 Mon Sep 17 00:00:00 2001 From: Bhargava Shastry Date: Mon, 8 Dec 2025 19:46:30 +0100 Subject: [PATCH 069/127] fix(statetest): use spec-aware blob base fee update fraction (#3210) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The state test runner was hardcoding BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN (3,338,477) instead of using the spec-aware value from CfgEnv. This caused consensus divergence with geth on Prague/Osaka blob transaction tests. Changes: - Modified block_env() to use cfg.blob_base_fee_update_fraction() which returns the correct value based on spec (Cancun: 3338477, Prague: 5007716) - Updated runner.rs to pass mutable cfg reference as required by the API - Added comprehensive unit tests verifying correct blob fee calculation for Cancun, Prague, and Osaka forks With excess_blob_gas=0x240000 and maxFeePerBlobGas=0x01: - Cancun fraction (3338477): blob_price = 2, tx FAILS (insufficient fee) - Prague fraction (5007716): blob_price = 1, tx SUCCEEDS 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude --- bins/revme/src/cmd/statetest/runner.rs | 2 +- crates/statetest-types/src/test_unit.rs | 157 +++++++++++++++++++++++- 2 files changed, 156 insertions(+), 3 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 9303041496..849748d51b 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -340,7 +340,7 @@ pub fn execute_test_suite( } // Setup block environment for this spec - let block = unit.block_env(&cfg); + let block = unit.block_env(&mut cfg); for (index, test) in tests.iter().enumerate() { // Setup transaction environment diff --git a/crates/statetest-types/src/test_unit.rs b/crates/statetest-types/src/test_unit.rs index c877fe2bcd..15d55d14dc 100644 --- a/crates/statetest-types/src/test_unit.rs +++ b/crates/statetest-types/src/test_unit.rs @@ -94,7 +94,7 @@ impl TestUnit { /// # Returns /// /// A configured [`BlockEnv`] ready for execution - pub fn block_env(&self, cfg: &CfgEnv) -> BlockEnv { + pub fn block_env(&self, cfg: &mut CfgEnv) -> BlockEnv { let mut block = BlockEnv { number: self.env.current_number, beneficiary: self.env.current_coinbase, @@ -112,10 +112,11 @@ impl TestUnit { }; // Handle EIP-4844 blob gas + // Use spec-aware blob fee fraction: Cancun uses 3338477, Prague/Osaka use 5007716 if let Some(current_excess_blob_gas) = self.env.current_excess_blob_gas { block.set_blob_excess_gas_and_price( current_excess_blob_gas.to(), - revm::primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, + cfg.blob_base_fee_update_fraction(), ); } @@ -127,3 +128,155 @@ impl TestUnit { block } } + +#[cfg(test)] +mod tests { + use super::*; + use revm::{ + context_interface::block::calc_blob_gasprice, + primitives::{ + eip4844::{BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE}, + U256, + }, + }; + + /// Creates a minimal TestUnit with excess blob gas set for testing blob fee calculation + fn create_test_unit_with_excess_blob_gas(excess_blob_gas: u64) -> TestUnit { + TestUnit { + info: None, + env: Env { + current_chain_id: None, + current_coinbase: Address::ZERO, + current_difficulty: U256::ZERO, + current_gas_limit: U256::from(1_000_000u64), + current_number: U256::from(1u64), + current_timestamp: U256::from(1u64), + current_base_fee: Some(U256::from(1u64)), + previous_hash: None, + current_random: None, + current_beacon_root: None, + current_withdrawals_root: None, + current_excess_blob_gas: Some(U256::from(excess_blob_gas)), + }, + pre: HashMap::default(), + post: BTreeMap::default(), + transaction: TransactionParts { + tx_type: None, + data: vec![], + gas_limit: vec![], + gas_price: None, + nonce: U256::ZERO, + secret_key: B256::ZERO, + sender: None, + to: None, + value: vec![], + max_fee_per_gas: None, + max_priority_fee_per_gas: None, + initcodes: None, + access_lists: vec![], + authorization_list: None, + blob_versioned_hashes: vec![], + max_fee_per_blob_gas: None, + }, + out: None, + } + } + + /// Test that block_env uses the correct blob base fee update fraction for Cancun + #[test] + fn test_block_env_blob_fee_fraction_cancun() { + let unit = create_test_unit_with_excess_blob_gas(0x240000); // 2,359,296 + + let mut cfg = CfgEnv::default(); + cfg.spec = SpecId::CANCUN; + + let block = unit.block_env(&mut cfg); + + // Verify blob gas price is calculated with Cancun fraction + let blob_info = block + .blob_excess_gas_and_price + .expect("blob info should be set"); + assert_eq!(blob_info.excess_blob_gas, 0x240000); + + // Calculate expected price with Cancun fraction (3338477) + // blob_gasprice = fake_exponential(1, excess_blob_gas, BLOB_BASE_FEE_UPDATE_FRACTION) + // With excess_blob_gas=0x240000 and CANCUN fraction=3338477, price should be 2 + let expected_price = calc_blob_gasprice(0x240000, BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN); + assert_eq!(blob_info.blob_gasprice, expected_price); + assert_eq!(blob_info.blob_gasprice, 2); // With Cancun fraction, price is 2 + } + + /// Test that block_env uses the correct blob base fee update fraction for Prague + #[test] + fn test_block_env_blob_fee_fraction_prague() { + let unit = create_test_unit_with_excess_blob_gas(0x240000); // 2,359,296 + + let mut cfg = CfgEnv::default(); + cfg.spec = SpecId::PRAGUE; + + let block = unit.block_env(&mut cfg); + + // Verify blob gas price is calculated with Prague fraction + let blob_info = block + .blob_excess_gas_and_price + .expect("blob info should be set"); + assert_eq!(blob_info.excess_blob_gas, 0x240000); + + // Calculate expected price with Prague fraction (5007716) + // With excess_blob_gas=0x240000 and PRAGUE fraction=5007716, price should be 1 + let expected_price = calc_blob_gasprice(0x240000, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE); + assert_eq!(blob_info.blob_gasprice, expected_price); + assert_eq!(blob_info.blob_gasprice, 1); // With Prague fraction, price is 1 + } + + /// Test that block_env uses the correct blob base fee update fraction for Osaka + #[test] + fn test_block_env_blob_fee_fraction_osaka() { + let unit = create_test_unit_with_excess_blob_gas(0x240000); // 2,359,296 + + let mut cfg = CfgEnv::default(); + cfg.spec = SpecId::OSAKA; + + let block = unit.block_env(&mut cfg); + + // Osaka should use Prague fraction (same as Prague) + let blob_info = block + .blob_excess_gas_and_price + .expect("blob info should be set"); + let expected_price = calc_blob_gasprice(0x240000, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE); + assert_eq!(blob_info.blob_gasprice, expected_price); + assert_eq!(blob_info.blob_gasprice, 1); // With Prague fraction, price is 1 + } + + /// Test that demonstrates the bug scenario from IMPLEMENTATION_PROMPT.md + /// With excess_blob_gas=0x240000 and maxFeePerBlobGas=0x01: + /// - Cancun fraction (3338477): blob_price = 2, tx FAILS (insufficient fee) + /// - Prague fraction (5007716): blob_price = 1, tx SUCCEEDS + #[test] + fn test_blob_fee_difference_affects_tx_validity() { + let excess_blob_gas = 0x240000u64; + + // Calculate prices with both fractions + let cancun_price = + calc_blob_gasprice(excess_blob_gas, BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN); + let prague_price = + calc_blob_gasprice(excess_blob_gas, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE); + + // Verify the prices are different + assert_eq!(cancun_price, 2, "Cancun blob price should be 2"); + assert_eq!(prague_price, 1, "Prague blob price should be 1"); + + // With maxFeePerBlobGas=1: + // - Cancun: 1 < 2, tx would fail with insufficient fee + // - Prague: 1 >= 1, tx would succeed + let max_fee_per_blob_gas = 1u128; + assert!( + max_fee_per_blob_gas < cancun_price, + "Tx should fail with Cancun fraction" + ); + assert!( + max_fee_per_blob_gas >= prague_price, + "Tx should succeed with Prague fraction" + ); + } +} From 9afd166642e5b00e8fb9d5eeb8e165dc4346bd0d Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 9 Dec 2025 23:38:48 +0100 Subject: [PATCH 070/127] feat: JournaledAccount sload/sstore (#3201) * feat: JournaledAccount sload/sstore * nit renames * revert doc * rename *_preserve_error to *_concrete_error * nits and rm of duplicated logic --- .../context/interface/src/journaled_state.rs | 7 +- .../interface/src/journaled_state/account.rs | 209 +++++++++++- crates/context/interface/src/lib.rs | 3 +- crates/context/src/context.rs | 19 +- crates/context/src/journal.rs | 20 +- crates/context/src/journal/inner.rs | 298 ++++++++++-------- crates/context/src/journal/warm_addresses.rs | 23 ++ crates/handler/src/frame.rs | 9 +- crates/handler/src/pre_execution.rs | 3 +- crates/primitives/src/hints_util.rs | 32 ++ crates/primitives/src/lib.rs | 1 + examples/cheatcode_inspector/src/main.rs | 9 +- 12 files changed, 457 insertions(+), 176 deletions(-) create mode 100644 crates/primitives/src/hints_util.rs diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 0883be6b4b..7edc224ae8 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -7,6 +7,7 @@ use crate::{ context::{SStoreResult, SelfDestructResult}, host::LoadError, journaled_state::account::JournaledAccountTr, + ErasedError, }; use core::ops::{Deref, DerefMut}; use database_interface::Database; @@ -15,7 +16,6 @@ use primitives::{ }; use state::{Account, AccountInfo, Bytecode}; use std::{borrow::Cow, vec::Vec}; - /// Trait that contains database and journal of all changes that were made to the state. pub trait JournalTr { /// Database type that is used in the journal. @@ -304,6 +304,9 @@ pub enum JournalLoadError { ColdLoadSkipped, } +/// Journal error on loading of storage or account with Boxed Database error. +pub type JournalLoadErasedError = JournalLoadError; + impl JournalLoadError { /// Returns true if the error is a database error. #[inline] @@ -462,6 +465,7 @@ pub struct AccountInfoLoad<'a> { impl<'a> AccountInfoLoad<'a> { /// Creates new [`AccountInfoLoad`] with the given account info, cold load status and empty status. + #[inline] pub fn new(account: &'a AccountInfo, is_cold: bool, is_empty: bool) -> Self { Self { account: Cow::Borrowed(account), @@ -473,6 +477,7 @@ impl<'a> AccountInfoLoad<'a> { /// Maps the account info of the [`AccountInfoLoad`] to a new [`StateLoad`]. /// /// Useful for transforming the account info of the [`AccountInfoLoad`] and preserving the cold load status. + #[inline] pub fn into_state_load(self, f: F) -> StateLoad where F: FnOnce(Cow<'a, AccountInfo>) -> O, diff --git a/crates/context/interface/src/journaled_state/account.rs b/crates/context/interface/src/journaled_state/account.rs index 363b1feb31..ae5691f7a0 100644 --- a/crates/context/interface/src/journaled_state/account.rs +++ b/crates/context/interface/src/journaled_state/account.rs @@ -3,12 +3,19 @@ //! //! Useful to encapsulate account and journal entries together. So when account gets changed, we can add a journal entry for it. -use crate::journaled_state::entry::JournalEntry; +use crate::{ + context::{SStoreResult, StateLoad}, + journaled_state::{entry::JournalEntry, JournalLoadErasedError, JournalLoadError}, + ErasedError, +}; use super::entry::JournalEntryTr; use auto_impl::auto_impl; -use primitives::{Address, B256, KECCAK_EMPTY, U256}; -use state::{Account, Bytecode}; +use database_interface::Database; +use primitives::{ + hash_map::Entry, Address, HashMap, HashSet, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, +}; +use state::{Account, Bytecode, EvmStorageSlot}; use std::vec::Vec; /// Trait that contains database and journal of all changes that were made to the account. @@ -17,6 +24,24 @@ pub trait JournaledAccountTr { /// Returns the account. fn account(&self) -> &Account; + /// Sloads the storage slot and returns its mutable reference + fn sload( + &mut self, + key: StorageKey, + skip_cold_load: bool, + ) -> Result, JournalLoadErasedError>; + + /// Loads the storage slot and stores the new value + fn sstore( + &mut self, + key: StorageKey, + new: StorageValue, + skip_cold_load: bool, + ) -> Result, JournalLoadErasedError>; + + /// Loads the code of the account. and returns it as reference. + fn load_code(&mut self) -> Result<&Bytecode, JournalLoadErasedError>; + /// Returns the balance of the account. fn balance(&self) -> &U256; @@ -96,38 +121,166 @@ pub trait JournaledAccountTr { /// /// Useful to encapsulate account and journal entries together. So when account gets changed, we can add a journal entry for it. #[derive(Debug, PartialEq, Eq)] -pub struct JournaledAccount<'a, ENTRY: JournalEntryTr = JournalEntry> { +pub struct JournaledAccount<'a, DB, ENTRY: JournalEntryTr = JournalEntry> { /// Address of the account. address: Address, /// Mutable account. account: &'a mut Account, /// Journal entries. journal_entries: &'a mut Vec, + /// Access list. + access_list: &'a HashMap>, + /// Transaction ID. + transaction_id: usize, + /// Database used to load storage. + db: &'a mut DB, } -impl<'a, ENTRY: JournalEntryTr> JournaledAccount<'a, ENTRY> { - /// Consumes the journaled account and returns the mutable account. - #[inline] - pub fn into_account_ref(self) -> &'a Account { - self.account - } - - /// Creates a new journaled account. +impl<'a, DB: Database, ENTRY: JournalEntryTr> JournaledAccount<'a, DB, ENTRY> { + /// Creates new JournaledAccount #[inline] pub fn new( address: Address, account: &'a mut Account, journal_entries: &'a mut Vec, + db: &'a mut DB, + access_list: &'a HashMap>, + transaction_id: usize, ) -> Self { Self { address, account, journal_entries, + access_list, + transaction_id, + db, } } + + /// Loads the storage slot. + /// + /// If storage is cold and skip_cold_load is true, it will return [`JournalLoadError::ColdLoadSkipped`] error. + /// + /// Does not erase the db error. + #[inline(never)] + pub fn sload_concrete_error( + &mut self, + key: StorageKey, + skip_cold_load: bool, + ) -> Result, JournalLoadError> { + let is_newly_created = self.account.is_created(); + let (slot, is_cold) = match self.account.storage.entry(key) { + Entry::Occupied(occ) => { + let slot = occ.into_mut(); + // skip load if account is cold. + let is_cold = slot.is_cold_transaction_id(self.transaction_id); + if is_cold && skip_cold_load { + return Err(JournalLoadError::ColdLoadSkipped); + } + slot.mark_warm_with_transaction_id(self.transaction_id); + (slot, is_cold) + } + Entry::Vacant(vac) => { + // is storage cold + let is_cold = self + .access_list + .get(&self.address) + .and_then(|v| v.get(&key)) + .is_none(); + + if is_cold && skip_cold_load { + return Err(JournalLoadError::ColdLoadSkipped); + } + // if storage was cleared, we don't need to ping db. + let value = if is_newly_created { + StorageValue::ZERO + } else { + self.db.storage(self.address, key)? + }; + + let slot = vac.insert(EvmStorageSlot::new(value, self.transaction_id)); + (slot, is_cold) + } + }; + + if is_cold { + // add it to journal as cold loaded. + self.journal_entries + .push(ENTRY::storage_warmed(self.address, key)); + } + + Ok(StateLoad::new(slot, is_cold)) + } + + /// Stores the storage slot. + /// + /// If storage is cold and skip_cold_load is true, it will return [`JournalLoadError::ColdLoadSkipped`] error. + /// + /// Does not erase the db error. + #[inline] + pub fn sstore_concrete_error( + &mut self, + key: StorageKey, + new: StorageValue, + skip_cold_load: bool, + ) -> Result, JournalLoadError> { + // touch the account so changes are tracked. + self.touch(); + + // assume that acc exists and load the slot. + let slot = self.sload_concrete_error(key, skip_cold_load)?; + + let ret = Ok(StateLoad::new( + SStoreResult { + original_value: slot.original_value(), + present_value: slot.present_value(), + new_value: new, + }, + slot.is_cold, + )); + + // when new value is different from present, we need to add a journal entry and make a change. + if slot.present_value != new { + let previous_value = slot.present_value; + // insert value into present state. + slot.data.present_value = new; + + // add journal entry. + self.journal_entries + .push(ENTRY::storage_changed(self.address, key, previous_value)); + } + + ret + } + + /// Loads the code of the account. and returns it as reference. + /// + /// Does not erase the db error. + #[inline] + pub fn load_code_preserve_error(&mut self) -> Result<&Bytecode, JournalLoadError> { + if self.account.info.code.is_none() { + let hash = *self.code_hash(); + let code = if hash == KECCAK_EMPTY { + Bytecode::default() + } else { + self.db.code_by_hash(hash)? + }; + self.account.info.code = Some(code); + } + + Ok(self.account.info.code.as_ref().unwrap()) + } + + /// Consumes the journaled account and returns the account. + #[inline] + pub fn into_account(self) -> &'a Account { + self.account + } } -impl<'a, ENTRY: JournalEntryTr> JournaledAccountTr for JournaledAccount<'a, ENTRY> { +impl<'a, DB: Database, ENTRY: JournalEntryTr> JournaledAccountTr + for JournaledAccount<'a, DB, ENTRY> +{ /// Returns the account. fn account(&self) -> &Account { self.account @@ -295,4 +448,34 @@ impl<'a, ENTRY: JournalEntryTr> JournaledAccountTr for JournaledAccount<'a, ENTR self.set_code(hash, bytecode); self.bump_nonce(); } + + /// Loads the storage slot. + #[inline] + fn sload( + &mut self, + key: StorageKey, + skip_cold_load: bool, + ) -> Result, JournalLoadErasedError> { + self.sload_concrete_error(key, skip_cold_load) + .map_err(|i| i.map(ErasedError::new)) + } + + /// Stores the storage slot. + #[inline] + fn sstore( + &mut self, + key: StorageKey, + new: StorageValue, + skip_cold_load: bool, + ) -> Result, JournalLoadErasedError> { + self.sstore_concrete_error(key, new, skip_cold_load) + .map_err(|i| i.map(ErasedError::new)) + } + + /// Loads the code of the account. and returns it as reference. + #[inline] + fn load_code(&mut self) -> Result<&Bytecode, JournalLoadErasedError> { + self.load_code_preserve_error() + .map_err(|i| i.map(ErasedError::new)) + } } diff --git a/crates/context/interface/src/lib.rs b/crates/context/interface/src/lib.rs index dcb65e731d..cdf8a79c38 100644 --- a/crates/context/interface/src/lib.rs +++ b/crates/context/interface/src/lib.rs @@ -17,8 +17,7 @@ pub mod transaction; pub use block::Block; pub use cfg::{Cfg, CreateScheme, TransactTo}; pub use context::{ContextError, ContextSetters, ContextTr}; -pub use database_interface::erased_error::ErasedError; -pub use database_interface::{DBErrorMarker, Database}; +pub use database_interface::{erased_error::ErasedError, DBErrorMarker, Database}; pub use either; pub use host::{DummyHost, Host}; pub use journaled_state::JournalTr; diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index f03ac49d19..5bf1832fa3 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -8,7 +8,9 @@ use context_interface::{ }; use database_interface::{Database, DatabaseRef, EmptyDB, WrapDatabaseRef}; use derive_where::derive_where; -use primitives::{hardfork::SpecId, Address, Log, StorageKey, StorageValue, B256, U256}; +use primitives::{ + hardfork::SpecId, hints_util::cold_path, Address, Log, StorageKey, StorageValue, B256, U256, +}; /// EVM context contains data that EVM needs for execution. #[derive_where(Clone, Debug; BLOCK, CFG, CHAIN, TX, DB, JOURNAL, ::Error, LOCAL)] @@ -499,6 +501,7 @@ impl< self.db_mut() .block_hash(requested_number) .map_err(|e| { + cold_path(); *self.error() = Err(e.into()); }) .ok() @@ -532,6 +535,7 @@ impl< self.journal_mut() .selfdestruct(address, target, skip_cold_load) .map_err(|e| { + cold_path(); let (ret, err) = e.into_parts(); if let Some(err) = err { *self.error() = Err(err.into()); @@ -551,6 +555,7 @@ impl< self.journal_mut() .sstore_skip_cold_load(address, key, value, skip_cold_load) .map_err(|e| { + cold_path(); let (ret, err) = e.into_parts(); if let Some(err) = err { *self.error() = Err(err.into()); @@ -569,6 +574,7 @@ impl< self.journal_mut() .sload_skip_cold_load(address, key, skip_cold_load) .map_err(|e| { + cold_path(); let (ret, err) = e.into_parts(); if let Some(err) = err { *self.error() = Err(err.into()); @@ -584,14 +590,17 @@ impl< load_code: bool, skip_cold_load: bool, ) -> Result, LoadError> { - let error = &mut self.error; - let journal = &mut self.journaled_state; - match journal.load_account_info_skip_cold_load(address, load_code, skip_cold_load) { + match self.journaled_state.load_account_info_skip_cold_load( + address, + load_code, + skip_cold_load, + ) { Ok(a) => Ok(a), Err(e) => { + cold_path(); let (ret, err) = e.into_parts(); if let Some(err) = err { - *error = Err(err.into()); + self.error = Err(err.into()); } Err(ret) } diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index f9bde2ca74..8360261e70 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -93,9 +93,10 @@ impl JournalTr for Journal { type Database = DB; type State = EvmState; type JournaledAccount<'a> - = JournaledAccount<'a, ENTRY> + = JournaledAccount<'a, DB, ENTRY> where - Self: 'a; + ENTRY: 'a, + DB: 'a; fn new(database: DB) -> Journal { Self { @@ -118,7 +119,7 @@ impl JournalTr for Journal { key: StorageKey, ) -> Result, ::Error> { self.inner - .sload(&mut self.database, address, key, false) + .sload_assume_account_present(&mut self.database, address, key, false) .map_err(JournalLoadError::unwrap_db_error) } @@ -129,7 +130,7 @@ impl JournalTr for Journal { value: StorageValue, ) -> Result, ::Error> { self.inner - .sstore(&mut self.database, address, key, value, false) + .sstore_assume_account_present(&mut self.database, address, key, value, false) .map_err(JournalLoadError::unwrap_db_error) } @@ -341,7 +342,7 @@ impl JournalTr for Journal { ) -> Result, JournalLoadError<::Error>> { self.inner - .sload(&mut self.database, address, key, skip_cold_load) + .sload_assume_account_present(&mut self.database, address, key, skip_cold_load) } #[inline] @@ -353,8 +354,13 @@ impl JournalTr for Journal { skip_cold_load: bool, ) -> Result, JournalLoadError<::Error>> { - self.inner - .sstore(&mut self.database, address, key, value, skip_cold_load) + self.inner.sstore_assume_account_present( + &mut self.database, + address, + key, + value, + skip_cold_load, + ) } #[inline] diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 36d1beb8db..6328b4262f 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -14,9 +14,10 @@ use database_interface::Database; use primitives::{ hardfork::SpecId::{self, *}, hash_map::Entry, + hints_util::unlikely, Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; -use state::{Account, EvmState, EvmStorageSlot, TransientStorage}; +use state::{Account, EvmState, TransientStorage}; use std::vec::Vec; /// Inner journal state that contains journal and state changes. /// @@ -565,11 +566,14 @@ impl JournalInner { /// Loads account into memory. return if it is cold or warm accessed #[inline] - pub fn load_account( - &mut self, - db: &mut DB, + pub fn load_account<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, address: Address, - ) -> Result, DB::Error> { + ) -> Result, DB::Error> + where + 'db: 'a, + { self.load_account_optional(db, address, false, false) .map_err(JournalLoadError::unwrap_db_error) } @@ -621,63 +625,121 @@ impl JournalInner { /// In case of EIP-7702 delegated account will not be loaded, /// [`Self::load_account_delegated`] should be used instead. #[inline] - pub fn load_code( - &mut self, - db: &mut DB, + pub fn load_code<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, address: Address, - ) -> Result, DB::Error> { + ) -> Result, DB::Error> + where + 'db: 'a, + { self.load_account_optional(db, address, true, false) .map_err(JournalLoadError::unwrap_db_error) } /// Loads account into memory. If account is already loaded it will be marked as warm. #[inline] - pub fn load_account_optional( - &mut self, - db: &mut DB, + pub fn load_account_optional<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, address: Address, load_code: bool, skip_cold_load: bool, - ) -> Result, JournalLoadError> { - let load = self.load_account_mut_optional_code(db, address, load_code, skip_cold_load)?; - Ok(load.map(|i| i.into_account_ref())) + ) -> Result, JournalLoadError> + where + 'db: 'a, + { + let mut load = self.load_account_mut_optional(db, address, skip_cold_load)?; + if load_code { + load.data.load_code_preserve_error()?; + } + Ok(load.map(|i| i.into_account())) } /// Loads account into memory. If account is already loaded it will be marked as warm. #[inline] - pub fn load_account_mut( - &mut self, - db: &mut DB, + pub fn load_account_mut<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, address: Address, - ) -> Result>, DB::Error> { - self.load_account_mut_optional_code(db, address, false, false) + ) -> Result>, DB::Error> + where + 'db: 'a, + { + self.load_account_mut_optional(db, address, false) .map_err(JournalLoadError::unwrap_db_error) } /// Loads account. If account is already loaded it will be marked as warm. - #[inline(never)] - pub fn load_account_mut_optional_code( - &mut self, - db: &mut DB, + #[inline] + pub fn load_account_mut_optional_code<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, address: Address, load_code: bool, skip_cold_load: bool, - ) -> Result>, JournalLoadError> { - let load = match self.state.entry(address) { + ) -> Result>, JournalLoadError> + where + 'db: 'a, + { + let mut load = self.load_account_mut_optional(db, address, skip_cold_load)?; + if load_code { + load.data.load_code_preserve_error()?; + } + Ok(load) + } + + /// Gets the account mut reference. + /// + /// # Load Unsafe + /// + /// Use this function only if you know what you are doing. It will not mark the account as warm or cold. + /// It will not bump transition_id or return if it is cold or warm loaded. This function is useful + /// when we know account is warm, touched and already loaded. + /// + /// It is useful when we want to access storage from account that is currently being executed. + #[inline] + pub fn get_account_mut<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, + address: Address, + ) -> Option> + where + 'db: 'a, + { + let account = self.state.get_mut(&address)?; + Some(JournaledAccount::new( + address, + account, + &mut self.journal, + db, + self.warm_addresses.access_list(), + self.transaction_id, + )) + } + + /// Loads account. If account is already loaded it will be marked as warm. + #[inline(never)] + pub fn load_account_mut_optional<'a, 'db, DB: Database>( + &'a mut self, + db: &'db mut DB, + address: Address, + skip_cold_load: bool, + ) -> Result>, JournalLoadError> + where + 'db: 'a, + { + let (account, is_cold) = match self.state.entry(address) { Entry::Occupied(entry) => { let account = entry.into_mut(); // skip load if account is cold. let mut is_cold = account.is_cold_transaction_id(self.transaction_id); - if is_cold { - // account can be loaded by we still need to check warm_addresses to see if it is cold. - let should_be_cold = self.warm_addresses.is_cold(&address); - // dont load it cold if skipping cold load is true. - if should_be_cold && skip_cold_load { - return Err(JournalLoadError::ColdLoadSkipped); - } - is_cold = should_be_cold; + if unlikely(is_cold) { + is_cold = self + .warm_addresses + .check_is_cold(&address, skip_cold_load)?; // mark it warm. account.mark_warm_with_transaction_id(self.transaction_id); @@ -690,20 +752,18 @@ impl JournalInner { } // unmark locally created account.unmark_created_locally(); + + // journal loading of cold account. + self.journal.push(ENTRY::account_warmed(address)); } - StateLoad { - data: account, - is_cold, - } + (account, is_cold) } Entry::Vacant(vac) => { - // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account - let is_cold = self.warm_addresses.is_cold(&address); - - // dont load cold account if skip_cold_load is true - if is_cold && skip_cold_load { - return Err(JournalLoadError::ColdLoadSkipped); - } + // Precompiles, among some other account(access list and coinbase included) + // are warm loaded so we need to take that into account + let is_cold = self + .warm_addresses + .check_is_cold(&address, skip_cold_load)?; let account = if let Some(account) = db.basic(address)? { let mut account: Account = account.into(); @@ -713,36 +773,29 @@ impl JournalInner { Account::new_not_existing(self.transaction_id) }; - StateLoad { - data: vac.insert(account), - is_cold, + // journal loading of cold account. + if is_cold { + self.journal.push(ENTRY::account_warmed(address)); } + + (vac.insert(account), is_cold) } }; - // journal loading of cold account. - if load.is_cold { - self.journal.push(ENTRY::account_warmed(address)); - } - - if load_code && load.data.info.code.is_none() { - let info = &mut load.data.info; - let code = if info.code_hash == KECCAK_EMPTY { - Bytecode::default() - } else { - db.code_by_hash(info.code_hash)? - }; - info.code = Some(code); - } - - Ok(load.map(|i| JournaledAccount::new(address, i, &mut self.journal))) + Ok(StateLoad::new( + JournaledAccount::new( + address, + account, + &mut self.journal, + db, + self.warm_addresses.access_list(), + self.transaction_id, + ), + is_cold, + )) } /// Loads storage slot. - /// - /// # Panics - /// - /// Panics if the account is not present in the state. #[inline] pub fn sload( &mut self, @@ -751,46 +804,45 @@ impl JournalInner { key: StorageKey, skip_cold_load: bool, ) -> Result, JournalLoadError> { - // assume acc is warm - let account = self.state.get_mut(&address).unwrap(); - - let is_newly_created = account.is_created(); - let (value, is_cold) = match account.storage.entry(key) { - Entry::Occupied(occ) => { - let slot = occ.into_mut(); - // skip load if account is cold. - let is_cold = slot.is_cold_transaction_id(self.transaction_id); - if skip_cold_load && is_cold { - return Err(JournalLoadError::ColdLoadSkipped); - } - slot.mark_warm_with_transaction_id(self.transaction_id); - (slot.present_value, is_cold) - } - Entry::Vacant(vac) => { - // is storage cold - let is_cold = !self.warm_addresses.is_storage_warm(&address, &key); - - if is_cold && skip_cold_load { - return Err(JournalLoadError::ColdLoadSkipped); - } - // if storage was cleared, we don't need to ping db. - let value = if is_newly_created { - StorageValue::ZERO - } else { - db.storage(address, key)? - }; - vac.insert(EvmStorageSlot::new(value, self.transaction_id)); + self.load_account_mut(db, address)? + .sload_concrete_error(key, skip_cold_load) + .map(|s| s.map(|s| s.present_value)) + } - (value, is_cold) - } + /// Loads storage slot. + /// + /// If account is not present it will return [`JournalLoadError::ColdLoadSkipped`] error. + #[inline] + pub fn sload_assume_account_present( + &mut self, + db: &mut DB, + address: Address, + key: StorageKey, + skip_cold_load: bool, + ) -> Result, JournalLoadError> { + let Some(mut account) = self.get_account_mut(db, address) else { + return Err(JournalLoadError::ColdLoadSkipped); }; - if is_cold { - // add it to journal as cold loaded. - self.journal.push(ENTRY::storage_warmed(address, key)); - } + account + .sload_concrete_error(key, skip_cold_load) + .map(|s| s.map(|s| s.present_value)) + } - Ok(StateLoad::new(value, is_cold)) + /// Stores storage slot. + /// + /// If account is not present it will load from database + #[inline] + pub fn sstore( + &mut self, + db: &mut DB, + address: Address, + key: StorageKey, + new: StorageValue, + skip_cold_load: bool, + ) -> Result, JournalLoadError> { + self.load_account_mut(db, address)? + .sstore_concrete_error(key, new, skip_cold_load) } /// Stores storage slot. @@ -799,7 +851,7 @@ impl JournalInner { /// /// **Note**: Account should already be present in our state. #[inline] - pub fn sstore( + pub fn sstore_assume_account_present( &mut self, db: &mut DB, address: Address, @@ -807,37 +859,11 @@ impl JournalInner { new: StorageValue, skip_cold_load: bool, ) -> Result, JournalLoadError> { - // assume that acc exists and load the slot. - let present = self.sload(db, address, key, skip_cold_load)?; - let acc = self.state.get_mut(&address).unwrap(); - - // if there is no original value in dirty return present value, that is our original. - let slot = acc.storage.get_mut(&key).unwrap(); - - // new value is same as present, we don't need to do anything - if present.data == new { - return Ok(StateLoad::new( - SStoreResult { - original_value: slot.original_value(), - present_value: present.data, - new_value: new, - }, - present.is_cold, - )); - } + let Some(mut account) = self.get_account_mut(db, address) else { + return Err(JournalLoadError::ColdLoadSkipped); + }; - self.journal - .push(ENTRY::storage_changed(address, key, present.data)); - // insert value into present state. - slot.present_value = new; - Ok(StateLoad::new( - SStoreResult { - original_value: slot.original_value(), - present_value: present.data, - new_value: new, - }, - present.is_cold, - )) + account.sstore_concrete_error(key, new, skip_cold_load) } /// Read transient storage tied to the account. @@ -928,7 +954,7 @@ mod tests { // Try to sload with skip_cold_load=true - should succeed because slot is in access list let mut db = EmptyDB::new(); - let result = journal.sload(&mut db, test_address, test_key, true); + let result = journal.sload_assume_account_present(&mut db, test_address, test_key, true); // Should succeed and return as warm assert!(result.is_ok()); diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs index ac5f1a6a40..27e5bce936 100644 --- a/crates/context/src/journal/warm_addresses.rs +++ b/crates/context/src/journal/warm_addresses.rs @@ -3,6 +3,7 @@ //! It is used to optimize access to precompile addresses. use bitvec::{bitvec, vec::BitVec}; +use context_interface::journaled_state::JournalLoadError; use primitives::{short_address, Address, HashMap, HashSet, StorageKey, SHORT_ADDRESS_CAP}; /// Stores addresses that are warm loaded. Contains precompiles and coinbase address. @@ -91,6 +92,12 @@ impl WarmAddresses { self.access_list = access_list; } + /// Returns the access list. + #[inline] + pub fn access_list(&self) -> &HashMap> { + &self.access_list + } + /// Clear the coinbase address. #[inline] pub fn clear_coinbase(&mut self) { @@ -150,6 +157,22 @@ impl WarmAddresses { pub fn is_cold(&self, address: &Address) -> bool { !self.is_warm(address) } + + /// Checks if the address is cold loaded and returns an error if it is and skip_cold_load is true. + #[inline(never)] + pub fn check_is_cold( + &self, + address: &Address, + skip_cold_load: bool, + ) -> Result> { + let is_cold = self.is_cold(address); + + if is_cold && skip_cold_load { + return Err(JournalLoadError::ColdLoadSkipped); + } + + Ok(is_cold) + } } #[cfg(test)] diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 50c2c59533..a40b1f4535 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -2,10 +2,10 @@ use crate::{ evm::FrameTr, item_or_result::FrameInitOrResult, precompile_provider::PrecompileProvider, CallFrame, CreateFrame, FrameData, FrameResult, ItemOrResult, }; -use context::{journaled_state::account::JournaledAccountTr, result::FromStringError}; +use context::result::FromStringError; use context_interface::{ context::ContextError, - journaled_state::{JournalCheckpoint, JournalTr}, + journaled_state::{account::JournaledAccountTr, JournalCheckpoint, JournalTr}, local::{FrameToken, OutFrame}, Cfg, ContextTr, Database, }; @@ -276,7 +276,8 @@ impl EthFrame { } // Fetch balance of caller. - let mut caller_info = context.journal_mut().load_account_mut(inputs.caller)?; + let journal = context.journal_mut(); + let mut caller_info = journal.load_account_mut(inputs.caller)?; // Check if caller has enough balance to send to the created contract. // decrement of balance is done in the create_account_checkpoint. @@ -304,7 +305,7 @@ impl EthFrame { drop(caller_info); // Drop caller info to avoid borrow checker issues. // warm load account. - context.journal_mut().load_account(created_address)?; + journal.load_account(created_address)?; // Create account, transfer funds and make the journal checkpoint. let checkpoint = match context.journal_mut().create_account_checkpoint( diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 1112f81eb4..88dc789b83 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -4,9 +4,8 @@ use crate::{EvmTr, PrecompileProvider}; use bytecode::Bytecode; -use context::journaled_state::account::JournaledAccountTr; use context_interface::{ - journaled_state::JournalTr, + journaled_state::{account::JournaledAccountTr, JournalTr}, result::InvalidTransaction, transaction::{AccessListItemTr, AuthorizationTr, Transaction, TransactionType}, Block, Cfg, ContextTr, Database, diff --git a/crates/primitives/src/hints_util.rs b/crates/primitives/src/hints_util.rs new file mode 100644 index 0000000000..dc858e9d5f --- /dev/null +++ b/crates/primitives/src/hints_util.rs @@ -0,0 +1,32 @@ +//! Utility functions for hints. +//! Used from Hashbrown . + +// FIXME: Replace with `core::hint::{likely, unlikely}` once they are stable. +// pub use core::intrinsics::{likely, unlikely}; + +/// Cold path function. +#[inline(always)] +#[cold] +pub fn cold_path() {} + +/// Returns `b` but mark `false` path as cold +#[inline(always)] +pub fn likely(b: bool) -> bool { + if b { + true + } else { + cold_path(); + false + } +} + +/// Returns `b` but mark `true` path as cold +#[inline(always)] +pub fn unlikely(b: bool) -> bool { + if b { + cold_path(); + true + } else { + false + } +} diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 5f1b2e112b..9193733bb2 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -24,6 +24,7 @@ pub mod eip7823; pub mod eip7825; pub mod eip7907; pub mod hardfork; +pub mod hints_util; mod once_lock; pub use constants::*; diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index 7142ea03f4..cbe0007aaa 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -60,10 +60,7 @@ impl Backend { impl JournalTr for Backend { type Database = InMemoryDB; type State = EvmState; - type JournaledAccount<'a> - = JournaledAccount<'a> - where - Self: 'a; + type JournaledAccount<'a> = JournaledAccount<'a, InMemoryDB, JournalEntry>; fn new(database: InMemoryDB) -> Self { Self::new(SpecId::default(), database) @@ -300,7 +297,7 @@ impl JournalTr for Backend { address: Address, load_code: bool, skip_cold_load: bool, - ) -> Result, JournalLoadError<::Error>> { + ) -> Result, JournalLoadError> { self.journaled_state .load_account_info_skip_cold_load(address, load_code, skip_cold_load) } @@ -309,7 +306,7 @@ impl JournalTr for Backend { &mut self, address: Address, load_code: bool, - ) -> Result>, ::Error> { + ) -> Result>, Infallible> { self.journaled_state .load_account_mut_optional_code(address, load_code) } From 58c49fbe5c5a7f7f91e830a6e154e066475e080f Mon Sep 17 00:00:00 2001 From: Developer Uche <69772615+developeruche@users.noreply.github.com> Date: Wed, 10 Dec 2025 12:14:00 +0100 Subject: [PATCH 071/127] feat(create): Implement Cache for CreateInputs::created_address (#3218) * cached created address * fmt --- crates/handler/src/execution.rs | 12 +++---- .../interpreter/src/instructions/contract.rs | 8 ++--- .../src/interpreter_action/create_inputs.rs | 31 +++++++++++++++++-- 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/crates/handler/src/execution.rs b/crates/handler/src/execution.rs index e79f9d4b4c..d326974642 100644 --- a/crates/handler/src/execution.rs +++ b/crates/handler/src/execution.rs @@ -31,12 +31,12 @@ pub fn create_init_frame( return_memory_offset: 0..0, })) } - TxKind::Create => FrameInput::Create(Box::new(CreateInputs { - caller: tx.caller(), - scheme: CreateScheme::Create, - value: tx.value(), - init_code: input, + TxKind::Create => FrameInput::Create(Box::new(CreateInputs::new( + tx.caller(), + CreateScheme::Create, + tx.value(), + input, gas_limit, - })), + ))), } } diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 22a36f6629..4a360c7350 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -95,13 +95,13 @@ pub fn create( .interpreter .bytecode .set_action(InterpreterAction::NewFrame(FrameInput::Create(Box::new( - CreateInputs { - caller: context.interpreter.input.target_address(), + CreateInputs::new( + context.interpreter.input.target_address(), scheme, value, - init_code: code, + code, gas_limit, - }, + ), )))); } diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index d44ed3eac8..fe88771072 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -1,8 +1,9 @@ use context_interface::CreateScheme; +use core::cell::OnceCell; use primitives::{Address, Bytes, U256}; /// Inputs for a create call -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] +#[derive(Clone, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateInputs { /// Caller address of the EVM @@ -15,17 +16,41 @@ pub struct CreateInputs { pub init_code: Bytes, /// The gas limit of the call pub gas_limit: u64, + /// Cached created address. This is computed lazily and cached to avoid + /// redundant keccak computations when inspectors call `created_address`. + #[cfg_attr(feature = "serde", serde(skip))] + cached_address: OnceCell
, } impl CreateInputs { + /// Creates a new `CreateInputs` instance. + pub fn new( + caller: Address, + scheme: CreateScheme, + value: U256, + init_code: Bytes, + gas_limit: u64, + ) -> Self { + Self { + caller, + scheme, + value, + init_code, + gas_limit, + cached_address: OnceCell::new(), + } + } + /// Returns the address that this create call will create. + /// + /// The result is cached to avoid redundant keccak computations. pub fn created_address(&self, nonce: u64) -> Address { - match self.scheme { + *self.cached_address.get_or_init(|| match self.scheme { CreateScheme::Create => self.caller.create(nonce), CreateScheme::Create2 { salt } => self .caller .create2_from_code(salt.to_be_bytes(), &self.init_code), CreateScheme::Custom { address } => address, - } + }) } } From 2befb622978d29a70a5b73f8902a484d294f33de Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 10 Dec 2025 12:14:22 +0100 Subject: [PATCH 072/127] feat: Gas params (#3132) * dyn gas table * continuation of work * rename to GasParams * gas params * sstore_dyn and sstore refund * continuation, first test passing * cleanup prints * fix selfdestruct * run-tests keep-going, fixes to pass tests * rename to gas params, sstore/call fixes * fix balance * cache on spec change * use instruction gas params * fix tests * fix tests * fix tests * fix tests * fix doc * fmt * cleanup * cleanup * move first values to table * cleanup * Apply suggestion from @rakita * Apply suggestions from code review * Apply suggestion from @rakita * Apply suggestion from @rakita * Add GasId struct * nits * copilot nits * nit, use resize_memory macro in place of fn --- crates/context/interface/src/context.rs | 12 + crates/context/src/journal/inner.rs | 2 +- crates/handler/src/evm.rs | 8 +- crates/handler/src/frame.rs | 19 +- crates/handler/src/handler.rs | 13 + crates/handler/src/instructions.rs | 47 +- crates/inspector/src/handler.rs | 3 + crates/interpreter/src/gas.rs | 25 +- crates/interpreter/src/gas/calc.rs | 329 +------- crates/interpreter/src/gas/constants.rs | 5 +- crates/interpreter/src/gas/params.rs | 775 ++++++++++++++++++ crates/interpreter/src/instructions.rs | 99 ++- .../src/instructions/arithmetic.rs | 19 +- .../interpreter/src/instructions/bitwise.rs | 27 - .../src/instructions/block_info.rs | 8 - .../interpreter/src/instructions/contract.rs | 25 +- .../src/instructions/contract/call_helpers.rs | 59 +- .../interpreter/src/instructions/control.rs | 14 +- crates/interpreter/src/instructions/host.rs | 147 ++-- crates/interpreter/src/instructions/macros.rs | 71 +- crates/interpreter/src/instructions/memory.rs | 10 +- crates/interpreter/src/instructions/stack.rs | 6 - crates/interpreter/src/instructions/system.rs | 26 +- .../interpreter/src/instructions/tx_info.rs | 3 - crates/interpreter/src/interpreter.rs | 31 +- .../src/interpreter/shared_memory.rs | 33 +- scripts/run-tests.sh | 57 +- 27 files changed, 1201 insertions(+), 672 deletions(-) create mode 100644 crates/interpreter/src/gas/params.rs diff --git a/crates/context/interface/src/context.rs b/crates/context/interface/src/context.rs index 114235cb6e..014dcf85e1 100644 --- a/crates/context/interface/src/context.rs +++ b/crates/context/interface/src/context.rs @@ -195,6 +195,18 @@ impl SStoreResult { self.new_value.const_eq(&self.present_value) } + /// Returns `true` if the new values changes the present value. + #[inline] + pub const fn new_values_changes_present(&self) -> bool { + !self.is_new_eq_present() + } + + /// Returns `true` if the original value is zero and the new value is not zero. + #[inline] + pub const fn have_changed_from_zero(&self) -> bool { + self.is_original_zero() && !self.is_new_zero() + } + /// Returns `true` if the original value is equal to the present value. #[inline] pub const fn is_original_eq_present(&self) -> bool { diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 6328b4262f..34f4e7d70e 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -499,7 +499,7 @@ impl JournalInner { address: Address, target: Address, skip_cold_load: bool, - ) -> Result, JournalLoadError<::Error>> { + ) -> Result, JournalLoadError> { let spec = self.spec; let account_load = self.load_account_optional(db, target, false, skip_cold_load)?; let is_cold = account_load.is_cold; diff --git a/crates/handler/src/evm.rs b/crates/handler/src/evm.rs index 0ad3130f0c..8607f48dce 100644 --- a/crates/handler/src/evm.rs +++ b/crates/handler/src/evm.rs @@ -183,7 +183,13 @@ where let ctx = &mut self.ctx; let precompiles = &mut self.precompiles; - let res = Self::Frame::init_with_context(new_frame, ctx, precompiles, frame_input)?; + let res = Self::Frame::init_with_context( + new_frame, + ctx, + precompiles, + frame_input, + self.instruction.gas_params(), + )?; Ok(res.map_frame(|token| { if is_first_init { diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index a40b1f4535..6338ea44af 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -12,7 +12,7 @@ use context_interface::{ use core::cmp::min; use derive_where::derive_where; use interpreter::{ - gas, + gas::{self, params::GasParams}, interpreter::{EthInterpreter, ExtBytecode}, interpreter_action::FrameInit, interpreter_types::ReturnData, @@ -101,6 +101,7 @@ pub type ContextTrDbError = <::Db as Database>::Error; impl EthFrame { /// Clear and initialize a frame. #[allow(clippy::too_many_arguments)] + #[inline(always)] pub fn clear( &mut self, data: FrameData, @@ -113,6 +114,7 @@ impl EthFrame { spec_id: SpecId, gas_limit: u64, checkpoint: JournalCheckpoint, + gas_params: GasParams, ) { let Self { data: data_ref, @@ -126,7 +128,9 @@ impl EthFrame { *input_ref = input; *depth_ref = depth; *is_finished_ref = false; - interpreter.clear(memory, bytecode, inputs, is_static, spec_id, gas_limit); + interpreter.clear( + memory, bytecode, inputs, is_static, spec_id, gas_limit, gas_params, + ); *checkpoint_ref = checkpoint; } @@ -143,6 +147,7 @@ impl EthFrame { depth: usize, memory: SharedMemory, inputs: Box, + gas_params: GasParams, ) -> Result, ERROR> { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -242,6 +247,7 @@ impl EthFrame { ctx.cfg().spec().into(), gas_limit, checkpoint, + gas_params, ); Ok(ItemOrResult::Item(this.consume())) } @@ -257,6 +263,7 @@ impl EthFrame { depth: usize, memory: SharedMemory, inputs: Box, + gas_params: GasParams, ) -> Result, ERROR> { let spec = context.cfg().spec().into(); let return_error = |e| { @@ -343,6 +350,7 @@ impl EthFrame { spec, gas_limit, checkpoint, + gas_params, ); Ok(ItemOrResult::Item(this.consume())) } @@ -356,6 +364,7 @@ impl EthFrame { ctx: &mut CTX, precompiles: &mut PRECOMPILES, frame_init: FrameInit, + gas_params: GasParams, ) -> Result< ItemOrResult, ContextError<<::Db as Database>::Error>, @@ -369,9 +378,11 @@ impl EthFrame { match frame_input { FrameInput::Call(inputs) => { - Self::make_call_frame(this, ctx, precompiles, depth, memory, inputs) + Self::make_call_frame(this, ctx, precompiles, depth, memory, inputs, gas_params) + } + FrameInput::Create(inputs) => { + Self::make_create_frame(this, ctx, depth, memory, inputs, gas_params) } - FrameInput::Create(inputs) => Self::make_create_frame(this, ctx, depth, memory, inputs), FrameInput::Empty => unreachable!(), } } diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 9c862d9b4b..ca905a1683 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -1,3 +1,4 @@ +use crate::instructions::InstructionProvider; use crate::{ evm::FrameTr, execution, post_execution, @@ -98,6 +99,7 @@ pub trait Handler { &mut self, evm: &mut Self::Evm, ) -> Result, Self::Error> { + self.configure(evm); // Run inner handler and catch all errors to handle cleanup. match self.run_without_catch_error(evm) { Ok(output) => Ok(output), @@ -105,6 +107,15 @@ pub trait Handler { } } + /// Configure the handler: + /// * Set Instruction gas table to the spec id. + #[inline] + fn configure(&mut self, evm: &mut Self::Evm) { + let spec_id = evm.ctx().cfg().spec().into(); + // sets static gas depending on the spec id. + evm.ctx_instructions().1.set_spec(spec_id); + } + /// Runs the system call. /// /// System call is a special transaction where caller is a [`crate::SYSTEM_ADDRESS`] @@ -126,6 +137,8 @@ pub trait Handler { ) -> Result, Self::Error> { // dummy values that are not used. let init_and_floor_gas = InitialAndFloorGas::new(0, 0); + // configure the evm for system call. + self.configure(evm); // call execution and than output. match self .execution(evm, &init_and_floor_gas) diff --git a/crates/handler/src/instructions.rs b/crates/handler/src/instructions.rs index b45582f0d4..1af53ddbc6 100644 --- a/crates/handler/src/instructions.rs +++ b/crates/handler/src/instructions.rs @@ -1,12 +1,14 @@ use auto_impl::auto_impl; use interpreter::{ - instructions::{instruction_table, InstructionTable}, + gas::params::GasParams, + instructions::{instruction_table_gas_changes_spec, InstructionTable}, Host, Instruction, InterpreterTypes, }; +use primitives::hardfork::SpecId; use std::boxed::Box; /// Stores instructions for EVM. -#[auto_impl(&, Arc, Rc)] +#[auto_impl(&mut, Box)] pub trait InstructionProvider { /// Context type. type Context; @@ -15,6 +17,12 @@ pub trait InstructionProvider { /// Returns the instruction table that is used by EvmTr to execute instructions. fn instruction_table(&self) -> &InstructionTable; + + /// Returns the gas params that is used by EvmTr to execute instructions. + fn gas_params(&self) -> GasParams; + + /// Sets the spec. Return true if the spec was changed. + fn set_spec(&mut self, spec: SpecId) -> bool; } /// Ethereum instruction contains list of mainnet instructions that is used for Interpreter execution. @@ -22,6 +30,10 @@ pub trait InstructionProvider { pub struct EthInstructions { /// Table containing instruction implementations indexed by opcode. pub instruction_table: Box>, + /// Gas params that sets gas costs for instructions. + pub gas_params: GasParams, + /// Spec that is used to set gas costs for instructions. + pub spec: SpecId, } impl Clone for EthInstructions @@ -31,6 +43,8 @@ where fn clone(&self) -> Self { Self { instruction_table: self.instruction_table.clone(), + gas_params: self.gas_params.clone(), + spec: self.spec, } } } @@ -42,14 +56,25 @@ where { /// Returns `EthInstructions` with mainnet spec. pub fn new_mainnet() -> Self { - Self::new(instruction_table::()) + let spec = SpecId::default(); + Self::new( + instruction_table_gas_changes_spec(spec), + GasParams::new_spec(spec), + spec, + ) } /// Returns a new instance of `EthInstructions` with custom instruction table. #[inline] - pub fn new(base_table: InstructionTable) -> Self { + pub fn new( + base_table: InstructionTable, + gas_params: GasParams, + spec: SpecId, + ) -> Self { Self { instruction_table: Box::new(base_table), + gas_params, + spec, } } @@ -71,6 +96,20 @@ where fn instruction_table(&self) -> &InstructionTable { &self.instruction_table } + + fn gas_params(&self) -> GasParams { + self.gas_params.clone() + } + + fn set_spec(&mut self, spec: SpecId) -> bool { + if spec == self.spec { + return false; + } + self.instruction_table = Box::new(instruction_table_gas_changes_spec(spec)); + self.gas_params = GasParams::new_spec(spec); + + true + } } impl Default for EthInstructions diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index 53bdf436db..fe43a71b46 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -42,6 +42,7 @@ where &mut self, evm: &mut Self::Evm, ) -> Result, Self::Error> { + self.configure(evm); match self.inspect_run_without_catch_error(evm) { Ok(output) => Ok(output), Err(e) => self.catch_error(evm, e), @@ -136,6 +137,8 @@ where ) -> Result, Self::Error> { // dummy values that are not used. let init_and_floor_gas = InitialAndFloorGas::new(0, 0); + // configure + self.configure(evm); // call execution with inspection and then output. match self .inspect_execution(evm, &init_and_floor_gas) diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index 37a0421835..a8ac93a37c 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -2,6 +2,7 @@ mod calc; mod constants; +pub mod params; pub use calc::*; pub use constants::*; @@ -91,11 +92,6 @@ impl Gas { self.remaining } - /// Return remaining gas after subtracting 63/64 parts. - pub const fn remaining_63_of_64_parts(&self) -> u64 { - self.remaining - self.remaining / 64 - } - /// Erases a gas cost from the totals. #[inline] pub fn erase_cost(&mut self, returned: u64) { @@ -199,15 +195,30 @@ impl MemoryGas { } } + /// Sets the number of words and the expansion cost. + /// + /// Returns the difference between the new and old expansion cost. + #[inline] + pub fn set_words_num(&mut self, words_num: usize, mut expansion_cost: u64) -> Option { + self.words_num = words_num; + core::mem::swap(&mut self.expansion_cost, &mut expansion_cost); + self.expansion_cost.checked_sub(expansion_cost) + } + /// Records a new memory length and calculates additional cost if memory is expanded. /// Returns the additional gas cost required, or None if no expansion is needed. #[inline] - pub fn record_new_len(&mut self, new_num: usize) -> Option { + pub fn record_new_len( + &mut self, + new_num: usize, + linear_cost: u64, + quadratic_cost: u64, + ) -> Option { if new_num <= self.words_num { return None; } self.words_num = new_num; - let mut cost = crate::gas::calc::memory_gas(new_num); + let mut cost = crate::gas::calc::memory_gas(new_num, linear_cost, quadratic_cost); core::mem::swap(&mut self.expansion_cost, &mut cost); // Safe to subtract because we know that new_len > length // Notice the swap above. diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 8b41601c01..06d9e6550d 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,70 +1,10 @@ use super::constants::*; -use crate::{num_words, tri, SStoreResult, SelfDestructResult, StateLoad}; -use context_interface::{ - journaled_state::AccountLoad, transaction::AccessListItemTr as _, Transaction, TransactionType, -}; +use crate::num_words; +use context_interface::{transaction::AccessListItemTr as _, Transaction, TransactionType}; use primitives::{eip7702, hardfork::SpecId, U256}; -/// `SSTORE` opcode refund calculation. -#[allow(clippy::collapsible_else_if)] #[inline] -pub fn sstore_refund(spec_id: SpecId, vals: &SStoreResult) -> i64 { - if spec_id.is_enabled_in(SpecId::ISTANBUL) { - // EIP-3529: Reduction in refunds - let sstore_clears_schedule = if spec_id.is_enabled_in(SpecId::LONDON) { - (SSTORE_RESET - COLD_SLOAD_COST + ACCESS_LIST_STORAGE_KEY) as i64 - } else { - REFUND_SSTORE_CLEARS - }; - if vals.is_new_eq_present() { - 0 - } else { - if vals.is_original_eq_present() && vals.is_new_zero() { - sstore_clears_schedule - } else { - let mut refund = 0; - - if !vals.is_original_zero() { - if vals.is_present_zero() { - refund -= sstore_clears_schedule; - } else if vals.is_new_zero() { - refund += sstore_clears_schedule; - } - } - - if vals.is_original_eq_new() { - let (gas_sstore_reset, gas_sload) = if spec_id.is_enabled_in(SpecId::BERLIN) { - (SSTORE_RESET - COLD_SLOAD_COST, WARM_STORAGE_READ_COST) - } else { - (SSTORE_RESET, sload_cost(spec_id, false)) - }; - if vals.is_original_zero() { - refund += (SSTORE_SET - gas_sload) as i64; - } else { - refund += (gas_sstore_reset - gas_sload) as i64; - } - } - - refund - } - } - } else { - if !vals.is_present_zero() && vals.is_new_zero() { - REFUND_SSTORE_CLEARS - } else { - 0 - } - } -} - -/// `CREATE2` opcode cost calculation. -#[inline] -pub const fn create2_cost(len: usize) -> Option { - CREATE.checked_add(tri!(cost_per_word(len, KECCAK256WORD))) -} - -#[inline] -const fn log2floor(value: U256) -> u64 { +pub(crate) const fn log2floor(value: U256) -> u64 { let mut l: u64 = 256; let mut i = 3; loop { @@ -86,62 +26,6 @@ const fn log2floor(value: U256) -> u64 { l } -/// `EXP` opcode cost calculation. -#[inline] -pub fn exp_cost(spec_id: SpecId, power: U256) -> Option { - if power.is_zero() { - Some(EXP) - } else { - // EIP-160: EXP cost increase - let gas_byte = U256::from(if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { - 50 - } else { - 10 - }); - let gas = U256::from(EXP) - .checked_add(gas_byte.checked_mul(U256::from(log2floor(power) / 8 + 1))?)?; - - u64::try_from(gas).ok() - } -} - -/// `*COPY` opcodes cost calculation. -#[inline] -pub const fn copy_cost_verylow(len: usize) -> Option { - copy_cost(VERYLOW, len) -} - -/// `EXTCODECOPY` opcode cost calculation. -#[inline] -pub const fn extcodecopy_cost(spec_id: SpecId, len: usize, is_cold: bool) -> Option { - let base_gas = if spec_id.is_enabled_in(SpecId::BERLIN) { - warm_cold_cost(is_cold) - } else if spec_id.is_enabled_in(SpecId::TANGERINE) { - 700 - } else { - 20 - }; - copy_cost(base_gas, len) -} - -#[inline] -/// Calculates the gas cost for copy operations based on data length. -pub const fn copy_cost(base_cost: u64, len: usize) -> Option { - base_cost.checked_add(tri!(cost_per_word(len, COPY))) -} - -/// `LOG` opcode cost calculation. -#[inline] -pub const fn log_cost(n: u8, len: u64) -> Option { - tri!(LOG.checked_add(tri!(LOGDATA.checked_mul(len)))).checked_add(LOGTOPIC * n as u64) -} - -/// `KECCAK256` opcode cost calculation. -#[inline] -pub const fn keccak256_cost(len: usize) -> Option { - KECCAK256.checked_add(tri!(cost_per_word(len, KECCAK256WORD))) -} - /// Calculate the cost of buffer per word. #[inline] pub const fn cost_per_word(len: usize, multiple: u64) -> Option { @@ -161,214 +45,13 @@ pub const fn initcode_cost(len: usize) -> u64 { cost } -/// `SLOAD` opcode cost calculation. -#[inline] -pub const fn sload_cost(spec_id: SpecId, is_cold: bool) -> u64 { - if spec_id.is_enabled_in(SpecId::BERLIN) { - if is_cold { - COLD_SLOAD_COST - } else { - WARM_STORAGE_READ_COST - } - } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { - // EIP-1884: Repricing for trie-size-dependent opcodes - ISTANBUL_SLOAD_GAS - } else if spec_id.is_enabled_in(SpecId::TANGERINE) { - // EIP-150: Gas cost changes for IO-heavy operations - 200 - } else { - 50 - } -} - -/// Static gas cost for sstore. -#[inline] -pub const fn sstore_cost_static(spec_id: SpecId) -> u64 { - if spec_id.is_enabled_in(SpecId::BERLIN) { - WARM_STORAGE_READ_COST - } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { - ISTANBUL_SLOAD_GAS - } else { - SSTORE_RESET - } -} - -/// Dynamic gas cost for sstore. -#[inline] -pub const fn sstore_cost_dynamic(spec_id: SpecId, vals: &SStoreResult, is_cold: bool) -> u64 { - sstore_cost(spec_id, vals, is_cold) - sstore_cost_static(spec_id) -} - -/// Static gas cost for sstore. -#[inline] -pub const fn static_sstore_cost(spec_id: SpecId) -> u64 { - if spec_id.is_enabled_in(SpecId::BERLIN) { - WARM_STORAGE_READ_COST - } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { - ISTANBUL_SLOAD_GAS - } else { - SSTORE_RESET - } -} - -/// Dynamic gas cost for sstore. -#[inline] -pub const fn dyn_sstore_cost(spec_id: SpecId, vals: &SStoreResult, is_cold: bool) -> u64 { - sstore_cost(spec_id, vals, is_cold) - static_sstore_cost(spec_id) -} - -/// `SSTORE` opcode cost calculation. -#[inline] -pub const fn sstore_cost(spec_id: SpecId, vals: &SStoreResult, is_cold: bool) -> u64 { - if spec_id.is_enabled_in(SpecId::BERLIN) { - // Berlin specification logic - let mut gas_cost = istanbul_sstore_cost::(vals); - - if is_cold { - gas_cost += COLD_SLOAD_COST; - } - gas_cost - } else if spec_id.is_enabled_in(SpecId::ISTANBUL) { - // Istanbul logic - istanbul_sstore_cost::(vals) - } else { - // Frontier logic - frontier_sstore_cost(vals) - } -} - -/// EIP-2200: Structured Definitions for Net Gas Metering -#[inline] -const fn istanbul_sstore_cost( - vals: &SStoreResult, -) -> u64 { - if vals.is_new_eq_present() { - SLOAD_GAS - } else if vals.is_original_eq_present() && vals.is_original_zero() { - SSTORE_SET - } else if vals.is_original_eq_present() { - SSTORE_RESET_GAS - } else { - SLOAD_GAS - } -} - -/// Frontier sstore cost just had two cases set and reset values. -#[inline] -const fn frontier_sstore_cost(vals: &SStoreResult) -> u64 { - if vals.is_present_zero() && !vals.is_new_zero() { - SSTORE_SET - } else { - SSTORE_RESET - } -} - -/// Static gas cost for selfdestruct. -#[inline] -pub const fn static_selfdestruct_cost(spec_id: SpecId) -> u64 { - // EIP-150: Gas cost changes for IO-heavy operations - if spec_id.is_enabled_in(SpecId::TANGERINE) { - 5000 - } else { - 0 - } -} - -/// `SELFDESTRUCT` opcode cost calculation. -#[inline] -pub const fn dyn_selfdestruct_cost(spec_id: SpecId, res: &StateLoad) -> u64 { - let is_tangerine = spec_id.is_enabled_in(SpecId::TANGERINE); - let mut gas = 0; - - // EIP-161: State trie clearing (invariant-preserving alternative) - let should_charge_topup = if spec_id.is_enabled_in(SpecId::SPURIOUS_DRAGON) { - res.data.had_value && !res.data.target_exists - } else { - !res.data.target_exists - }; - - // EIP-150: Gas cost changes for IO-heavy operations - if is_tangerine && should_charge_topup { - gas += NEWACCOUNT - } - - if res.is_cold { - gas += selfdestruct_cold_beneficiary_cost(spec_id); - } - - gas -} - -/// EIP-2929: Gas cost increases for state access opcodes -#[inline] -pub const fn selfdestruct_cold_beneficiary_cost(spec_id: SpecId) -> u64 { - if spec_id.is_enabled_in(SpecId::BERLIN) { - COLD_ACCOUNT_ACCESS_COST - } else { - 0 - } -} - -/// `SELFDESTRUCT` opcode cost calculation. -#[inline] -pub const fn selfdestruct_cost(spec_id: SpecId, res: StateLoad) -> u64 { - static_selfdestruct_cost(spec_id) + dyn_selfdestruct_cost(spec_id, &res) -} - -/// Calculate static gas for the call -/// -/// Gas depends on: -/// * Spec. For berlin hardfork only warm gas [`WARM_STORAGE_READ_COST`] is calculated. -/// * If there is transfer value. additional gas of [`CALLVALUE`] is added. -#[inline] -pub fn calc_call_static_gas(spec_id: SpecId, has_transfer: bool) -> u64 { - // Account access. - let mut gas = if spec_id.is_enabled_in(SpecId::BERLIN) { - WARM_STORAGE_READ_COST - } else if spec_id.is_enabled_in(SpecId::TANGERINE) { - // EIP-150: Gas cost changes for IO-heavy operations - 700 - } else { - 40 - }; - - // Transfer value cost - if has_transfer { - gas += CALLVALUE; - } - - gas -} - -/// Berlin warm and cold storage access cost for account access. -#[inline] -pub const fn warm_cold_cost(is_cold: bool) -> u64 { - if is_cold { - COLD_ACCOUNT_ACCESS_COST - } else { - WARM_STORAGE_READ_COST - } -} - -/// Berlin warm and cold storage access cost for account access. -/// -/// If delegation is Some, add additional cost for delegation account load. -#[inline] -pub const fn warm_cold_cost_with_delegation(load: StateLoad) -> u64 { - let mut gas = warm_cold_cost(load.is_cold); - if let Some(is_cold) = load.data.is_delegate_account_cold { - gas += warm_cold_cost(is_cold); - } - gas -} - /// Memory expansion cost calculation for a given number of words. #[inline] -pub const fn memory_gas(num_words: usize) -> u64 { +pub const fn memory_gas(num_words: usize, linear_cost: u64, quadratic_cost: u64) -> u64 { let num_words = num_words as u64; - MEMORY + linear_cost .saturating_mul(num_words) - .saturating_add(num_words.saturating_mul(num_words) / 512) + .saturating_add(num_words.saturating_mul(num_words) / quadratic_cost) } /// Init and floor gas from transaction diff --git a/crates/interpreter/src/gas/constants.rs b/crates/interpreter/src/gas/constants.rs index 1739e8ca08..a4a101a985 100644 --- a/crates/interpreter/src/gas/constants.rs +++ b/crates/interpreter/src/gas/constants.rs @@ -83,6 +83,7 @@ pub const EOF_CREATE_GAS: u64 = 32000; pub const ACCESS_LIST_ADDRESS: u64 = 2400; /// Gas cost for accessing a storage key in the access list (EIP-2930). pub const ACCESS_LIST_STORAGE_KEY: u64 = 1900; + /// Gas cost for SLOAD when accessing a cold storage slot (EIP-2929). pub const COLD_SLOAD_COST: u64 = 2100; /// Gas cost for accessing a cold account (EIP-2929). @@ -90,8 +91,6 @@ pub const COLD_ACCOUNT_ACCESS_COST: u64 = 2600; /// Additional gas cost for accessing a cold account. pub const COLD_ACCOUNT_ACCESS_COST_ADDITIONAL: u64 = COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST; -/// Additional gas cost for accessing a cold storage -pub const COLD_SLOAD_COST_ADDITIONAL: u64 = COLD_SLOAD_COST - WARM_STORAGE_READ_COST; /// Gas cost for reading from a warm storage slot (EIP-2929). pub const WARM_STORAGE_READ_COST: u64 = 100; /// Gas cost for SSTORE reset operation on a warm storage slot. @@ -102,5 +101,3 @@ pub const INITCODE_WORD_COST: u64 = 2; /// Gas stipend provided to the recipient of a CALL with value transfer. pub const CALL_STIPEND: u64 = 2300; -/// Minimum gas that must be provided to a callee. -pub const MIN_CALLEE_GAS: u64 = CALL_STIPEND; diff --git a/crates/interpreter/src/gas/params.rs b/crates/interpreter/src/gas/params.rs new file mode 100644 index 0000000000..77db84955b --- /dev/null +++ b/crates/interpreter/src/gas/params.rs @@ -0,0 +1,775 @@ +//! Gas table for dynamic gas constants. + +use crate::{ + gas::{self, log2floor, ISTANBUL_SLOAD_GAS, SSTORE_RESET, SSTORE_SET, WARM_SSTORE_RESET}, + num_words, +}; +use context_interface::context::SStoreResult; +use primitives::{ + hardfork::SpecId::{self}, + U256, +}; +use std::sync::Arc; + +/// Gas table for dynamic gas constants. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct GasParams { + /// Table of gas costs for operations + table: Arc<[u64; 256]>, + /// Pointer to the table. + ptr: *const u64, +} + +#[cfg(feature = "serde")] +mod serde { + use super::{Arc, GasParams}; + use std::vec::Vec; + + #[derive(serde::Serialize, serde::Deserialize)] + struct GasParamsSerde { + table: Vec, + } + + #[cfg(feature = "serde")] + impl serde::Serialize for GasParams { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + GasParamsSerde { + table: self.table.to_vec(), + } + .serialize(serializer) + } + } + + impl<'de> serde::Deserialize<'de> for GasParams { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let table = GasParamsSerde::deserialize(deserializer)?; + if table.table.len() != 256 { + return Err(serde::de::Error::custom("Invalid gas params length")); + } + Ok(Self::new(Arc::new(table.table.try_into().unwrap()))) + } + } +} + +impl Default for GasParams { + fn default() -> Self { + Self::new_spec(SpecId::default()) + } +} + +impl GasParams { + /// Creates a new `GasParams` with the given table. + #[inline] + pub fn new(table: Arc<[u64; 256]>) -> Self { + Self { + ptr: table.as_ptr(), + table, + } + } + + /// Overrides the gas cost for the given gas id. + /// + /// It will clone underlying table and override the values. + /// + /// Use to override default gas cost + /// + /// ```rust + /// use revm_interpreter::gas::params::{GasParams, GasId}; + /// use primitives::hardfork::SpecId; + /// + /// let mut gas_table = GasParams::new_spec(SpecId::default()); + /// gas_table.override_gas([(GasId::memory_linear_cost(), 2), (GasId::memory_quadratic_reduction(), 512)].into_iter()); + /// assert_eq!(gas_table.get(GasId::memory_linear_cost()), 2); + /// assert_eq!(gas_table.get(GasId::memory_quadratic_reduction()), 512); + /// ``` + pub fn override_gas(&mut self, values: impl IntoIterator) { + let mut table = *self.table.clone(); + for (id, value) in values.into_iter() { + table[id.as_usize()] = value; + } + *self = Self::new(Arc::new(table)); + } + + /// Returns the table. + #[inline] + pub fn table(&self) -> &[u64; 256] { + &self.table + } + + /// Creates a new `GasParams` for the given spec. + #[inline] + pub fn new_spec(spec: SpecId) -> Self { + let mut table = [0; 256]; + + table[GasId::exp_byte_gas().as_usize()] = 10; + table[GasId::logdata().as_usize()] = gas::LOGDATA; + table[GasId::logtopic().as_usize()] = gas::LOGTOPIC; + table[GasId::copy_per_word().as_usize()] = gas::COPY; + table[GasId::extcodecopy_per_word().as_usize()] = gas::COPY; + table[GasId::mcopy_per_word().as_usize()] = gas::COPY; + table[GasId::keccak256_per_word().as_usize()] = gas::KECCAK256WORD; + table[GasId::memory_linear_cost().as_usize()] = gas::MEMORY; + table[GasId::memory_quadratic_reduction().as_usize()] = 512; + table[GasId::initcode_per_word().as_usize()] = gas::INITCODE_WORD_COST; + table[GasId::create().as_usize()] = gas::CREATE; + table[GasId::call_stipend_reduction().as_usize()] = 64; + table[GasId::transfer_value_cost().as_usize()] = gas::CALLVALUE; + table[GasId::cold_account_additional_cost().as_usize()] = 0; + table[GasId::new_account_cost().as_usize()] = gas::NEWACCOUNT; + table[GasId::warm_storage_read_cost().as_usize()] = 0; + // Frontiers had fixed 5k cost. + table[GasId::sstore_static().as_usize()] = SSTORE_RESET; + // SSTORE SET + table[GasId::sstore_set_without_load_cost().as_usize()] = SSTORE_SET - SSTORE_RESET; + // SSTORE RESET Is covered in SSTORE_STATIC. + table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = 0; + // SSTORE CLEARING SLOT REFUND + table[GasId::sstore_clearing_slot_refund().as_usize()] = 15000; + table[GasId::selfdestruct_refund().as_usize()] = 24000; + table[GasId::call_stipend().as_usize()] = gas::CALL_STIPEND; + table[GasId::cold_storage_additional_cost().as_usize()] = 0; + table[GasId::cold_storage_cost().as_usize()] = 0; + table[GasId::new_account_cost_for_selfdestruct().as_usize()] = 0; + + if spec.is_enabled_in(SpecId::TANGERINE) { + table[GasId::new_account_cost_for_selfdestruct().as_usize()] = gas::NEWACCOUNT; + } + + if spec.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + table[GasId::exp_byte_gas().as_usize()] = 50; + } + + if spec.is_enabled_in(SpecId::ISTANBUL) { + table[GasId::sstore_static().as_usize()] = gas::ISTANBUL_SLOAD_GAS; + table[GasId::sstore_set_without_load_cost().as_usize()] = + SSTORE_SET - ISTANBUL_SLOAD_GAS; + table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = + SSTORE_RESET - ISTANBUL_SLOAD_GAS; + } + + if spec.is_enabled_in(SpecId::BERLIN) { + table[GasId::sstore_static().as_usize()] = gas::WARM_STORAGE_READ_COST; + table[GasId::cold_account_additional_cost().as_usize()] = + gas::COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + table[GasId::cold_storage_additional_cost().as_usize()] = + gas::COLD_SLOAD_COST - gas::WARM_STORAGE_READ_COST; + table[GasId::cold_storage_cost().as_usize()] = gas::COLD_SLOAD_COST; + table[GasId::warm_storage_read_cost().as_usize()] = gas::WARM_STORAGE_READ_COST; + + table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = + WARM_SSTORE_RESET - gas::WARM_STORAGE_READ_COST; + table[GasId::sstore_set_without_load_cost().as_usize()] = + SSTORE_SET - gas::WARM_STORAGE_READ_COST; + } + + if spec.is_enabled_in(SpecId::LONDON) { + // EIP-3529: Reduction in refunds + + // Replace SSTORE_CLEARS_SCHEDULE (as defined in EIP-2200) with + // SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST (4,800 gas as of EIP-2929 + EIP-2930) + table[GasId::sstore_clearing_slot_refund().as_usize()] = + WARM_SSTORE_RESET + gas::ACCESS_LIST_STORAGE_KEY; + + table[GasId::selfdestruct_refund().as_usize()] = 0; + } + + Self::new(Arc::new(table)) + } + + /// Gets the gas cost for the given gas id. + #[inline] + pub const fn get(&self, id: GasId) -> u64 { + unsafe { *self.ptr.add(id.as_usize()) } + } + + /// `EXP` opcode cost calculation. + #[inline] + pub fn exp_cost(&self, power: U256) -> u64 { + if power.is_zero() { + return 0; + } + // EIP-160: EXP cost increase + self.get(GasId::exp_byte_gas()) + .saturating_mul(log2floor(power) / 8 + 1) + } + + /// Selfdestruct refund. + #[inline] + pub fn selfdestruct_refund(&self) -> i64 { + self.get(GasId::selfdestruct_refund()) as i64 + } + + /// Selfdestruct cost. + #[inline] + pub fn selfdestruct_cost(&self, should_charge_topup: bool, is_cold: bool) -> u64 { + let mut gas = 0; + + // EIP-150: Gas cost changes for IO-heavy operations + if should_charge_topup { + gas += self.new_account_cost_for_selfdestruct(); + } + + if is_cold { + // Note: SELFDESTRUCT does not charge a WARM_STORAGE_READ_COST in case the recipient is already warm, + // which differs from how the other call-variants work. The reasoning behind this is to keep + // the changes small, a SELFDESTRUCT already costs 5K and is a no-op if invoked more than once. + // + // For GasParams both values are zero before BERLIN fork. + gas += self.cold_account_additional_cost() + self.warm_storage_read_cost(); + } + gas + } + + /// EXTCODECOPY gas cost + #[inline] + pub fn extcodecopy(&self, len: usize) -> u64 { + self.get(GasId::extcodecopy_per_word()) + .saturating_mul(num_words(len) as u64) + } + + /// MCOPY gas cost + #[inline] + pub fn mcopy_cost(&self, len: usize) -> u64 { + self.get(GasId::mcopy_per_word()) + .saturating_mul(num_words(len) as u64) + } + + /// Static gas cost for SSTORE opcode + #[inline] + pub fn sstore_static_gas(&self) -> u64 { + self.get(GasId::sstore_static()) + } + + /// SSTORE set cost + #[inline] + pub fn sstore_set_without_load_cost(&self) -> u64 { + self.get(GasId::sstore_set_without_load_cost()) + } + + /// SSTORE reset cost + #[inline] + pub fn sstore_reset_without_cold_load_cost(&self) -> u64 { + self.get(GasId::sstore_reset_without_cold_load_cost()) + } + + /// SSTORE clearing slot refund + #[inline] + pub fn sstore_clearing_slot_refund(&self) -> u64 { + self.get(GasId::sstore_clearing_slot_refund()) + } + + /// Dynamic gas cost for SSTORE opcode. + /// + /// Dynamic gas cost is gas that needs input from SSTORE operation to be calculated. + #[inline] + pub fn sstore_dynamic_gas(&self, is_istanbul: bool, vals: &SStoreResult, is_cold: bool) -> u64 { + // frontier logic gets charged for every SSTORE operation if original value is zero. + // this behaviour is fixed in istanbul fork. + if !is_istanbul { + if vals.is_present_zero() && !vals.is_new_zero() { + return self.sstore_set_without_load_cost(); + } else { + return self.sstore_reset_without_cold_load_cost(); + } + } + + let mut gas = 0; + + // this will be zero before berlin fork. + if is_cold { + gas += self.cold_storage_cost(); + } + + // if new values changed present value and present value is unchanged from original. + if vals.new_values_changes_present() && vals.is_original_eq_present() { + gas += if vals.is_original_zero() { + // set cost for creating storage slot (Zero slot means it is not existing). + // and previous condition says present is same as original. + self.sstore_set_without_load_cost() + } else { + // if new value is not zero, this means we are setting some value to it. + self.sstore_reset_without_cold_load_cost() + }; + } + gas + } + + /// SSTORE refund calculation. + #[inline] + pub fn sstore_refund(&self, is_istanbul: bool, vals: &SStoreResult) -> i64 { + // EIP-3529: Reduction in refunds + let sstore_clearing_slot_refund = self.sstore_clearing_slot_refund() as i64; + + if !is_istanbul { + // // before istanbul fork, refund was always awarded without checking original state. + if !vals.is_present_zero() && vals.is_new_zero() { + return sstore_clearing_slot_refund; + } + return 0; + } + + // If current value equals new value (this is a no-op) + if vals.is_new_eq_present() { + return 0; + } + + // refund for the clearing of storage slot. + // As new is not equal to present, new values zero means that original and present values are not zero + if vals.is_original_eq_present() && vals.is_new_zero() { + return sstore_clearing_slot_refund; + } + + let mut refund = 0; + // If original value is not 0 + if !vals.is_original_zero() { + // If current value is 0 (also means that new value is not 0), + if vals.is_present_zero() { + // remove SSTORE_CLEARS_SCHEDULE gas from refund counter. + refund -= sstore_clearing_slot_refund; + // If new value is 0 (also means that current value is not 0), + } else if vals.is_new_zero() { + // add SSTORE_CLEARS_SCHEDULE gas to refund counter. + refund += sstore_clearing_slot_refund; + } + } + + // If original value equals new value (this storage slot is reset) + if vals.is_original_eq_new() { + // If original value is 0 + if vals.is_original_zero() { + // add SSTORE_SET_GAS - SLOAD_GAS to refund counter. + refund += self.sstore_set_without_load_cost() as i64; + // Otherwise + } else { + // add SSTORE_RESET_GAS - SLOAD_GAS gas to refund counter. + refund += self.sstore_reset_without_cold_load_cost() as i64; + } + } + refund + } + + /// `LOG` opcode cost calculation. + #[inline] + pub const fn log_cost(&self, n: u8, len: u64) -> u64 { + self.get(GasId::logdata()) + .saturating_mul(len) + .saturating_add(self.get(GasId::logtopic()) * n as u64) + } + + /// KECCAK256 gas cost per word + #[inline] + pub fn keccak256_cost(&self, len: usize) -> u64 { + self.get(GasId::keccak256_per_word()) + .saturating_mul(num_words(len) as u64) + } + + /// Memory gas cost + #[inline] + pub fn memory_cost(&self, len: usize) -> u64 { + let len = len as u64; + self.get(GasId::memory_linear_cost()) + .saturating_mul(len) + .saturating_add( + (len.saturating_mul(len)) + .saturating_div(self.get(GasId::memory_quadratic_reduction())), + ) + } + + /// Initcode word cost + #[inline] + pub fn initcode_cost(&self, len: usize) -> u64 { + self.get(GasId::initcode_per_word()) + .saturating_mul(num_words(len) as u64) + } + + /// Create gas cost + #[inline] + pub fn create_cost(&self) -> u64 { + self.get(GasId::create()) + } + + /// Create2 gas cost. + #[inline] + pub fn create2_cost(&self, len: usize) -> u64 { + self.get(GasId::create()).saturating_add( + self.get(GasId::keccak256_per_word()) + .saturating_mul(num_words(len) as u64), + ) + } + + /// Call stipend. + #[inline] + pub fn call_stipend(&self) -> u64 { + self.get(GasId::call_stipend()) + } + + /// Call stipend reduction. Call stipend is reduced by 1/64 of the gas limit. + #[inline] + pub fn call_stipend_reduction(&self, gas_limit: u64) -> u64 { + gas_limit - gas_limit / self.get(GasId::call_stipend_reduction()) + } + + /// Transfer value cost + #[inline] + pub fn transfer_value_cost(&self) -> u64 { + self.get(GasId::transfer_value_cost()) + } + + /// Additional cold cost. Additional cold cost is added to the gas cost if the account is cold loaded. + #[inline] + pub fn cold_account_additional_cost(&self) -> u64 { + self.get(GasId::cold_account_additional_cost()) + } + + /// Cold storage additional cost. + #[inline] + pub fn cold_storage_additional_cost(&self) -> u64 { + self.get(GasId::cold_storage_additional_cost()) + } + + /// Cold storage cost. + #[inline] + pub fn cold_storage_cost(&self) -> u64 { + self.get(GasId::cold_storage_cost()) + } + + /// New account cost. New account cost is added to the gas cost if the account is empty. + #[inline] + pub fn new_account_cost(&self, is_spurious_dragon: bool, transfers_value: bool) -> u64 { + // EIP-161: State trie clearing (invariant-preserving alternative) + // Pre-Spurious Dragon: always charge for new account + // Post-Spurious Dragon: only charge if value is transferred + if !is_spurious_dragon || transfers_value { + return self.get(GasId::new_account_cost()); + } + 0 + } + + /// New account cost for selfdestruct. + #[inline] + pub fn new_account_cost_for_selfdestruct(&self) -> u64 { + self.get(GasId::new_account_cost_for_selfdestruct()) + } + + /// Warm storage read cost. Warm storage read cost is added to the gas cost if the account is warm loaded. + #[inline] + pub fn warm_storage_read_cost(&self) -> u64 { + self.get(GasId::warm_storage_read_cost()) + } + + /// Copy cost + #[inline] + pub fn copy_cost(&self, len: usize) -> u64 { + self.copy_per_word_cost(num_words(len)) + } + + /// Copy per word cost + #[inline] + pub fn copy_per_word_cost(&self, word_num: usize) -> u64 { + self.get(GasId::copy_per_word()) + .saturating_mul(word_num as u64) + } +} + +/// Gas identifier that maps onto index in gas table. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct GasId(u8); + +impl GasId { + /// Creates a new `GasId` with the given id. + pub const fn new(id: u8) -> Self { + Self(id) + } + + /// Returns the id of the gas. + pub const fn as_u8(&self) -> u8 { + self.0 + } + + /// Returns the id of the gas as a usize. + pub const fn as_usize(&self) -> usize { + self.0 as usize + } + + /// Returns the name of the gas identifier as a string. + /// + /// # Examples + /// + /// ``` + /// use revm_interpreter::gas::params::GasId; + /// + /// assert_eq!(GasId::exp_byte_gas().name(), "exp_byte_gas"); + /// assert_eq!(GasId::memory_linear_cost().name(), "memory_linear_cost"); + /// assert_eq!(GasId::sstore_static().name(), "sstore_static"); + /// ``` + pub const fn name(&self) -> &'static str { + match self.0 { + x if x == Self::exp_byte_gas().as_u8() => "exp_byte_gas", + x if x == Self::extcodecopy_per_word().as_u8() => "extcodecopy_per_word", + x if x == Self::copy_per_word().as_u8() => "copy_per_word", + x if x == Self::logdata().as_u8() => "logdata", + x if x == Self::logtopic().as_u8() => "logtopic", + x if x == Self::mcopy_per_word().as_u8() => "mcopy_per_word", + x if x == Self::keccak256_per_word().as_u8() => "keccak256_per_word", + x if x == Self::memory_linear_cost().as_u8() => "memory_linear_cost", + x if x == Self::memory_quadratic_reduction().as_u8() => "memory_quadratic_reduction", + x if x == Self::initcode_per_word().as_u8() => "initcode_per_word", + x if x == Self::create().as_u8() => "create", + x if x == Self::call_stipend_reduction().as_u8() => "call_stipend_reduction", + x if x == Self::transfer_value_cost().as_u8() => "transfer_value_cost", + x if x == Self::cold_account_additional_cost().as_u8() => { + "cold_account_additional_cost" + } + x if x == Self::new_account_cost().as_u8() => "new_account_cost", + x if x == Self::warm_storage_read_cost().as_u8() => "warm_storage_read_cost", + x if x == Self::sstore_static().as_u8() => "sstore_static", + x if x == Self::sstore_set_without_load_cost().as_u8() => { + "sstore_set_without_load_cost" + } + x if x == Self::sstore_reset_without_cold_load_cost().as_u8() => { + "sstore_reset_without_cold_load_cost" + } + x if x == Self::sstore_clearing_slot_refund().as_u8() => "sstore_clearing_slot_refund", + x if x == Self::selfdestruct_refund().as_u8() => "selfdestruct_refund", + x if x == Self::call_stipend().as_u8() => "call_stipend", + x if x == Self::cold_storage_additional_cost().as_u8() => { + "cold_storage_additional_cost" + } + x if x == Self::cold_storage_cost().as_u8() => "cold_storage_cost", + x if x == Self::new_account_cost_for_selfdestruct().as_u8() => { + "new_account_cost_for_selfdestruct" + } + _ => "unknown", + } + } + + /// Converts a string to a `GasId`. + /// + /// Returns `None` if the string does not match any known gas identifier. + /// + /// # Examples + /// + /// ``` + /// use revm_interpreter::gas::params::GasId; + /// + /// assert_eq!(GasId::from_name("exp_byte_gas"), Some(GasId::exp_byte_gas())); + /// assert_eq!(GasId::from_name("memory_linear_cost"), Some(GasId::memory_linear_cost())); + /// assert_eq!(GasId::from_name("invalid_name"), None); + /// ``` + pub fn from_name(s: &str) -> Option { + match s { + "exp_byte_gas" => Some(Self::exp_byte_gas()), + "extcodecopy_per_word" => Some(Self::extcodecopy_per_word()), + "copy_per_word" => Some(Self::copy_per_word()), + "logdata" => Some(Self::logdata()), + "logtopic" => Some(Self::logtopic()), + "mcopy_per_word" => Some(Self::mcopy_per_word()), + "keccak256_per_word" => Some(Self::keccak256_per_word()), + "memory_linear_cost" => Some(Self::memory_linear_cost()), + "memory_quadratic_reduction" => Some(Self::memory_quadratic_reduction()), + "initcode_per_word" => Some(Self::initcode_per_word()), + "create" => Some(Self::create()), + "call_stipend_reduction" => Some(Self::call_stipend_reduction()), + "transfer_value_cost" => Some(Self::transfer_value_cost()), + "cold_account_additional_cost" => Some(Self::cold_account_additional_cost()), + "new_account_cost" => Some(Self::new_account_cost()), + "warm_storage_read_cost" => Some(Self::warm_storage_read_cost()), + "sstore_static" => Some(Self::sstore_static()), + "sstore_set_without_load_cost" => Some(Self::sstore_set_without_load_cost()), + "sstore_reset_without_cold_load_cost" => { + Some(Self::sstore_reset_without_cold_load_cost()) + } + "sstore_clearing_slot_refund" => Some(Self::sstore_clearing_slot_refund()), + "selfdestruct_refund" => Some(Self::selfdestruct_refund()), + "call_stipend" => Some(Self::call_stipend()), + "cold_storage_additional_cost" => Some(Self::cold_storage_additional_cost()), + "cold_storage_cost" => Some(Self::cold_storage_cost()), + "new_account_cost_for_selfdestruct" => Some(Self::new_account_cost_for_selfdestruct()), + _ => None, + } + } + + /// EXP gas cost per byte + pub const fn exp_byte_gas() -> GasId { + Self::new(1) + } + + /// EXTCODECOPY gas cost per word + pub const fn extcodecopy_per_word() -> GasId { + Self::new(2) + } + + /// Copy copy per word + pub const fn copy_per_word() -> GasId { + Self::new(3) + } + + /// Log data gas cost per byte + pub const fn logdata() -> GasId { + Self::new(4) + } + + /// Log topic gas cost per topic + pub const fn logtopic() -> GasId { + Self::new(5) + } + + /// MCOPY gas cost per word + pub const fn mcopy_per_word() -> GasId { + Self::new(6) + } + + /// KECCAK256 gas cost per word + pub const fn keccak256_per_word() -> GasId { + Self::new(7) + } + + /// Memory linear cost. Memory is additionally added as n*linear_cost. + pub const fn memory_linear_cost() -> GasId { + Self::new(8) + } + + /// Memory quadratic reduction. Memory is additionally added as n*n/quadratic_reduction. + pub const fn memory_quadratic_reduction() -> GasId { + Self::new(9) + } + + /// Initcode word cost + pub const fn initcode_per_word() -> GasId { + Self::new(10) + } + + /// Create gas cost + pub const fn create() -> GasId { + Self::new(11) + } + + /// Call stipend reduction. Call stipend is reduced by 1/64 of the gas limit. + pub const fn call_stipend_reduction() -> GasId { + Self::new(12) + } + + /// Transfer value cost + pub const fn transfer_value_cost() -> GasId { + Self::new(13) + } + + /// Additional cold cost. Additional cold cost is added to the gas cost if the account is cold loaded. + pub const fn cold_account_additional_cost() -> GasId { + Self::new(14) + } + + /// New account cost. New account cost is added to the gas cost if the account is empty. + pub const fn new_account_cost() -> GasId { + Self::new(15) + } + + /// Warm storage read cost. Warm storage read cost is added to the gas cost if the account is warm loaded. + /// + /// Used in delegated account access to specify delegated account warm gas cost. + pub const fn warm_storage_read_cost() -> GasId { + Self::new(16) + } + + /// Static gas cost for SSTORE opcode. This gas in comparison with other gas const needs + /// to be deducted after check for minimal stipend gas cost. This is a reason why it is here. + pub const fn sstore_static() -> GasId { + Self::new(17) + } + + /// SSTORE set cost additional amount after SSTORE_RESET is added. + pub const fn sstore_set_without_load_cost() -> GasId { + Self::new(18) + } + + /// SSTORE reset cost + pub const fn sstore_reset_without_cold_load_cost() -> GasId { + Self::new(19) + } + + /// SSTORE clearing slot refund + pub const fn sstore_clearing_slot_refund() -> GasId { + Self::new(20) + } + + /// Selfdestruct refund. + pub const fn selfdestruct_refund() -> GasId { + Self::new(21) + } + + /// Call stipend checked in sstore. + pub const fn call_stipend() -> GasId { + Self::new(22) + } + + /// Cold storage additional cost. + pub const fn cold_storage_additional_cost() -> GasId { + Self::new(23) + } + + /// Cold storage cost + pub const fn cold_storage_cost() -> GasId { + Self::new(24) + } + + /// New account cost for selfdestruct. + pub const fn new_account_cost_for_selfdestruct() -> GasId { + Self::new(25) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use std::collections::HashSet; + + #[test] + fn test_gas_id_name_and_from_str_coverage() { + let mut unique_names = HashSet::new(); + let mut known_gas_ids = 0; + + // Iterate over all possible GasId values (0..256) + for i in 0..=255 { + let gas_id = GasId::new(i); + let name = gas_id.name(); + + // Count unique names (excluding "unknown") + if name != "unknown" { + unique_names.insert(name); + } + } + + // Now test from_str for each unique name + for name in &unique_names { + if let Some(gas_id) = GasId::from_name(name) { + known_gas_ids += 1; + // Verify round-trip: name -> GasId -> name should be consistent + assert_eq!(gas_id.name(), *name, "Round-trip failed for {}", name); + } + } + + println!("Total unique named GasIds: {}", unique_names.len()); + println!("GasIds resolvable via from_str: {}", known_gas_ids); + + // All unique names should be resolvable via from_str + assert_eq!( + unique_names.len(), + known_gas_ids, + "Not all unique names are resolvable via from_str" + ); + + // We should have exactly 25 known GasIds (based on the indices 1-25 used) + assert_eq!( + unique_names.len(), + 25, + "Expected 25 unique GasIds, found {}", + unique_names.len() + ); + } +} diff --git a/crates/interpreter/src/instructions.rs b/crates/interpreter/src/instructions.rs index 185b11b6e1..cae338c29f 100644 --- a/crates/interpreter/src/instructions.rs +++ b/crates/interpreter/src/instructions.rs @@ -27,7 +27,9 @@ pub mod tx_info; /// Utility functions and helpers for instruction implementation. pub mod utility; -use crate::{interpreter_types::InterpreterTypes, Host, InstructionContext}; +use primitives::hardfork::SpecId; + +use crate::{gas, interpreter_types::InterpreterTypes, Host, InstructionContext}; /// EVM opcode function signature. #[derive(Debug)] @@ -81,6 +83,51 @@ pub const fn instruction_table() -> [Instructio const { instruction_table_impl::() } } +/// Create a instruction table with applied spec changes to static gas cost. +#[inline] +pub fn instruction_table_gas_changes_spec( + spec: SpecId, +) -> [Instruction; 256] { + use bytecode::opcode::*; + use SpecId::*; + let mut table = instruction_table(); + + if spec.is_enabled_in(TANGERINE) { + // EIP-150: Gas cost changes for IO-heavy operations + table[SLOAD as usize].static_gas = 200; + table[BALANCE as usize].static_gas = 400; + table[EXTCODESIZE as usize].static_gas = 700; + table[EXTCODECOPY as usize].static_gas = 700; + table[CALL as usize].static_gas = 700; + table[CALLCODE as usize].static_gas = 700; + table[DELEGATECALL as usize].static_gas = 700; + table[STATICCALL as usize].static_gas = 700; + table[SELFDESTRUCT as usize].static_gas = 5000; + } + + if spec.is_enabled_in(ISTANBUL) { + // EIP-1884: Repricing for trie-size-dependent opcodes + table[SLOAD as usize].static_gas = gas::ISTANBUL_SLOAD_GAS; + table[BALANCE as usize].static_gas = 700; + table[EXTCODEHASH as usize].static_gas = 700; + } + + if spec.is_enabled_in(BERLIN) { + // warm account cost is base gas that is spend. Additional gas depends if account is cold loaded. + table[SLOAD as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[BALANCE as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[EXTCODESIZE as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[EXTCODEHASH as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[EXTCODECOPY as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[CALL as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[CALLCODE as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[DELEGATECALL as usize].static_gas = gas::WARM_STORAGE_READ_COST; + table[STATICCALL as usize].static_gas = gas::WARM_STORAGE_READ_COST; + } + + table +} + const fn instruction_table_impl() -> [Instruction; 256] { use bytecode::opcode::*; let mut table = [Instruction::unknown(); 256]; @@ -95,7 +142,7 @@ const fn instruction_table_impl() -> [Instructi table[SMOD as usize] = Instruction::new(arithmetic::smod, 5); table[ADDMOD as usize] = Instruction::new(arithmetic::addmod, 8); table[MULMOD as usize] = Instruction::new(arithmetic::mulmod, 8); - table[EXP as usize] = Instruction::new(arithmetic::exp, 0); // dynamic + table[EXP as usize] = Instruction::new(arithmetic::exp, gas::EXP); // base table[SIGNEXTEND as usize] = Instruction::new(arithmetic::signextend, 5); table[LT as usize] = Instruction::new(bitwise::lt, 3); @@ -114,25 +161,25 @@ const fn instruction_table_impl() -> [Instructi table[SAR as usize] = Instruction::new(bitwise::sar, 3); table[CLZ as usize] = Instruction::new(bitwise::clz, 5); - table[KECCAK256 as usize] = Instruction::new(system::keccak256, 0); // dynamic + table[KECCAK256 as usize] = Instruction::new(system::keccak256, gas::KECCAK256); table[ADDRESS as usize] = Instruction::new(system::address, 2); - table[BALANCE as usize] = Instruction::new(host::balance, 0); // dynamic + table[BALANCE as usize] = Instruction::new(host::balance, 20); table[ORIGIN as usize] = Instruction::new(tx_info::origin, 2); table[CALLER as usize] = Instruction::new(system::caller, 2); table[CALLVALUE as usize] = Instruction::new(system::callvalue, 2); table[CALLDATALOAD as usize] = Instruction::new(system::calldataload, 3); table[CALLDATASIZE as usize] = Instruction::new(system::calldatasize, 2); - table[CALLDATACOPY as usize] = Instruction::new(system::calldatacopy, 0); // static 2, mostly dynamic + table[CALLDATACOPY as usize] = Instruction::new(system::calldatacopy, 3); table[CODESIZE as usize] = Instruction::new(system::codesize, 2); - table[CODECOPY as usize] = Instruction::new(system::codecopy, 0); // static 2, mostly dynamic + table[CODECOPY as usize] = Instruction::new(system::codecopy, 3); table[GASPRICE as usize] = Instruction::new(tx_info::gasprice, 2); - table[EXTCODESIZE as usize] = Instruction::new(host::extcodesize, 0); // dynamic - table[EXTCODECOPY as usize] = Instruction::new(host::extcodecopy, 0); // dynamic + table[EXTCODESIZE as usize] = Instruction::new(host::extcodesize, 20); + table[EXTCODECOPY as usize] = Instruction::new(host::extcodecopy, 20); table[RETURNDATASIZE as usize] = Instruction::new(system::returndatasize, 2); - table[RETURNDATACOPY as usize] = Instruction::new(system::returndatacopy, 0); // static 2, mostly dynamic - table[EXTCODEHASH as usize] = Instruction::new(host::extcodehash, 0); // dynamic + table[RETURNDATACOPY as usize] = Instruction::new(system::returndatacopy, 3); + table[EXTCODEHASH as usize] = Instruction::new(host::extcodehash, 400); table[BLOCKHASH as usize] = Instruction::new(host::blockhash, 20); table[COINBASE as usize] = Instruction::new(block_info::coinbase, 2); table[TIMESTAMP as usize] = Instruction::new(block_info::timestamp, 2); @@ -149,8 +196,10 @@ const fn instruction_table_impl() -> [Instructi table[MLOAD as usize] = Instruction::new(memory::mload, 3); table[MSTORE as usize] = Instruction::new(memory::mstore, 3); table[MSTORE8 as usize] = Instruction::new(memory::mstore8, 3); - table[SLOAD as usize] = Instruction::new(host::sload, 0); // dynamic - table[SSTORE as usize] = Instruction::new(host::sstore, 0); // dynamic + table[SLOAD as usize] = Instruction::new(host::sload, 50); + // SSTORE static gas can be found in GasParams as check for minimal stipend + // needs to be done before deduction of static gas. + table[SSTORE as usize] = Instruction::new(host::sstore, 0); table[JUMP as usize] = Instruction::new(control::jump, 8); table[JUMPI as usize] = Instruction::new(control::jumpi, 10); table[PC as usize] = Instruction::new(control::pc, 2); @@ -159,7 +208,7 @@ const fn instruction_table_impl() -> [Instructi table[JUMPDEST as usize] = Instruction::new(control::jumpdest, 1); table[TLOAD as usize] = Instruction::new(host::tload, 100); table[TSTORE as usize] = Instruction::new(host::tstore, 100); - table[MCOPY as usize] = Instruction::new(memory::mcopy, 0); // static 2, mostly dynamic + table[MCOPY as usize] = Instruction::new(memory::mcopy, 3); // static 2, mostly dynamic table[PUSH0 as usize] = Instruction::new(stack::push0, 2); table[PUSH1 as usize] = Instruction::new(stack::push::<1, _, _>, 3); @@ -229,23 +278,23 @@ const fn instruction_table_impl() -> [Instructi table[SWAP15 as usize] = Instruction::new(stack::swap::<15, _, _>, 3); table[SWAP16 as usize] = Instruction::new(stack::swap::<16, _, _>, 3); - table[LOG0 as usize] = Instruction::new(host::log::<0, _>, 0); // dynamic - table[LOG1 as usize] = Instruction::new(host::log::<1, _>, 0); // dynamic - table[LOG2 as usize] = Instruction::new(host::log::<2, _>, 0); // dynamic - table[LOG3 as usize] = Instruction::new(host::log::<3, _>, 0); // dynamic - table[LOG4 as usize] = Instruction::new(host::log::<4, _>, 0); // dynamic + table[LOG0 as usize] = Instruction::new(host::log::<0, _>, gas::LOG); + table[LOG1 as usize] = Instruction::new(host::log::<1, _>, gas::LOG); + table[LOG2 as usize] = Instruction::new(host::log::<2, _>, gas::LOG); + table[LOG3 as usize] = Instruction::new(host::log::<3, _>, gas::LOG); + table[LOG4 as usize] = Instruction::new(host::log::<4, _>, gas::LOG); - table[CREATE as usize] = Instruction::new(contract::create::<_, false, _>, 0); // dynamic - table[CALL as usize] = Instruction::new(contract::call, 0); // dynamic - table[CALLCODE as usize] = Instruction::new(contract::call_code, 0); // dynamic + table[CREATE as usize] = Instruction::new(contract::create::<_, false, _>, 0); + table[CALL as usize] = Instruction::new(contract::call, 40); + table[CALLCODE as usize] = Instruction::new(contract::call_code, 40); table[RETURN as usize] = Instruction::new(control::ret, 0); - table[DELEGATECALL as usize] = Instruction::new(contract::delegate_call, 0); // dynamic - table[CREATE2 as usize] = Instruction::new(contract::create::<_, true, _>, 0); // dynamic + table[DELEGATECALL as usize] = Instruction::new(contract::delegate_call, 40); + table[CREATE2 as usize] = Instruction::new(contract::create::<_, true, _>, 0); - table[STATICCALL as usize] = Instruction::new(contract::static_call, 0); // dynamic + table[STATICCALL as usize] = Instruction::new(contract::static_call, 40); table[REVERT as usize] = Instruction::new(control::revert, 0); table[INVALID as usize] = Instruction::new(control::invalid, 0); - table[SELFDESTRUCT as usize] = Instruction::new(host::selfdestruct, 0); // dynamic + table[SELFDESTRUCT as usize] = Instruction::new(host::selfdestruct, 0); table } diff --git a/crates/interpreter/src/instructions/arithmetic.rs b/crates/interpreter/src/instructions/arithmetic.rs index 68333c9385..024938ad8d 100644 --- a/crates/interpreter/src/instructions/arithmetic.rs +++ b/crates/interpreter/src/instructions/arithmetic.rs @@ -1,35 +1,30 @@ use super::i256::{i256_div, i256_mod}; use crate::{ - gas, - interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr}, + interpreter_types::{InterpreterTypes, StackTr}, InstructionContext, }; use primitives::U256; /// Implements the ADD instruction - adds two values from stack. pub fn add(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = op1.wrapping_add(*op2); } /// Implements the MUL instruction - multiplies two values from stack. pub fn mul(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); *op2 = op1.wrapping_mul(*op2); } /// Implements the SUB instruction - subtracts two values from stack. pub fn sub(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = op1.wrapping_sub(*op2); } /// Implements the DIV instruction - divides two values from stack. pub fn div(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); if !op2.is_zero() { *op2 = op1.wrapping_div(*op2); @@ -40,7 +35,6 @@ pub fn div(context: InstructionContext<'_, H, /// /// Performs signed division of two values from stack. pub fn sdiv(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); *op2 = i256_div(op1, *op2); } @@ -49,7 +43,6 @@ pub fn sdiv(context: InstructionContext<'_, H /// /// Pops two values from stack and pushes the remainder of their division. pub fn rem(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); if !op2.is_zero() { *op2 = op1.wrapping_rem(*op2); @@ -60,7 +53,6 @@ pub fn rem(context: InstructionContext<'_, H, /// /// Performs signed modulo of two values from stack. pub fn smod(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); *op2 = i256_mod(op1, *op2) } @@ -69,7 +61,6 @@ pub fn smod(context: InstructionContext<'_, H /// /// Pops three values from stack and pushes (a + b) % n. pub fn addmod(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::MID); popn_top!([op1, op2], op3, context.interpreter); *op3 = op1.add_mod(op2, *op3) } @@ -78,16 +69,17 @@ pub fn addmod(context: InstructionContext<'_, /// /// Pops three values from stack and pushes (a * b) % n. pub fn mulmod(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::MID); popn_top!([op1, op2], op3, context.interpreter); *op3 = op1.mul_mod(op2, *op3) } /// Implements the EXP instruction - exponentiates two values from stack. pub fn exp(context: InstructionContext<'_, H, WIRE>) { - let spec_id = context.interpreter.runtime_flag.spec_id(); popn_top!([op1], op2, context.interpreter); - gas_or_fail!(context.interpreter, gas::exp_cost(spec_id, *op2)); + gas!( + context.interpreter, + context.interpreter.gas_params.exp_cost(*op2) + ); *op2 = op1.pow(*op2); } @@ -121,7 +113,6 @@ pub fn exp(context: InstructionContext<'_, H, /// Similarly, if `b == 0` then the yellow paper says the output should start with all zeros, /// then end with bits from `b`; this is equal to `y & mask` where `&` is bitwise `AND`. pub fn signextend(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::LOW); popn_top!([ext], x, context.interpreter); // For 31 we also don't need to do anything. if ext < U256::from(31) { diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index d07f7638e1..170fbe56bd 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -8,25 +8,20 @@ use primitives::U256; /// Implements the LT instruction - less than comparison. pub fn lt(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = U256::from(op1 < *op2); } /// Implements the GT instruction - greater than comparison. pub fn gt(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - *op2 = U256::from(op1 > *op2); } /// Implements the CLZ instruction - count leading zeros. pub fn clz(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, OSAKA); - //gas!(context.interpreter, gas::LOW); popn_top!([], op1, context.interpreter); - let leading_zeros = op1.leading_zeros(); *op1 = U256::from(leading_zeros); } @@ -35,9 +30,7 @@ pub fn clz(context: InstructionContext<'_, H, /// /// Signed less than comparison of two values from stack. pub fn slt(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less); } @@ -45,9 +38,7 @@ pub fn slt(context: InstructionContext<'_, H, /// /// Signed greater than comparison of two values from stack. pub fn sgt(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater); } @@ -55,9 +46,7 @@ pub fn sgt(context: InstructionContext<'_, H, /// /// Equality comparison of two values from stack. pub fn eq(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - *op2 = U256::from(op1 == *op2); } @@ -65,7 +54,6 @@ pub fn eq(context: InstructionContext<'_, H, /// /// Checks if the top stack value is zero. pub fn iszero(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([], op1, context.interpreter); *op1 = U256::from(op1.is_zero()); } @@ -74,7 +62,6 @@ pub fn iszero(context: InstructionContext<'_, /// /// Bitwise AND of two values from stack. pub fn bitand(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = op1 & *op2; } @@ -83,9 +70,7 @@ pub fn bitand(context: InstructionContext<'_, /// /// Bitwise OR of two values from stack. pub fn bitor(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - *op2 = op1 | *op2; } @@ -93,9 +78,7 @@ pub fn bitor(context: InstructionContext<'_, /// /// Bitwise XOR of two values from stack. pub fn bitxor(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - *op2 = op1 ^ *op2; } @@ -103,9 +86,7 @@ pub fn bitxor(context: InstructionContext<'_, /// /// Bitwise NOT (negation) of the top stack value. pub fn not(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([], op1, context.interpreter); - *op1 = !*op1; } @@ -113,9 +94,7 @@ pub fn not(context: InstructionContext<'_, H, /// /// Extracts a single byte from a word at a given index. pub fn byte(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - let o1 = as_usize_saturated!(op1); *op2 = if o1 < 32 { // `31 - o1` because `byte` returns LE, while we want BE @@ -128,9 +107,7 @@ pub fn byte(context: InstructionContext<'_, H /// EIP-145: Bitwise shifting instructions in EVM pub fn shl(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, CONSTANTINOPLE); - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - let shift = as_usize_saturated!(op1); *op2 = if shift < 256 { *op2 << shift @@ -142,9 +119,7 @@ pub fn shl(context: InstructionContext<'_, H, /// EIP-145: Bitwise shifting instructions in EVM pub fn shr(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, CONSTANTINOPLE); - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - let shift = as_usize_saturated!(op1); *op2 = if shift < 256 { *op2 >> shift @@ -156,9 +131,7 @@ pub fn shr(context: InstructionContext<'_, H, /// EIP-145: Bitwise shifting instructions in EVM pub fn sar(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, CONSTANTINOPLE); - //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); - let shift = as_usize_saturated!(op1); *op2 = if shift < 256 { op2.arithmetic_shr(shift) diff --git a/crates/interpreter/src/instructions/block_info.rs b/crates/interpreter/src/instructions/block_info.rs index fa2c118c7a..8956d55378 100644 --- a/crates/interpreter/src/instructions/block_info.rs +++ b/crates/interpreter/src/instructions/block_info.rs @@ -9,7 +9,6 @@ use crate::InstructionContext; /// EIP-1344: ChainID opcode pub fn chainid(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, ISTANBUL); - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.chain_id()); } @@ -19,7 +18,6 @@ pub fn chainid(context: InstructionCon pub fn coinbase( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context.host.beneficiary().into_word().into() @@ -32,7 +30,6 @@ pub fn coinbase( pub fn timestamp( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.timestamp()); } @@ -42,7 +39,6 @@ pub fn timestamp( pub fn block_number( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.block_number()); } @@ -52,7 +48,6 @@ pub fn block_number( pub fn difficulty( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BASE); if context .interpreter .runtime_flag @@ -72,14 +67,12 @@ pub fn difficulty( pub fn gaslimit( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.gas_limit()); } /// EIP-3198: BASEFEE opcode pub fn basefee(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, LONDON); - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.basefee()); } @@ -88,6 +81,5 @@ pub fn blob_basefee( context: InstructionContext<'_, H, WIRE>, ) { check!(context.interpreter, CANCUN); - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.blob_gasprice()); } diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 4a360c7350..1fea5f1275 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -2,7 +2,7 @@ mod call_helpers; pub use call_helpers::{ get_memory_input_and_out_ranges, load_acc_and_calc_gas, load_account_delegated, - load_account_delegated_handle_error, new_account_cost, resize_memory, + load_account_delegated_handle_error, resize_memory, }; use crate::{ @@ -51,11 +51,15 @@ pub fn create( .halt(InstructionResult::CreateInitCodeSizeLimit); return; } - gas!(context.interpreter, gas::initcode_cost(len)); + gas!( + context.interpreter, + context.interpreter.gas_params.initcode_cost(len) + ); } let code_offset = as_usize_or_fail!(context.interpreter, code_offset); resize_memory!(context.interpreter, code_offset, len); + code = Bytes::copy_from_slice( context .interpreter @@ -69,10 +73,16 @@ pub fn create( let scheme = if IS_CREATE2 { popn!([salt], context.interpreter); // SAFETY: `len` is reasonable in size as gas for it is already deducted. - gas_or_fail!(context.interpreter, gas::create2_cost(len)); + gas!( + context.interpreter, + context.interpreter.gas_params.create2_cost(len) + ); CreateScheme::Create2 { salt } } else { - gas!(context.interpreter, gas::CREATE); + gas!( + context.interpreter, + context.interpreter.gas_params.create_cost() + ); CreateScheme::Create }; @@ -86,7 +96,10 @@ pub fn create( .is_enabled_in(SpecId::TANGERINE) { // Take remaining gas and deduce l64 part of it. - gas_limit -= gas_limit / 64 + gas_limit = context + .interpreter + .gas_params + .call_stipend_reduction(gas_limit); } gas!(context.interpreter, gas_limit); @@ -123,10 +136,12 @@ pub fn call( .halt(InstructionResult::CallNotAllowedInsideStatic); return; } + let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter) else { return; }; + let Some((gas_limit, bytecode, bytecode_hash)) = load_acc_and_calc_gas(&mut context, to, has_transfer, true, local_gas_limit) else { diff --git a/crates/interpreter/src/instructions/contract/call_helpers.rs b/crates/interpreter/src/instructions/contract/call_helpers.rs index 88163bea09..f58ad3ae7a 100644 --- a/crates/interpreter/src/instructions/contract/call_helpers.rs +++ b/crates/interpreter/src/instructions/contract/call_helpers.rs @@ -1,8 +1,5 @@ use crate::{ - gas::{ - self, calc_call_static_gas, COLD_ACCOUNT_ACCESS_COST_ADDITIONAL, NEWACCOUNT, - WARM_STORAGE_READ_COST, - }, + gas::params::GasParams, interpreter::Interpreter, interpreter_types::{InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}, InstructionContext, @@ -61,10 +58,14 @@ pub fn load_acc_and_calc_gas( create_empty_account: bool, stack_gas_limit: u64, ) -> Option<(u64, Bytecode, B256)> { - let spec = context.interpreter.runtime_flag.spec_id(); - // calculate static gas first. For berlin hardfork it will take warm gas. - let static_gas = calc_call_static_gas(spec, transfers_value); - gas!(context.interpreter, static_gas, None); + // Transfer value cost + if transfers_value { + gas!( + context.interpreter, + context.interpreter.gas_params.transfer_value_cost(), + None + ); + } // load account delegated and deduct dynamic gas. let (gas, bytecode, code_hash) = @@ -74,18 +75,23 @@ pub fn load_acc_and_calc_gas( // deduct dynamic gas. gas!(interpreter, gas, None); + let interpreter = &mut context.interpreter; + // EIP-150: Gas cost changes for IO-heavy operations let mut gas_limit = if interpreter.runtime_flag.spec_id().is_enabled_in(TANGERINE) { - // Take l64 part of gas_limit - min(interpreter.gas.remaining_63_of_64_parts(), stack_gas_limit) + // On mainnet this will take return 63/64 of gas_limit. + let reduced_gas_limit = interpreter + .gas_params + .call_stipend_reduction(interpreter.gas.remaining()); + min(reduced_gas_limit, stack_gas_limit) } else { stack_gas_limit }; - gas!(interpreter, gas_limit, None); + // Add call stipend if there is value to be transferred. if transfers_value { - gas_limit = gas_limit.saturating_add(gas::CALL_STIPEND); + gas_limit = gas_limit.saturating_add(interpreter.gas_params.call_stipend()); } Some((gas_limit, bytecode, code_hash)) @@ -101,8 +107,10 @@ pub fn load_account_delegated_handle_error( ) -> Option<(u64, Bytecode, B256)> { // move this to static gas. let remaining_gas = context.interpreter.gas.remaining(); + let gas_table = &context.interpreter.gas_params; match load_account_delegated( context.host, + gas_table, context.interpreter.runtime_flag.spec_id(), remaining_gas, to, @@ -126,6 +134,7 @@ pub fn load_account_delegated_handle_error( #[inline] pub fn load_account_delegated( host: &mut H, + gas_table: &GasParams, spec: SpecId, remaining_gas: u64, address: Address, @@ -136,35 +145,37 @@ pub fn load_account_delegated( let is_berlin = spec.is_enabled_in(SpecId::BERLIN); let is_spurious_dragon = spec.is_enabled_in(SpecId::SPURIOUS_DRAGON); - let skip_cold_load = is_berlin && remaining_gas < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + let additional_cold_cost = gas_table.cold_account_additional_cost(); + + let skip_cold_load = is_berlin && remaining_gas < additional_cold_cost; let account = host.load_account_info_skip_cold_load(address, true, skip_cold_load)?; if is_berlin && account.is_cold { - cost += COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + cost += additional_cold_cost; } let mut bytecode = account.code.clone().unwrap_or_default(); let mut code_hash = account.code_hash(); // New account cost, as account is empty there is no delegated account and we can return early. if create_empty_account && account.is_empty { - cost += new_account_cost(is_spurious_dragon, transfers_value); + cost += gas_table.new_account_cost(is_spurious_dragon, transfers_value); return Ok((cost, bytecode, code_hash)); } // load delegate code if account is EIP-7702 if let Some(Bytecode::Eip7702(code)) = &account.code { // EIP-7702 is enabled after berlin hardfork. - cost += WARM_STORAGE_READ_COST; + cost += gas_table.warm_storage_read_cost(); if cost > remaining_gas { return Err(LoadError::ColdLoadSkipped); } let address = code.address(); // skip cold load if there is enough gas to cover the cost. - let skip_cold_load = remaining_gas < cost + COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + let skip_cold_load = remaining_gas < cost + additional_cold_cost; let delegate_account = host.load_account_info_skip_cold_load(address, true, skip_cold_load)?; if delegate_account.is_cold { - cost += COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + cost += additional_cold_cost; } bytecode = delegate_account.code.clone().unwrap_or_default(); code_hash = delegate_account.code_hash(); @@ -172,15 +183,3 @@ pub fn load_account_delegated( Ok((cost, bytecode, code_hash)) } - -/// Returns new account cost. -#[inline] -pub fn new_account_cost(is_spurious_dragon: bool, transfers_value: bool) -> u64 { - // EIP-161: State trie clearing (invariant-preserving alternative) - // Pre-Spurious Dragon: always charge for new account - // Post-Spurious Dragon: only charge if value is transferred - if !is_spurious_dragon || transfers_value { - return NEWACCOUNT; - } - 0 -} diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 66224360c4..32ff53ca81 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -11,7 +11,6 @@ use crate::InstructionContext; /// /// Unconditional jump to a valid destination. pub fn jump(context: InstructionContext<'_, H, ITy>) { - //gas!(context.interpreter, gas::MID); popn!([target], context.interpreter); jump_inner(context.interpreter, target); } @@ -20,9 +19,7 @@ pub fn jump(context: InstructionContext<'_, H, /// /// Conditional jump to a valid destination if condition is true. pub fn jumpi(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::HIGH); popn!([target, cond], context.interpreter); - if !cond.is_zero() { jump_inner(context.interpreter, target); } @@ -45,15 +42,12 @@ fn jump_inner(interpreter: &mut Interpreter, targe /// Implements the JUMPDEST instruction. /// /// Marks a valid destination for jump operations. -pub fn jumpdest(_context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::JUMPDEST); -} +pub fn jumpdest(_context: InstructionContext<'_, H, WIRE>) {} /// Implements the PC instruction. /// /// Pushes the current program counter onto the stack. pub fn pc(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); // - 1 because we have already advanced the instruction pointer in `Interpreter::step` push!( context.interpreter, @@ -69,15 +63,15 @@ fn return_inner( interpreter: &mut Interpreter, instruction_result: InstructionResult, ) { - // Zero gas cost - // //gas!(interpreter, gas::ZERO) popn!([offset, len], interpreter); let len = as_usize_or_fail!(interpreter, len); // Important: Offset must be ignored if len is zeros let mut output = Bytes::default(); if len != 0 { let offset = as_usize_or_fail!(interpreter, offset); - resize_memory!(interpreter, offset, len); + if !interpreter.resize_memory(offset, len) { + return; + } output = interpreter.memory.slice_len(offset, len).to_vec().into() } diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index e9d1c3645f..7324c39802 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -1,16 +1,14 @@ use crate::{ - gas::{ - self, selfdestruct_cold_beneficiary_cost, CALL_STIPEND, - COLD_ACCOUNT_ACCESS_COST_ADDITIONAL, COLD_SLOAD_COST_ADDITIONAL, ISTANBUL_SLOAD_GAS, - WARM_STORAGE_READ_COST, - }, instructions::utility::{IntoAddress, IntoU256}, interpreter_types::{InputsTr, InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}, Host, InstructionResult, }; use context_interface::host::LoadError; use core::cmp::min; -use primitives::{hardfork::SpecId::*, Bytes, Log, LogData, B256, BLOCK_HASH_HISTORY, U256}; +use primitives::{ + hardfork::SpecId::{self, *}, + Bytes, Log, LogData, B256, BLOCK_HASH_HISTORY, U256, +}; use crate::InstructionContext; @@ -25,15 +23,6 @@ pub fn balance(context: InstructionCon let account = berlin_load_account!(context, address, false); *top = account.balance; } else { - let gas = if spec_id.is_enabled_in(ISTANBUL) { - // EIP-1884: Repricing for trie-size-dependent opcodes - 700 - } else if spec_id.is_enabled_in(TANGERINE) { - 400 - } else { - 20 - }; - gas!(context.interpreter, gas); let Ok(account) = context .host .load_account_info_skip_cold_load(address, false, false) @@ -49,7 +38,6 @@ pub fn selfbalance( context: InstructionContext<'_, H, WIRE>, ) { check!(context.interpreter, ISTANBUL); - //gas!(context.interpreter, gas::LOW); let Some(balance) = context .host @@ -68,18 +56,13 @@ pub fn extcodesize( ) { popn_top!([], top, context.interpreter); let address = top.into_address(); + let spec_id = context.interpreter.runtime_flag.spec_id(); if spec_id.is_enabled_in(BERLIN) { let account = berlin_load_account!(context, address, true); // safe to unwrap because we are loading code *top = U256::from(account.code.as_ref().unwrap().len()); } else { - let gas = if spec_id.is_enabled_in(TANGERINE) { - 700 - } else { - 20 - }; - gas!(context.interpreter, gas); let Ok(account) = context .host .load_account_info_skip_cold_load(address, true, false) @@ -103,12 +86,6 @@ pub fn extcodehash( let account = if spec_id.is_enabled_in(BERLIN) { berlin_load_account!(context, address, true) } else { - let gas = if spec_id.is_enabled_in(ISTANBUL) { - 700 - } else { - 400 - }; - gas!(context.interpreter, gas); let Ok(account) = context .host .load_account_info_skip_cold_load(address, true, false) @@ -143,7 +120,7 @@ pub fn extcodecopy( let len = as_usize_or_fail!(context.interpreter, len_u256); gas!( context.interpreter, - gas::copy_cost(0, len).unwrap_or(u64::MAX) + context.interpreter.gas_params.extcodecopy(len) ); let mut memory_offset_usize = 0; @@ -151,6 +128,7 @@ pub fn extcodecopy( if len != 0 { // fail on casting of memory_offset only if len is not zero. memory_offset_usize = as_usize_or_fail!(context.interpreter, memory_offset); + // Resize memory to fit the code resize_memory!(context.interpreter, memory_offset_usize, len); } @@ -158,13 +136,6 @@ pub fn extcodecopy( let account = berlin_load_account!(context, address, true); account.code.as_ref().unwrap().original_bytes() } else { - let gas = if spec_id.is_enabled_in(TANGERINE) { - 700 - } else { - 20 - }; - gas!(context.interpreter, gas); - let Some(code) = context.host.load_account_code(address) else { return context.interpreter.halt_fatal(); }; @@ -187,7 +158,6 @@ pub fn extcodecopy( pub fn blockhash( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BLOCKHASH); popn_top!([], number, context.interpreter); let requested_number = *number; @@ -224,26 +194,17 @@ pub fn sload(context: InstructionConte let spec_id = context.interpreter.runtime_flag.spec_id(); let target = context.interpreter.input.target_address(); - // `SLOAD` opcode cost calculation. - let gas = if spec_id.is_enabled_in(BERLIN) { - WARM_STORAGE_READ_COST - } else if spec_id.is_enabled_in(ISTANBUL) { - // EIP-1884: Repricing for trie-size-dependent opcodes - ISTANBUL_SLOAD_GAS - } else if spec_id.is_enabled_in(TANGERINE) { - // EIP-150: Gas cost changes for IO-heavy operations - 200 - } else { - 50 - }; - gas!(context.interpreter, gas); if spec_id.is_enabled_in(BERLIN) { - let skip_cold = context.interpreter.gas.remaining() < COLD_SLOAD_COST_ADDITIONAL; + let additional_cold_cost = context + .interpreter + .gas_params + .cold_storage_additional_cost(); + let skip_cold = context.interpreter.gas.remaining() < additional_cold_cost; let res = context.host.sload_skip_cold_load(target, *index, skip_cold); match res { Ok(storage) => { if storage.is_cold { - gas!(context.interpreter, COLD_SLOAD_COST_ADDITIONAL); + gas!(context.interpreter, additional_cold_cost); } *index = storage.data; @@ -269,13 +230,10 @@ pub fn sstore(context: InstructionCont let target = context.interpreter.input.target_address(); let spec_id = context.interpreter.runtime_flag.spec_id(); - // EIP-1706 Disable SSTORE with gasleft lower than call stipend - if context - .interpreter - .runtime_flag - .spec_id() - .is_enabled_in(ISTANBUL) - && context.interpreter.gas.remaining() <= CALL_STIPEND + // EIP-2200: Structured Definitions for Net Gas Metering + // If gasleft is less than or equal to gas stipend, fail the current call frame with ‘out of gas’ exception. + if spec_id.is_enabled_in(ISTANBUL) + && context.interpreter.gas.remaining() <= context.interpreter.gas_params.call_stipend() { context .interpreter @@ -283,14 +241,17 @@ pub fn sstore(context: InstructionCont return; } - // static gas gas!( context.interpreter, - gas::static_sstore_cost(context.interpreter.runtime_flag.spec_id()) + context.interpreter.gas_params.sstore_static_gas() ); let state_load = if spec_id.is_enabled_in(BERLIN) { - let skip_cold = context.interpreter.gas.remaining() < COLD_SLOAD_COST_ADDITIONAL; + let additional_cold_cost = context + .interpreter + .gas_params + .cold_storage_additional_cost(); + let skip_cold = context.interpreter.gas.remaining() < additional_cold_cost; let res = context .host .sstore_skip_cold_load(target, index, value, skip_cold); @@ -306,21 +267,25 @@ pub fn sstore(context: InstructionCont load }; + let is_istanbul = spec_id.is_enabled_in(ISTANBUL); + // dynamic gas gas!( context.interpreter, - gas::dyn_sstore_cost( - context.interpreter.runtime_flag.spec_id(), + context.interpreter.gas_params.sstore_dynamic_gas( + is_istanbul, &state_load.data, state_load.is_cold ) ); // refund - context.interpreter.gas.record_refund(gas::sstore_refund( - context.interpreter.runtime_flag.spec_id(), - &state_load.data, - )); + context.interpreter.gas.record_refund( + context + .interpreter + .gas_params + .sstore_refund(is_istanbul, &state_load.data), + ); } /// EIP-1153: Transient storage opcodes @@ -328,8 +293,6 @@ pub fn sstore(context: InstructionCont pub fn tstore(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, CANCUN); require_non_staticcall!(context.interpreter); - //gas!(context.interpreter, gas::WARM_STORAGE_READ_COST); - popn!([index, value], context.interpreter); context @@ -341,8 +304,6 @@ pub fn tstore(context: InstructionCont /// Load value from transient storage pub fn tload(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, CANCUN); - //gas!(context.interpreter, gas::WARM_STORAGE_READ_COST); - popn_top!([], index, context.interpreter); *index = context @@ -360,11 +321,15 @@ pub fn log( popn!([offset, len], context.interpreter); let len = as_usize_or_fail!(context.interpreter, len); - gas_or_fail!(context.interpreter, gas::log_cost(N as u8, len as u64)); + gas!( + context.interpreter, + context.interpreter.gas_params.log_cost(N as u8, len as u64) + ); let data = if len == 0 { Bytes::new() } else { let offset = as_usize_or_fail!(context.interpreter, offset); + // Resize memory to fit the data resize_memory!(context.interpreter, offset, len); Bytes::copy_from_slice(context.interpreter.memory.slice_len(offset, len).as_ref()) }; @@ -393,34 +358,42 @@ pub fn selfdestruct( let target = target.into_address(); let spec = context.interpreter.runtime_flag.spec_id(); - // static gas - gas!(context.interpreter, gas::static_selfdestruct_cost(spec)); + let cold_load_gas = context + .interpreter + .gas_params + .cold_account_additional_cost(); - let skip_cold = context.interpreter.gas.remaining() < selfdestruct_cold_beneficiary_cost(spec); + let skip_cold_load = context.interpreter.gas.remaining() < cold_load_gas; let res = match context.host.selfdestruct( context.interpreter.input.target_address(), target, - skip_cold, + skip_cold_load, ) { Ok(res) => res, Err(LoadError::ColdLoadSkipped) => return context.interpreter.halt_oog(), Err(LoadError::DBError) => return context.interpreter.halt_fatal(), }; - gas!(context.interpreter, gas::dyn_selfdestruct_cost(spec, &res)); + // EIP-161: State trie clearing (invariant-preserving alternative) + let should_charge_topup = if spec.is_enabled_in(SpecId::SPURIOUS_DRAGON) { + res.had_value && !res.target_exists + } else { + !res.target_exists + }; + + gas!( + context.interpreter, + context + .interpreter + .gas_params + .selfdestruct_cost(should_charge_topup, res.is_cold) + ); - // EIP-3529: Reduction in refunds - if !context - .interpreter - .runtime_flag - .spec_id() - .is_enabled_in(LONDON) - && !res.previously_destroyed - { + if !res.previously_destroyed { context .interpreter .gas - .record_refund(gas::SELFDESTRUCT_REFUND); + .record_refund(context.interpreter.gas_params.selfdestruct_refund()); } context.interpreter.halt(InstructionResult::SelfDestruct); diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 791400643f..30e30fd949 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -1,17 +1,5 @@ //! Utility macros to help implementing opcode instruction functions. -/// `const` Option `?`. -#[macro_export] -#[collapse_debuginfo(yes)] -macro_rules! tri { - ($e:expr) => { - match $e { - Some(v) => v, - None => return None, - } - }; -} - /// Fails the instruction if the current call is static. #[macro_export] #[collapse_debuginfo(yes)] @@ -24,23 +12,6 @@ macro_rules! require_non_staticcall { }; } -/// Macro for optional try - returns early if the expression evaluates to None. -/// Similar to the `?` operator but for use in instruction implementations. -#[macro_export] -#[collapse_debuginfo(yes)] -#[deprecated( - since = "29.0.0", - note = "Prefer `let Some(x) = expr else { return; };` for early return in instruction functions" -)] -macro_rules! otry { - ($expression: expr) => {{ - let Some(value) = $expression else { - return; - }; - value - }}; -} - /// Check if the `SPEC` is enabled, and fail the instruction if it is not. #[macro_export] #[collapse_debuginfo(yes)] @@ -80,20 +51,18 @@ macro_rules! berlin_load_account { $crate::berlin_load_account!($context, $address, $load_code, ()) }; ($context:expr, $address:expr, $load_code:expr, $ret:expr) => {{ - $crate::gas!($context.interpreter, WARM_STORAGE_READ_COST, $ret); - let skip_cold_load = - $context.interpreter.gas.remaining() < COLD_ACCOUNT_ACCESS_COST_ADDITIONAL; + let cold_load_gas = $context + .interpreter + .gas_params + .cold_account_additional_cost(); + let skip_cold_load = $context.interpreter.gas.remaining() < cold_load_gas; match $context .host .load_account_info_skip_cold_load($address, $load_code, skip_cold_load) { Ok(account) => { if account.is_cold { - $crate::gas!( - $context.interpreter, - COLD_ACCOUNT_ACCESS_COST_ADDITIONAL, - $ret - ); + $crate::gas!($context.interpreter, cold_load_gas, $ret); } account } @@ -109,24 +78,6 @@ macro_rules! berlin_load_account { }}; } -/// Same as [`gas!`], but with `gas` as an option. -#[macro_export] -#[collapse_debuginfo(yes)] -macro_rules! gas_or_fail { - ($interpreter:expr, $gas:expr) => { - $crate::gas_or_fail!($interpreter, $gas, ()) - }; - ($interpreter:expr, $gas:expr, $ret:expr) => { - match $gas { - Some(gas_used) => $crate::gas!($interpreter, gas_used, $ret), - None => { - $interpreter.halt_oog(); - return $ret; - } - } - }; -} - /// Resizes the interpreter memory if necessary. Fails the instruction if the memory or gas limit /// is exceeded. #[macro_export] @@ -136,18 +87,14 @@ macro_rules! resize_memory { $crate::resize_memory!($interpreter, $offset, $len, ()) }; ($interpreter:expr, $offset:expr, $len:expr, $ret:expr) => { - #[cfg(feature = "memory_limit")] - if $interpreter.memory.limit_reached($offset, $len) { - $interpreter.halt_memory_limit_oog(); - return $ret; - } - if !$crate::interpreter::resize_memory( + if let Err(result) = $crate::interpreter::resize_memory( &mut $interpreter.gas, &mut $interpreter.memory, + &$interpreter.gas_params, $offset, $len, ) { - $interpreter.halt_memory_oog(); + $interpreter.halt(result); return $ret; } }; diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index 9a48d88f3d..8c6b6acc1d 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -11,7 +11,6 @@ use crate::InstructionContext; /// /// Loads a 32-byte word from memory. pub fn mload(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([], top, context.interpreter); let offset = as_usize_or_fail!(context.interpreter, top); resize_memory!(context.interpreter, offset, 32); @@ -23,7 +22,6 @@ pub fn mload(context: InstructionContext<'_, /// /// Stores a 32-byte word to memory. pub fn mstore(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn!([offset, value], context.interpreter); let offset = as_usize_or_fail!(context.interpreter, offset); resize_memory!(context.interpreter, offset, 32); @@ -37,7 +35,6 @@ pub fn mstore(context: InstructionContext<'_, /// /// Stores a single byte to memory. pub fn mstore8(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn!([offset, value], context.interpreter); let offset = as_usize_or_fail!(context.interpreter, offset); resize_memory!(context.interpreter, offset, 1); @@ -48,7 +45,6 @@ pub fn mstore8(context: InstructionContext<'_ /// /// Gets the size of active memory in bytes. pub fn msize(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.memory.size()) @@ -65,7 +61,11 @@ pub fn mcopy(context: InstructionContext<'_, // Into usize or fail let len = as_usize_or_fail!(context.interpreter, len); // Deduce gas - gas_or_fail!(context.interpreter, gas::copy_cost_verylow(len)); + gas!( + context.interpreter, + context.interpreter.gas_params.mcopy_cost(len) + ); + if len == 0 { return; } diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index 822e6240d7..f2fb7f4cba 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -10,7 +10,6 @@ use crate::InstructionContext; /// /// Removes the top item from the stack. pub fn pop(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); // Can ignore return. as relative N jump is safe operation. popn!([_i], context.interpreter); } @@ -20,7 +19,6 @@ pub fn pop(context: InstructionContext<'_, H, /// Introduce a new instruction which pushes the constant value 0 onto the stack. pub fn push0(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, SHANGHAI); - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, U256::ZERO); } @@ -30,8 +28,6 @@ pub fn push0(context: InstructionContext<'_, pub fn push( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::VERYLOW); - let slice = context.interpreter.bytecode.read_slice(N); if !context.interpreter.stack.push_slice(slice) { context.interpreter.halt(InstructionResult::StackOverflow); @@ -48,7 +44,6 @@ pub fn push( pub fn dup( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::VERYLOW); if !context.interpreter.stack.dup(N) { context.interpreter.halt(InstructionResult::StackOverflow); } @@ -60,7 +55,6 @@ pub fn dup( pub fn swap( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::VERYLOW); assert!(N != 0); if !context.interpreter.stack.exchange(0, N) { context.interpreter.halt(InstructionResult::StackOverflow); diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 0bea684e7f..cf6f7e2f76 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -17,7 +17,10 @@ use crate::InstructionContext; pub fn keccak256(context: InstructionContext<'_, H, WIRE>) { popn_top!([offset], top, context.interpreter); let len = as_usize_or_fail!(context.interpreter, top); - gas_or_fail!(context.interpreter, gas::keccak256_cost(len)); + gas!( + context.interpreter, + context.interpreter.gas_params.keccak256_cost(len) + ); let hash = if len == 0 { KECCAK_EMPTY } else { @@ -32,7 +35,6 @@ pub fn keccak256(context: InstructionContext< /// /// Pushes the current contract's address onto the stack. pub fn address(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context @@ -48,7 +50,6 @@ pub fn address(context: InstructionContext<'_ /// /// Pushes the caller's address onto the stack. pub fn caller(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context @@ -64,7 +65,6 @@ pub fn caller(context: InstructionContext<'_, /// /// Pushes the size of running contract's bytecode onto the stack. pub fn codesize(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.bytecode.bytecode_len()) @@ -77,7 +77,8 @@ pub fn codesize(context: InstructionContext<' pub fn codecopy(context: InstructionContext<'_, H, WIRE>) { popn!([memory_offset, code_offset, len], context.interpreter); let len = as_usize_or_fail!(context.interpreter, len); - let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else { + let Some(memory_offset) = copy_cost_and_memory_resize(context.interpreter, memory_offset, len) + else { return; }; let code_offset = as_usize_saturated!(code_offset); @@ -95,7 +96,6 @@ pub fn codecopy(context: InstructionContext<' /// /// Loads 32 bytes of input data from the specified offset. pub fn calldataload(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::VERYLOW); popn_top!([], offset_ptr, context.interpreter); let mut word = B256::ZERO; let offset = as_usize_saturated!(offset_ptr); @@ -133,7 +133,6 @@ pub fn calldataload(context: InstructionConte /// /// Pushes the size of input data onto the stack. pub fn calldatasize(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.input.input().len()) @@ -144,7 +143,6 @@ pub fn calldatasize(context: InstructionConte /// /// Pushes the value sent with the current call onto the stack. pub fn callvalue(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.interpreter.input.call_value()); } @@ -154,7 +152,8 @@ pub fn callvalue(context: InstructionContext< pub fn calldatacopy(context: InstructionContext<'_, H, WIRE>) { popn!([memory_offset, data_offset, len], context.interpreter); let len = as_usize_or_fail!(context.interpreter, len); - let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else { + let Some(memory_offset) = copy_cost_and_memory_resize(context.interpreter, memory_offset, len) + else { return; }; @@ -180,7 +179,6 @@ pub fn calldatacopy(context: InstructionConte /// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY pub fn returndatasize(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, BYZANTIUM); - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.return_data.buffer().len()) @@ -202,7 +200,8 @@ pub fn returndatacopy(context: InstructionCon return; } - let Some(memory_offset) = memory_resize(context.interpreter, memory_offset, len) else { + let Some(memory_offset) = copy_cost_and_memory_resize(context.interpreter, memory_offset, len) + else { return; }; @@ -219,7 +218,6 @@ pub fn returndatacopy(context: InstructionCon /// /// Pushes the amount of remaining gas onto the stack. pub fn gas(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.gas.remaining()) @@ -229,13 +227,13 @@ pub fn gas(context: InstructionContext<'_, H, /// Common logic for copying data from a source buffer to the EVM's memory. /// /// Handles memory expansion and gas calculation for data copy operations. -pub fn memory_resize( +pub fn copy_cost_and_memory_resize( interpreter: &mut Interpreter, memory_offset: U256, len: usize, ) -> Option { // Safe to cast usize to u64 - gas_or_fail!(interpreter, gas::copy_cost_verylow(len), None); + gas!(interpreter, interpreter.gas_params.copy_cost(len), None); if len == 0 { return None; } diff --git a/crates/interpreter/src/instructions/tx_info.rs b/crates/interpreter/src/instructions/tx_info.rs index d710b1d24f..90395ee54f 100644 --- a/crates/interpreter/src/instructions/tx_info.rs +++ b/crates/interpreter/src/instructions/tx_info.rs @@ -11,7 +11,6 @@ use crate::InstructionContext; pub fn gasprice( context: InstructionContext<'_, H, WIRE>, ) { - //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.effective_gas_price()); } @@ -19,7 +18,6 @@ pub fn gasprice( /// /// Gets the execution origination address. pub fn origin(context: InstructionContext<'_, H, WIRE>) { - //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context.host.caller().into_word().into() @@ -33,7 +31,6 @@ pub fn blob_hash( context: InstructionContext<'_, H, WIRE>, ) { check!(context.interpreter, CANCUN); - //gas!(context.interpreter, gas::VERYLOW); popn_top!([], index, context.interpreter); let i = as_usize_saturated!(index); *index = context.host.blob_hash(i).unwrap_or_default(); diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 3eeb6f10b0..2bfdab36a5 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -19,8 +19,8 @@ pub use stack::{Stack, STACK_LIMIT}; // imports use crate::{ - host::DummyHost, instruction_context::InstructionContext, interpreter_types::*, Gas, Host, - InstructionResult, InstructionTable, InterpreterAction, + gas::params::GasParams, host::DummyHost, instruction_context::InstructionContext, + interpreter_types::*, Gas, Host, InstructionResult, InstructionTable, InterpreterAction, }; use bytecode::Bytecode; use primitives::{hardfork::SpecId, Bytes}; @@ -29,6 +29,8 @@ use primitives::{hardfork::SpecId, Bytes}; #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Interpreter { + /// Gas table for dynamic gas constants. + pub gas_params: GasParams, /// Bytecode being executed. pub bytecode: WIRE::Bytecode, /// Gas tracking for execution costs. @@ -56,6 +58,7 @@ impl Interpreter> { is_static: bool, spec_id: SpecId, gas_limit: u64, + gas_params: GasParams, ) -> Self { Self::new_inner( Stack::new(), @@ -65,6 +68,7 @@ impl Interpreter> { is_static, spec_id, gas_limit, + gas_params, ) } @@ -87,6 +91,7 @@ impl Interpreter> { false, SpecId::default(), u64::MAX, + GasParams::default(), ) } @@ -99,10 +104,12 @@ impl Interpreter> { is_static: bool, spec_id: SpecId, gas_limit: u64, + gas_params: GasParams, ) -> Self { Self { bytecode, gas: Gas::new(gas_limit), + gas_params, stack, return_data: Default::default(), memory, @@ -114,6 +121,7 @@ impl Interpreter> { /// Clears and reinitializes the interpreter with new parameters. #[allow(clippy::too_many_arguments)] + #[inline(always)] pub fn clear( &mut self, memory: SharedMemory, @@ -122,10 +130,12 @@ impl Interpreter> { is_static: bool, spec_id: SpecId, gas_limit: u64, + gas_params: GasParams, ) { let Self { bytecode: bytecode_ref, gas, + gas_params: gas_params_ref, stack, return_data, memory: memory_ref, @@ -144,6 +154,7 @@ impl Interpreter> { *memory_ref = memory; *input_ref = input; *runtime_flag = RuntimeFlags { spec_id, is_static }; + *gas_params_ref = gas_params; *extend = EXT::default(); } @@ -155,6 +166,7 @@ impl Interpreter> { /// Sets the specid for the interpreter. pub fn set_spec_id(&mut self, spec_id: SpecId) { + self.gas_params = GasParams::new_spec(spec_id); self.runtime_flag.spec_id = spec_id; } } @@ -187,7 +199,17 @@ impl Interpreter { #[inline] #[must_use] pub fn resize_memory(&mut self, offset: usize, len: usize) -> bool { - resize_memory(&mut self.gas, &mut self.memory, offset, len) + if let Err(result) = resize_memory( + &mut self.gas, + &mut self.memory, + &self.gas_params, + offset, + len, + ) { + self.halt(result); + return false; + } + true } /// Takes the next action from the control and returns it. @@ -426,6 +448,7 @@ mod tests { false, SpecId::default(), u64::MAX, + GasParams::default(), ); let serialized = serde_json::to_string_pretty(&interpreter).unwrap(); @@ -463,6 +486,7 @@ fn test_mstore_big_offset_memory_oog() { false, SpecId::default(), 1000, + GasParams::default(), ); let table = instruction_table::(); @@ -501,6 +525,7 @@ fn test_mstore_big_offset_memory_limit_oog() { false, SpecId::default(), 100000, + GasParams::default(), ); let table = instruction_table::(); diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index f83dde5e14..abaf4ca1df 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -1,4 +1,5 @@ use super::MemoryTr; +use crate::{gas::params::GasParams, InstructionResult}; use core::{ cell::{Ref, RefCell, RefMut}, cmp::min, @@ -556,24 +557,29 @@ unsafe fn set_data(dst: &mut [u8], src: &[u8], dst_offset: usize, src_offset: us /// i.e. it rounds up the number bytes to number of words. #[inline] pub const fn num_words(len: usize) -> usize { - len.saturating_add(31) / 32 + len.div_ceil(32) } /// Performs EVM memory resize. #[inline] -#[must_use] pub fn resize_memory( gas: &mut crate::Gas, memory: &mut Memory, + gas_table: &GasParams, offset: usize, len: usize, -) -> bool { +) -> Result<(), InstructionResult> { + #[cfg(feature = "memory_limit")] + if memory.limit_reached(offset, len) { + return Err(InstructionResult::MemoryLimitOOG); + } + let new_num_words = num_words(offset.saturating_add(len)); if new_num_words > gas.memory().words_num { - resize_memory_cold(gas, memory, new_num_words) - } else { - true + return resize_memory_cold(gas, memory, gas_table, new_num_words); } + + Ok(()) } #[cold] @@ -581,18 +587,21 @@ pub fn resize_memory( fn resize_memory_cold( gas: &mut crate::Gas, memory: &mut Memory, + gas_table: &GasParams, new_num_words: usize, -) -> bool { +) -> Result<(), InstructionResult> { + let cost = gas_table.memory_cost(new_num_words); let cost = unsafe { gas.memory_mut() - .record_new_len(new_num_words) + .set_words_num(new_num_words, cost) .unwrap_unchecked() }; + if !gas.record_cost(cost) { - return false; + return Err(InstructionResult::MemoryOOG); } memory.resize(new_num_words * 32); - true + Ok(()) } #[cfg(test)] @@ -609,7 +618,9 @@ mod tests { assert_eq!(num_words(63), 2); assert_eq!(num_words(64), 2); assert_eq!(num_words(65), 3); - assert_eq!(num_words(usize::MAX), usize::MAX / 32); + assert_eq!(num_words(usize::MAX - 31), usize::MAX / 32); + assert_eq!(num_words(usize::MAX - 30), (usize::MAX / 32) + 1); + assert_eq!(num_words(usize::MAX), (usize::MAX / 32) + 1); } #[test] diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 3b53c88d57..b9aa17480f 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -31,9 +31,12 @@ LEGACY_REPO_URL="https://github.com/ethereum/legacytests.git" # Print usage information and exit usage() { - echo "Usage: $0 [clean] [runner] [profile] [target]" + echo "Usage: $0 [clean] [--keep-going] [runner] [profile] [target]" echo "" - echo "Arguments (after optional 'clean'):" + echo "Flags (can be specified before or after 'clean'):" + echo " --keep-going Continue running tests even after failures." + echo "" + echo "Arguments (after optional 'clean' and '--keep-going'):" echo " runner (Optional) Rust runner command. Must be either 'cargo' or 'cross'. Defaults to 'cargo'." echo " profile (Optional) Rust profile to use. Defaults to 'debug' if not provided." echo " target (Optional) Rust target. Only used if provided." @@ -45,14 +48,17 @@ usage() { echo " $0 release" echo " Uses runner 'cargo', profile 'release', and no target." echo "" + echo " $0 --keep-going release" + echo " Uses runner 'cargo', profile 'release', and keeps going on test failures." + echo "" echo " $0 release x86-win" echo " Uses runner 'cargo', profile 'release', with target 'x86-win'." echo "" echo " $0 clean" echo " Cleans fixtures then uses runner 'cargo', profile 'debug', and no target." echo "" - echo " $0 clean cross release x86-win" - echo " Cleans fixtures then uses runner 'cross', profile 'release', and target 'x86-win'." + echo " $0 clean --keep-going cross release x86-win" + echo " Cleans fixtures then uses runner 'cross', profile 'release', target 'x86-win', and keeps going on failures." exit 1 } @@ -145,36 +151,51 @@ build_cargo_options() { # Run tests for each set of fixtures using the chosen runner. run_tests() { echo "Running main stable statetests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$MAIN_STABLE_DIR/state_tests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest $KEEP_GOING_FLAG "$MAIN_STABLE_DIR/state_tests" echo "Running main develop statetests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$MAIN_DEVELOP_DIR/state_tests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest $KEEP_GOING_FLAG "$MAIN_DEVELOP_DIR/state_tests" echo "Running devnet statetests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$DEVNET_DIR/state_tests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest $KEEP_GOING_FLAG "$DEVNET_DIR/state_tests" echo "Running legacy Cancun tests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$LEGACY_DIR/Cancun/GeneralStateTests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest $KEEP_GOING_FLAG "$LEGACY_DIR/Cancun/GeneralStateTests" echo "Running legacy Constantinople tests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest "$LEGACY_DIR/Constantinople/GeneralStateTests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- statetest $KEEP_GOING_FLAG "$LEGACY_DIR/Constantinople/GeneralStateTests" echo "Running main develop blockchain tests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- btest "$MAIN_DEVELOP_DIR/blockchain_tests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- btest $KEEP_GOING_FLAG "$MAIN_DEVELOP_DIR/blockchain_tests" echo "Running main stable blockchain tests..." - $RUST_RUNNER run $CARGO_OPTS -p revme -- btest "$MAIN_STABLE_DIR/blockchain_tests" + $RUST_RUNNER run $CARGO_OPTS -p revme -- btest $KEEP_GOING_FLAG "$MAIN_STABLE_DIR/blockchain_tests" } ############################## # Main logic -# If the first argument is "clean", perform cleaning and download fixtures. -if [ "$1" = "clean" ]; then - clean - download_fixtures - shift -else +# Initialize flags +KEEP_GOING_FLAG="" +DID_CLEAN=false + +# Process "clean" and "--keep-going" flags +while true; do + if [ "$1" = "clean" ]; then + clean + download_fixtures + DID_CLEAN=true + shift + elif [ "$1" = "--keep-going" ]; then + KEEP_GOING_FLAG="--keep-going" + shift + else + break + fi +done + +# If no clean was specified, check for existing fixtures +if [ "$DID_CLEAN" = false ]; then if check_fixtures; then echo "Using existing test fixtures." else @@ -184,7 +205,7 @@ else fi # Argument parsing for runner, profile, target. -# Expected order (after optional clean): [runner] [profile] [target] +# Expected order (after optional clean and --keep-going): [runner] [profile] [target] # If the first argument is "cargo" or "cross", then it is the runner. # Otherwise, runner defaults to "cargo", and the arguments are profile and target. if [ "$#" -eq 0 ]; then From 5fec9bb0039ff984afe3b5571166c08ab57a70b0 Mon Sep 17 00:00:00 2001 From: Developer Uche <69772615+developeruche@users.noreply.github.com> Date: Thu, 11 Dec 2025 11:20:43 +0100 Subject: [PATCH 073/127] fix(create): Fix CreateInputs::created_address Cache invalidation (#3222) * fix create input cache invalidation * clippy * introduced getter funtions for Create Inputs --- crates/handler/src/frame.rs | 26 ++++---- .../src/interpreter_action/create_inputs.rs | 63 +++++++++++++++++-- 2 files changed, 71 insertions(+), 18 deletions(-) diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 6338ea44af..479e4093c1 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -270,7 +270,7 @@ impl EthFrame { Ok(ItemOrResult::Result(FrameResult::Create(CreateOutcome { result: InterpreterResult { result: e, - gas: Gas::new(inputs.gas_limit), + gas: Gas::new(inputs.gas_limit()), output: Bytes::new(), }, address: None, @@ -284,11 +284,11 @@ impl EthFrame { // Fetch balance of caller. let journal = context.journal_mut(); - let mut caller_info = journal.load_account_mut(inputs.caller)?; + let mut caller_info = journal.load_account_mut(inputs.caller())?; // Check if caller has enough balance to send to the created contract. // decrement of balance is done in the create_account_checkpoint. - if *caller_info.balance() < inputs.value { + if *caller_info.balance() < inputs.value() { return return_error(InstructionResult::OutOfFunds); } @@ -300,11 +300,11 @@ impl EthFrame { // Create address let mut init_code_hash = None; - let created_address = match inputs.scheme { - CreateScheme::Create => inputs.caller.create(old_nonce), + let created_address = match inputs.scheme() { + CreateScheme::Create => inputs.caller().create(old_nonce), CreateScheme::Create2 { salt } => { - let init_code_hash = *init_code_hash.insert(keccak256(&inputs.init_code)); - inputs.caller.create2(salt.to_be_bytes(), init_code_hash) + let init_code_hash = *init_code_hash.insert(keccak256(inputs.init_code())); + inputs.caller().create2(salt.to_be_bytes(), init_code_hash) } CreateScheme::Custom { address } => address, }; @@ -316,9 +316,9 @@ impl EthFrame { // Create account, transfer funds and make the journal checkpoint. let checkpoint = match context.journal_mut().create_account_checkpoint( - inputs.caller, + inputs.caller(), created_address, - inputs.value, + inputs.value(), spec, ) { Ok(checkpoint) => checkpoint, @@ -326,18 +326,18 @@ impl EthFrame { }; let bytecode = ExtBytecode::new_with_optional_hash( - Bytecode::new_legacy(inputs.init_code.clone()), + Bytecode::new_legacy(inputs.init_code().clone()), init_code_hash, ); let interpreter_input = InputsImpl { target_address: created_address, - caller_address: inputs.caller, + caller_address: inputs.caller(), bytecode_address: None, input: CallInput::Bytes(Bytes::new()), - call_value: inputs.value, + call_value: inputs.value(), }; - let gas_limit = inputs.gas_limit; + let gas_limit = inputs.gas_limit(); this.get(EthFrame::invalid).clear( FrameData::Create(CreateFrame { created_address }), diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index fe88771072..1085c3dab8 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -7,15 +7,15 @@ use primitives::{Address, Bytes, U256}; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CreateInputs { /// Caller address of the EVM - pub caller: Address, + caller: Address, /// The create scheme - pub scheme: CreateScheme, + scheme: CreateScheme, /// The value to transfer - pub value: U256, + value: U256, /// The init code of the contract - pub init_code: Bytes, + init_code: Bytes, /// The gas limit of the call - pub gas_limit: u64, + gas_limit: u64, /// Cached created address. This is computed lazily and cached to avoid /// redundant keccak computations when inspectors call `created_address`. #[cfg_attr(feature = "serde", serde(skip))] @@ -53,4 +53,57 @@ impl CreateInputs { CreateScheme::Custom { address } => address, }) } + + /// Returns the caller address of the EVM. + pub fn caller(&self) -> Address { + self.caller + } + + /// Returns the create scheme of the EVM. + pub fn scheme(&self) -> CreateScheme { + self.scheme + } + + /// Returns the value to transfer. + pub fn value(&self) -> U256 { + self.value + } + + /// Returns the init code of the contract. + pub fn init_code(&self) -> &Bytes { + &self.init_code + } + + /// Returns the gas limit of the call. + pub fn gas_limit(&self) -> u64 { + self.gas_limit + } + + /// Set call + pub fn set_call(&mut self, caller: Address) { + self.caller = caller; + self.cached_address = OnceCell::new(); + } + + /// Set scheme + pub fn set_scheme(&mut self, scheme: CreateScheme) { + self.scheme = scheme; + self.cached_address = OnceCell::new(); + } + + /// Set value + pub fn set_value(&mut self, value: U256) { + self.value = value; + } + + /// Set init code + pub fn set_init_code(&mut self, init_code: Bytes) { + self.init_code = init_code; + self.cached_address = OnceCell::new(); + } + + /// Set gas limit + pub fn set_gas_limit(&mut self, gas_limit: u64) { + self.gas_limit = gas_limit; + } } From 4c0dad5fd00d78a0edf745b263e8631a9e908fcf Mon Sep 17 00:00:00 2001 From: anim001k <140460766+anim001k@users.noreply.github.com> Date: Mon, 15 Dec 2025 05:47:31 +0100 Subject: [PATCH 074/127] chore(cleanup): remove unused duplicate ContextSetters trait in context crate (#3225) --- crates/context/src/setters.rs | 39 ----------------------------------- 1 file changed, 39 deletions(-) delete mode 100644 crates/context/src/setters.rs diff --git a/crates/context/src/setters.rs b/crates/context/src/setters.rs deleted file mode 100644 index 278fd40d74..0000000000 --- a/crates/context/src/setters.rs +++ /dev/null @@ -1,39 +0,0 @@ -use crate::Context; -use auto_impl::auto_impl; -use context_interface::{Block, Cfg, Database, JournalTr, Transaction}; - -/// Setters for the context. -#[auto_impl(&mut, Box)] -pub trait ContextSetters { - /// Transaction type. - type Tx: Transaction; - /// Block type. - type Block: Block; - - /// Set the transaction. - fn set_tx(&mut self, tx: Self::Tx); - - /// Set the block. - fn set_block(&mut self, block: Self::Block); -} - -impl ContextSetters - for Context -where - BLOCK: Block, - TX: Transaction, - CFG: Cfg, - DB: Database, - JOURNAL: JournalTr, -{ - type Tx = TX; - type Block = BLOCK; - - fn set_tx(&mut self, tx: Self::Tx) { - self.tx = tx; - } - - fn set_block(&mut self, block: Self::Block) { - self.block = block; - } -} From ae7789556f567170bccf07f58cae85648647b557 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 15 Dec 2025 13:39:54 +0100 Subject: [PATCH 075/127] chore(clippy): remove unused imports (#3227) --- crates/handler/src/instructions.rs | 2 +- crates/interpreter/src/instructions/contract.rs | 1 - crates/interpreter/src/instructions/memory.rs | 5 +---- crates/interpreter/src/instructions/system.rs | 1 - 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/handler/src/instructions.rs b/crates/handler/src/instructions.rs index 1af53ddbc6..ebe5a2d319 100644 --- a/crates/handler/src/instructions.rs +++ b/crates/handler/src/instructions.rs @@ -105,7 +105,7 @@ where if spec == self.spec { return false; } - self.instruction_table = Box::new(instruction_table_gas_changes_spec(spec)); + *self.instruction_table = instruction_table_gas_changes_spec(spec); self.gas_params = GasParams::new_spec(spec); true diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 1fea5f1275..dbcefcc426 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -6,7 +6,6 @@ pub use call_helpers::{ }; use crate::{ - gas, instructions::utility::IntoAddress, interpreter_action::FrameInput, interpreter_types::{InputsTr, InterpreterTypes, LoopControl, MemoryTr, RuntimeFlag, StackTr}, diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index 8c6b6acc1d..81d7e0c46a 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -1,7 +1,4 @@ -use crate::{ - gas, - interpreter_types::{InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}, -}; +use crate::interpreter_types::{InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}; use core::cmp::max; use primitives::U256; diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index cf6f7e2f76..678dd7bf6a 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -1,5 +1,4 @@ use crate::{ - gas, interpreter::Interpreter, interpreter_types::{ InputsTr, InterpreterTypes, LegacyBytecode, MemoryTr, ReturnData, RuntimeFlag, StackTr, From 436cd995ea59903cb133b4948edfb26f8627e648 Mon Sep 17 00:00:00 2001 From: anim001k <140460766+anim001k@users.noreply.github.com> Date: Mon, 15 Dec 2025 14:18:42 +0100 Subject: [PATCH 076/127] chore: Remove redundant tx fetch in Optimism handler gas accounting (#3220) * Update handler.rs * Update handler.rs * Update contract.rs * Update memory.rs * Update system.rs * Update instructions.rs --- crates/op-revm/src/handler.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index ca86a3b72e..13ee5c4f92 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -220,13 +220,10 @@ where // Regolith, gas is reported as normal. gas.erase_cost(remaining); gas.record_refund(refunded); - } else if is_deposit { - let tx = ctx.tx(); - if tx.is_system_transaction() { - // System transactions were a special type of deposit transaction in - // the Bedrock hardfork that did not incur any gas costs. - gas.erase_cost(tx_gas_limit); - } + } else if is_deposit && tx.is_system_transaction() { + // System transactions were a special type of deposit transaction in + // the Bedrock hardfork that did not incur any gas costs. + gas.erase_cost(tx_gas_limit); } } else if instruction_result.is_revert() { // On Optimism, deposit transactions report gas usage uniquely to other From 5787cd3c568cacd2079139dc56cdcde19fd489cd Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com> Date: Thu, 18 Dec 2025 02:02:41 +0000 Subject: [PATCH 077/127] perf(database): avoid triple cache lookup (#3232) --- crates/database/src/states/state.rs | 51 +++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index e862d7d0fd..d1b752795a 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -134,16 +134,39 @@ impl State { /// If the account is not found in the cache, it will be loaded from the /// database and inserted into the cache. pub fn load_cache_account(&mut self, address: Address) -> Result<&mut CacheAccount, DB::Error> { - match self.cache.accounts.entry(address) { + Self::load_cache_account_with( + &mut self.cache, + self.use_preloaded_bundle, + &self.bundle_state, + &mut self.database, + address, + ) + } + + /// Get a mutable reference to the [`CacheAccount`] for the given address. + /// + /// If the account is not found in the cache, it will be loaded from the + /// database and inserted into the cache. + /// + /// This function accepts destructed fields of [`Self`] as arguments and + /// returns a cached account with the lifetime of the provided cache reference. + fn load_cache_account_with<'a>( + cache: &'a mut CacheState, + use_preloaded_bundle: bool, + bundle_state: &BundleState, + database: &mut DB, + address: Address, + ) -> Result<&'a mut CacheAccount, DB::Error> { + Ok(match cache.accounts.entry(address) { hash_map::Entry::Vacant(entry) => { - if self.use_preloaded_bundle { + if use_preloaded_bundle { // Load account from bundle state - if let Some(account) = self.bundle_state.account(&address).map(Into::into) { + if let Some(account) = bundle_state.account(&address).map(Into::into) { return Ok(entry.insert(account)); } } // If not found in bundle, load it from database - let info = self.database.basic(address)?; + let info = database.basic(address)?; let account = match info { None => CacheAccount::new_loaded_not_existing(), Some(acc) if acc.is_empty() => { @@ -151,10 +174,10 @@ impl State { } Some(acc) => CacheAccount::new_loaded(acc, HashMap::default()), }; - Ok(entry.insert(account)) + entry.insert(account) } - hash_map::Entry::Occupied(entry) => Ok(entry.into_mut()), - } + hash_map::Entry::Occupied(entry) => entry.into_mut(), + }) } // TODO : Make cache aware of transitions dropping by having global transition counter. @@ -205,13 +228,13 @@ impl Database for State { index: StorageKey, ) -> Result { // If account is not found in cache, it will be loaded from database. - let account = if let Some(account) = self.cache.accounts.get_mut(&address) { - account - } else { - self.load_cache_account(address)?; - // safe to unwrap as account is loaded a line above. - self.cache.accounts.get_mut(&address).unwrap() - }; + let account = Self::load_cache_account_with( + &mut self.cache, + self.use_preloaded_bundle, + &self.bundle_state, + &mut self.database, + address, + )?; // Account will always be some, but if it is not, StorageValue::ZERO will be returned. let is_storage_known = account.status.is_storage_known(); From 500d68a32981760fd5998a720245b0d175223040 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin <5773434+shekhirin@users.noreply.github.com> Date: Thu, 18 Dec 2025 02:04:12 +0000 Subject: [PATCH 078/127] perf(database): use fixed hashmaps in cache db (#3231) * perf(database): cache db fixed hash maps * bump alloy deps --- Cargo.lock | 235 ++++++++++++++++++++-------- Cargo.toml | 14 +- crates/database/src/in_memory_db.rs | 7 +- crates/database/src/states/cache.rs | 6 +- crates/primitives/src/lib.rs | 2 +- 5 files changed, 182 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fa8cef2155..14ed45234a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -57,9 +57,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7345077623aaa080fc06735ac13b8fa335125c8550f9c4f64135a5bf6f79967" +checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" dependencies = [ "alloy-eips", "alloy-primitives", @@ -68,6 +68,7 @@ dependencies = [ "alloy-trie", "alloy-tx-macros", "auto_impl", + "borsh", "c-kzg", "derive_more", "either", @@ -76,15 +77,16 @@ dependencies = [ "rand 0.8.5", "secp256k1 0.30.0", "serde", + "serde_json", "serde_with", "thiserror", ] [[package]] name = "alloy-consensus-any" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501f83565d28bdb9d6457dd3b5d646e19db37709d0f27608a26a1839052ddade" +checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" dependencies = [ "alloy-consensus", "alloy-eips", @@ -109,23 +111,25 @@ dependencies = [ [[package]] name = "alloy-eip2930" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b82752a889170df67bbb36d42ca63c531eb16274f0d7299ae2a680facba17bd" +checksum = "9441120fa82df73e8959ae0e4ab8ade03de2aaae61be313fbf5746277847ce25" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "serde", ] [[package]] name = "alloy-eip7702" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d4769c6ffddca380b0070d71c8b7f30bed375543fe76bb2f74ec0acf4b7cd16" +checksum = "2919c5a56a1007492da313e7a3b6d45ef5edc5d33416fdec63c0d7a2702a0d20" dependencies = [ "alloy-primitives", "alloy-rlp", + "borsh", "k256", "serde", "thiserror", @@ -133,9 +137,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c219a87fb386a75780ddbdbbced242477321887e426b0f946c05815ceabe5e09" +checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -144,6 +148,7 @@ dependencies = [ "alloy-rlp", "alloy-serde", "auto_impl", + "borsh", "c-kzg", "derive_more", "either", @@ -155,9 +160,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "125a1c373261b252e53e04d6e92c37d881833afc1315fceab53fd46045695640" +checksum = "6bfca3dbbcb7498f0f60e67aff2ad6aff57032e22eb2fd03189854be11a22c03" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -167,9 +172,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "334555c323fa2bb98f1d4c242b62da9de8c715557a2ed680a76cefbcac19fefd" +checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -182,9 +187,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ea377c9650203d7a7da9e8dee7f04906b49a9253f554b110edd7972e75ef34" +checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -208,9 +213,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f9ab9a9e92c49a357edaee2d35deea0a32ac8f313cfa37448f04e7e029c9d9" +checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" dependencies = [ "alloy-consensus", "alloy-eips", @@ -221,9 +226,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9485c56de23438127a731a6b4c87803d49faf1a7068dcd1d8768aca3a9edb9" +checksum = "5c850e6ccbd34b8a463a1e934ffc8fc00e1efc5e5489f2ad82d7797949f3bd4e" dependencies = [ "alloy-rlp", "arbitrary", @@ -231,9 +236,9 @@ dependencies = [ "cfg-if", "const-hex", "derive_more", - "foldhash", + "foldhash 0.2.0", "getrandom 0.3.3", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "indexmap 2.11.0", "itoa", "k256", @@ -242,6 +247,7 @@ dependencies = [ "proptest", "proptest-derive", "rand 0.9.2", + "rapidhash", "ruint", "rustc-hash", "serde", @@ -251,9 +257,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a85361c88c16116defbd98053e3d267054d6b82729cdbef0236f7881590f924" +checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" dependencies = [ "alloy-chains", "alloy-consensus", @@ -312,9 +318,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "743fc964abb0106e454e9e8683fb0809fb32940270ef586a58e913531360b302" +checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -335,9 +341,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97372c51a14a804fb9c17010e3dd6c117f7866620b264e24b64d2259be44bcdf" +checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -346,9 +352,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672286c19528007df058bafd82c67e23247b4b3ebbc538cbddc705a82d8a930f" +checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -367,9 +373,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aae653f049267ae7e040eab6c9b9a417064ca1a6cb21e3dd59b9f1131ef048f" +checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" dependencies = [ "alloy-primitives", "serde", @@ -378,9 +384,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d97cedce202f848592b96f7e891503d3adb33739c4e76904da73574290141b93" +checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" dependencies = [ "alloy-primitives", "async-trait", @@ -393,9 +399,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83ae7d854db5b7cdd5b9ed7ad13d1e5e034cdd8be85ffef081f61dc6c9e18351" +checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" dependencies = [ "alloy-consensus", "alloy-network", @@ -409,9 +415,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20d867dcf42019d4779519a1ceb55eba8d7f3d0e4f0a89bcba82b8f9eb01e48" +checksum = "b2218e3aeb3ee665d117fdf188db0d5acfdc3f7b7502c827421cb78f26a2aec0" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -423,9 +429,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74e91b0b553c115d14bd0ed41898309356dc85d0e3d4b9014c4e7715e48c8ad" +checksum = "b231cb8cc48e66dd1c6e11a1402f3ac86c3667cbc13a6969a0ac030ba7bb8c88" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -441,9 +447,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84194d31220803f5f62d0a00f583fd3a062b36382e2bea446f1af96727754565" +checksum = "49a522d79929c1bf0152b07567a38f7eaed3ab149e53e7528afa78ff11994668" dependencies = [ "const-hex", "dunce", @@ -457,9 +463,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe8c27b3cf6b2bb8361904732f955bc7c05e00be5f469cec7e2280b6167f3ff0" +checksum = "0475c459859c8d9428af6ff3736614655a57efda8cc435a3b8b4796fa5ac1dd0" dependencies = [ "serde", "winnow", @@ -467,9 +473,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5383d34ea00079e6dd89c652bcbdb764db160cef84e6250926961a0b2295d04" +checksum = "35287d9d821d5f26011bcd8d9101340898f761c9933cf50fca689bb7ed62fdeb" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -479,12 +485,11 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08b383bc903c927635e39e1dae7df2180877d93352d1abd389883665a598afc" +checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" dependencies = [ "alloy-json-rpc", - "alloy-primitives", "auto_impl", "base64", "derive_more", @@ -503,9 +508,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e58dee1f7763ef302074b645fc4f25440637c09a60e8de234b62993f06c0ae3" +checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -534,12 +539,11 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.0.27" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d14809f908822dbff0dc472c77ca4aa129ab12e22fd9bff2dd1ef54603e68e3d" +checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" dependencies = [ - "alloy-primitives", - "darling", + "darling 0.21.3", "proc-macro2", "quote", "syn 2.0.106", @@ -1133,6 +1137,29 @@ dependencies = [ "zeroize", ] +[[package]] +name = "borsh" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f" +dependencies = [ + "borsh-derive", + "cfg_aliases", +] + +[[package]] +name = "borsh-derive" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0686c856aa6aac0c4498f936d7d6a02df690f614c03e4d906d1018062b5c5e2c" +dependencies = [ + "once_cell", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "bumpalo" version = "3.19.0" @@ -1536,8 +1563,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core 0.21.3", + "darling_macro 0.21.3", ] [[package]] @@ -1554,13 +1591,39 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "darling_core" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "serde", + "strsim", + "syn 2.0.106", +] + [[package]] name = "darling_macro" version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "darling_macro" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core 0.21.3", "quote", "syn 2.0.106", ] @@ -1952,6 +2015,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2186,8 +2255,18 @@ checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "foldhash 0.2.0", "serde", + "serde_core", ] [[package]] @@ -3304,9 +3383,9 @@ dependencies = [ [[package]] name = "proptest-derive" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ee1c9ac207483d5e7db4940700de86a9aae46ef90c48b57f99fe7edb8345e49" +checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" dependencies = [ "proc-macro2", "quote", @@ -3411,6 +3490,16 @@ dependencies = [ "rand_core 0.9.3", ] +[[package]] +name = "rapidhash" +version = "4.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8e65c75143ce5d47c55b510297eeb1182f3c739b6043c537670e9fc18612dae" +dependencies = [ + "rand 0.9.2", + "rustversion", +] + [[package]] name = "rayon" version = "1.11.0" @@ -4109,18 +4198,28 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.219" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -4178,7 +4277,7 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", "syn 2.0.106", @@ -4390,9 +4489,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0b198d366dbec045acfcd97295eb653a7a2b40e4dc764ef1e79aafcad439d3c" +checksum = "60ceeb7c95a4536de0c0e1649bd98d1a72a4bb9590b1f3e45a8a0bfdb7c188c0" dependencies = [ "paste", "proc-macro2", diff --git a/Cargo.toml b/Cargo.toml index f724c01f4f..1a9f727219 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,16 +60,16 @@ ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1 # alloy alloy-eip2930 = { version = "0.2.1", default-features = false } alloy-eip7702 = { version = "0.6.1", default-features = false } -alloy-primitives = { version = "1.3.1", default-features = false } +alloy-primitives = { version = "1.5.0", default-features = false } # alloy in examples, revme or feature flagged. alloy-rlp = { version = "0.3.12", default-features = false } -alloy-sol-types = { version = "1.3.1", default-features = false } -alloy-consensus = { version = "1.0.27", default-features = false } -alloy-eips = { version = "1.0.27", default-features = false } -alloy-provider = { version = "1.0.27", default-features = false } -alloy-signer = { version = "1.0.27", default-features = false } -alloy-signer-local = { version = "1.0.27", default-features = false } +alloy-sol-types = { version = "1.5.0", default-features = false } +alloy-consensus = { version = "1.1.3", default-features = false } +alloy-eips = { version = "1.1.3", default-features = false } +alloy-provider = { version = "1.1.3", default-features = false } +alloy-signer = { version = "1.1.3", default-features = false } +alloy-signer-local = { version = "1.1.3", default-features = false } alloy-transport = { version = "1.0.12", default-features = false } # precompiles diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index 86e44691f0..a49e1e2189 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -4,7 +4,8 @@ use database_interface::{ BENCH_TARGET, BENCH_TARGET_BALANCE, }; use primitives::{ - hash_map::Entry, Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, + hash_map::Entry, Address, AddressMap, B256Map, HashMap, Log, StorageKey, StorageValue, B256, + KECCAK_EMPTY, U256, }; use state::{Account, AccountInfo, Bytecode}; use std::vec::Vec; @@ -22,9 +23,9 @@ pub type InMemoryDB = CacheDB; pub struct Cache { /// Account info where None means it is not existing. Not existing state is needed for Pre TANGERINE forks. /// `code` is always `None`, and bytecode can be found in `contracts`. - pub accounts: HashMap, + pub accounts: AddressMap, /// Tracks all contracts by their code hash. - pub contracts: HashMap, + pub contracts: B256Map, /// All logs that were committed via [DatabaseCommit::commit]. pub logs: Vec, /// All cached block hashes from the [DatabaseRef]. diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index 2d786dd893..ebb75f6188 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -2,7 +2,7 @@ use super::{ plain_account::PlainStorage, transition_account::TransitionAccount, CacheAccount, PlainAccount, }; use bytecode::Bytecode; -use primitives::{Address, HashMap, B256}; +use primitives::{Address, AddressMap, B256Map, HashMap}; use state::{Account, AccountInfo}; use std::vec::Vec; @@ -17,9 +17,9 @@ use std::vec::Vec; #[derive(Clone, Debug, PartialEq, Eq)] pub struct CacheState { /// Block state account with account state - pub accounts: HashMap, + pub accounts: AddressMap, /// Created contracts - pub contracts: HashMap, + pub contracts: B256Map, /// Has EIP-161 state clear enabled (Spurious Dragon hardfork) pub has_state_clear: bool, } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 9193733bb2..cdbdabbad7 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -34,7 +34,7 @@ pub use once_lock::OnceLock; pub use alloy_primitives::{ self, address, b256, bytes, fixed_bytes, hex, hex_literal, keccak256, - map::{self, hash_map, hash_set, HashMap, HashSet}, + map::{self, hash_map, hash_set, AddressMap, B256Map, HashMap, HashSet}, ruint, uint, Address, Bytes, FixedBytes, Log, LogData, TxKind, B256, I128, I256, U128, U256, }; From dd5173c90046eb2645940f5de9fc568f941eed94 Mon Sep 17 00:00:00 2001 From: forkfury Date: Thu, 18 Dec 2025 04:57:39 +0100 Subject: [PATCH 079/127] fix(database): verify handle belongs to current runtime before block_in_place (#3212) * Update async_db.rs * Apply suggestion from @rakita --- crates/database/interface/src/async_db.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/crates/database/interface/src/async_db.rs b/crates/database/interface/src/async_db.rs index 7ae1ecd5f9..db0325f739 100644 --- a/crates/database/interface/src/async_db.rs +++ b/crates/database/interface/src/async_db.rs @@ -191,13 +191,17 @@ impl HandleOrRuntime { { match self { Self::Handle(handle) => { - // Use block_in_place only when we're currently inside a multi-threaded Tokio runtime. - // Otherwise, call handle.block_on directly to avoid panicking outside of a runtime. + // Use block_in_place only when we're currently inside a multi-threaded Tokio runtime + // and the handle belongs to the same runtime. Otherwise, call handle.block_on directly. let can_block_in_place = match Handle::try_current() { - Ok(current) => !matches!( - current.runtime_flavor(), - tokio::runtime::RuntimeFlavor::CurrentThread - ), + Ok(current) => { + // Only use block_in_place if we're in a multi-threaded runtime + // and the handle belongs to the current runtime (same handle instance). + !matches!( + current.runtime_flavor(), + tokio::runtime::RuntimeFlavor::CurrentThread + ) && core::ptr::eq(handle as *const _, ¤t as *const _) + } Err(_) => false, }; From 3377d5bbf3eb41584f0b4ed7900bd9733b21ea01 Mon Sep 17 00:00:00 2001 From: anim001k <140460766+anim001k@users.noreply.github.com> Date: Thu, 18 Dec 2025 04:59:12 +0100 Subject: [PATCH 080/127] fix(revme): incorrect debug log message in btest (#3233) --- bins/revme/src/cmd/blockchaintest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index f286a3ca85..d1e87d625d 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -856,7 +856,7 @@ fn execute_blockchain_test( println!("{}", serde_json::to_string(&output).unwrap()); } else { eprintln!( - "⚠️ Skipping block {block_idx} due to expected failure: {exception}" + "⚠️ Skipping block {block_idx}: transaction unexpectedly succeeded (expected failure: {exception})" ); } break; // Skip to next block From b397fd1a90186340a68295de1cd8b7a8626e557f Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 18 Dec 2025 07:29:03 +0100 Subject: [PATCH 081/127] refactor(handler): validate_initial_tx_gas takes &mut Evm (#3235) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor(handler): validate_initial_tx_gas takes &mut Evm Change the `validate_initial_tx_gas` function signature to take `&mut EVM` instead of individual parameters (tx, spec, is_eip7623_disabled). This makes the API more consistent with other handler functions and allows the function to extract what it needs from the EVM context. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * revert fn sig --------- Co-authored-by: Claude Opus 4.5 --- crates/handler/src/handler.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index ca905a1683..1b96c3fbe7 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -265,7 +265,10 @@ pub trait Handler { /// /// Verifies the initial cost does not exceed the transaction gas limit. #[inline] - fn validate_initial_tx_gas(&self, evm: &Self::Evm) -> Result { + fn validate_initial_tx_gas( + &self, + evm: &mut Self::Evm, + ) -> Result { let ctx = evm.ctx_ref(); validation::validate_initial_tx_gas( ctx.tx(), From 23065598a316aa7a47021e23ac0e29a1f94f82ac Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 18 Dec 2025 11:35:28 +0100 Subject: [PATCH 082/127] feat: BAL EIP-7928 (#3070) * BAL * WIP * bal wip * bal followup * Database::bal and Bal IndexMap for accounts * bal builder and integration with databases * chore: bump eest tests v5.3.0 * bump bal for caller/beneficiary * bal builder from state on commit, alloy included * cleanup * bal integration in btests * wip sys call * fix few bugs, propagate error * remove bal panic from btest * error handling * cleanup bal tests * skip touching beneficiary if reward is 0 * handle local selfdestruct * feat: dont load access list immediatly * nits fmt * bump output as accounts now have original account info * BalDatabase * nit, rm clone * bump tests, add missing imports, cleanup * reause indexmap from alloy with default hasher * typos * add missing serde propagation * dont skip test * Create BalState and add it inside State so that we dont need to use BalDatabase * nits, and deserialization for Account without original info * propagate feature * fix: add bal_builder.commit to state, small cleanup * fix: bal binary search cases (#3139) * fix: bal binary search cases * nit(test): generalize BAL binary search test for any threshold * code cleanup --------- Co-authored-by: rakita * compile tests * Rename BalDatabaseError to EvmDatabaseError * throw error if bal exist but account/storage not * rename storage_id to account_id * rm println * use alloy main, clippy/typo fixes * ark the bytecode * typo * add statis default for Bytecode * use oncelock * try with oncelock * box original acc info --- Cargo.lock | 14 + Cargo.toml | 3 +- bins/revme/src/cmd/blockchaintest.rs | 40 +- .../src/cmd/blockchaintest/post_block.rs | 74 +++- .../revme/src/cmd/blockchaintest/pre_block.rs | 41 +- bins/revme/src/cmd/statetest/merkle_trie.rs | 7 +- bins/revme/src/cmd/statetest/runner.rs | 23 +- crates/bytecode/src/bytecode.rs | 24 +- crates/bytecode/src/iter.rs | 10 +- crates/bytecode/src/legacy/raw.rs | 6 + crates/context/src/journal/inner.rs | 10 +- crates/database/interface/src/async_db.rs | 57 +++ crates/database/interface/src/bal.rs | 391 ++++++++++++++++++ crates/database/interface/src/either.rs | 24 ++ crates/database/interface/src/lib.rs | 30 ++ crates/database/src/in_memory_db.rs | 3 + crates/database/src/states/bundle_state.rs | 27 +- crates/database/src/states/cache.rs | 11 +- crates/database/src/states/state.rs | 217 ++++++++-- crates/database/src/states/state_builder.rs | 24 +- .../op_revm_testdata/test_deposit_tx.json | 20 + .../test_halted_deposit_tx.json | 42 ++ ...all_bls12_381_g1_add_input_wrong_size.json | 100 +++++ ...d_tx_call_bls12_381_g1_add_out_of_gas.json | 100 +++++ ...all_bls12_381_g1_msm_input_wrong_size.json | 100 +++++ ...d_tx_call_bls12_381_g1_msm_out_of_gas.json | 100 +++++ ...l_bls12_381_g1_msm_wrong_input_layout.json | 100 +++++ ...all_bls12_381_g2_add_input_wrong_size.json | 100 +++++ ...d_tx_call_bls12_381_g2_add_out_of_gas.json | 100 +++++ ...all_bls12_381_g2_msm_input_wrong_size.json | 100 +++++ ...d_tx_call_bls12_381_g2_msm_out_of_gas.json | 100 +++++ ...l_bls12_381_g2_msm_wrong_input_layout.json | 100 +++++ ...12_381_map_fp2_to_g2_input_wrong_size.json | 100 +++++ ...ll_bls12_381_map_fp2_to_g2_out_of_gas.json | 100 +++++ ...s12_381_map_fp_to_g1_input_wrong_size.json | 100 +++++ ...all_bls12_381_map_fp_to_g1_out_of_gas.json | 100 +++++ ...ll_bls12_381_pairing_input_wrong_size.json | 100 +++++ ..._tx_call_bls12_381_pairing_out_of_gas.json | 100 +++++ ..._bls12_381_pairing_wrong_input_layout.json | 100 +++++ .../test_halted_tx_call_bn254_pair_fjord.json | 100 +++++ ...est_halted_tx_call_bn254_pair_granite.json | 100 +++++ .../test_halted_tx_call_p256verify.json | 100 +++++ .../test_l1block_load_for_pre_regolith.json | 106 +++++ .../test_l1block_load_for_regolit.json | 165 -------- .../op_revm_testdata/test_log_inspector.json | 108 +++++ .../test_tx_call_p256verify.json | 100 +++++ .../revm_testdata/test_multi_tx_create.json | 82 +++- .../test_selfdestruct_multi_tx.json | 80 ++++ crates/inspector/src/inspector_tests.rs | 2 + crates/interpreter/src/gas/params.rs | 9 +- crates/interpreter/src/instructions/host.rs | 5 +- crates/op-revm/src/handler.rs | 13 +- crates/primitives/Cargo.toml | 6 +- crates/primitives/src/lib.rs | 2 +- crates/state/Cargo.toml | 23 +- crates/state/src/account_info.rs | 48 +-- crates/state/src/bal.rs | 242 +++++++++++ crates/state/src/bal/account.rs | 320 ++++++++++++++ crates/state/src/bal/alloy.rs | 80 ++++ crates/state/src/bal/writes.rs | 184 +++++++++ crates/state/src/lib.rs | 113 ++++- crates/statetest-types/Cargo.toml | 3 + crates/statetest-types/src/blockchain.rs | 38 ++ crates/statetest-types/src/spec.rs | 7 +- crates/statetest-types/src/test_unit.rs | 1 + .../src/custom_evm.rs | 3 + .../custom_precompile_journal/src/main.rs | 2 + examples/erc20_gas/src/main.rs | 8 +- examples/uniswap_v2_usdc_swap/src/main.rs | 6 +- 69 files changed, 4495 insertions(+), 359 deletions(-) create mode 100644 crates/database/interface/src/bal.rs delete mode 100644 crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json create mode 100644 crates/state/src/bal.rs create mode 100644 crates/state/src/bal/account.rs create mode 100644 crates/state/src/bal/alloy.rs create mode 100644 crates/state/src/bal/writes.rs diff --git a/Cargo.lock b/Cargo.lock index 14ed45234a..3a7f74b491 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -135,6 +135,17 @@ dependencies = [ "thiserror", ] +[[package]] +name = "alloy-eip7928" +version = "0.2.0" +source = "git+https://github.com/rakita/alloy-eips.git?rev=734beaf#734beafea409bdd87b3a4e33ac72ac68654bb8dd" +dependencies = [ + "alloy-primitives", + "alloy-rlp", + "borsh", + "serde", +] + [[package]] name = "alloy-eips" version = "1.1.3" @@ -3816,16 +3827,19 @@ dependencies = [ name = "revm-state" version = "8.1.1" dependencies = [ + "alloy-eip7928", "bitflags", "revm-bytecode", "revm-primitives", "serde", + "serde_json", ] [[package]] name = "revm-statetest-types" version = "13.1.0" dependencies = [ + "alloy-eip7928", "alloy-eips", "k256", "revm", diff --git a/Cargo.toml b/Cargo.toml index 1a9f727219..1bfb122ee9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1 # alloy alloy-eip2930 = { version = "0.2.1", default-features = false } alloy-eip7702 = { version = "0.6.1", default-features = false } +alloy-eip7928 = { version = "0.2.0", default-features = false, git = "https://github.com/rakita/alloy-eips.git", rev = "734beaf" } alloy-primitives = { version = "1.5.0", default-features = false } # alloy in examples, revme or feature flagged. @@ -70,7 +71,7 @@ alloy-eips = { version = "1.1.3", default-features = false } alloy-provider = { version = "1.1.3", default-features = false } alloy-signer = { version = "1.1.3", default-features = false } alloy-signer-local = { version = "1.1.3", default-features = false } -alloy-transport = { version = "1.0.12", default-features = false } +alloy-transport = { version = "1.1.3", default-features = false } # precompiles ark-bls12-381 = { version = "0.5", default-features = false } diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index d1e87d625d..9ee6290ba3 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -11,7 +11,7 @@ use revm::{ handler::EvmTr, inspector::inspectors::TracerEip3155, primitives::{hardfork::SpecId, hex, Address, HashMap, U256}, - state::AccountInfo, + state::{bal::Bal, AccountInfo}, Context, Database, ExecuteCommitEvm, ExecuteEvm, InspectEvm, MainBuilder, MainContext, }; use serde_json::json; @@ -22,6 +22,7 @@ use std::{ collections::BTreeMap, fs, path::{Path, PathBuf}, + sync::Arc, time::Instant, }; use thiserror::Error; @@ -654,7 +655,7 @@ fn execute_blockchain_test( } // Create database with initial state - let mut state = State::builder().build(); + let mut state = State::builder().with_bal_builder().build(); // Capture pre-state for debug info let mut pre_state_debug = HashMap::default(); @@ -667,6 +668,7 @@ fn execute_blockchain_test( nonce: account.nonce, code_hash: revm::primitives::keccak256(&account.code), code: Some(Bytecode::new_raw(account.code.clone())), + account_id: None, }; // Store for debug info @@ -723,6 +725,15 @@ fn execute_blockchain_test( this_excess_blob_gas = None; } + let bal_test = block + .block_access_list + .as_ref() + .and_then(|bal| Bal::try_from(bal.clone()).ok()) + .map(Arc::new); + + //state.set_bal(bal_test); + state.reset_bal_index(); + // Create EVM context for each transaction to ensure fresh state access let evm_context = Context::mainnet() .with_block(&block_env) @@ -808,6 +819,9 @@ fn execute_blockchain_test( } }; + // bump bal index + evm.db_mut().bump_bal_index(); + // If JSON output requested, output transaction details let execution_result = if json_output { evm.inspect_tx(tx_env.clone()) @@ -917,6 +931,9 @@ fn execute_blockchain_test( } } + // bump bal index + evm.db_mut().bump_bal_index(); + // uncle rewards are not implemented yet post_block::post_block_transition( &mut evm, @@ -930,6 +947,19 @@ fn execute_blockchain_test( .block_hashes .insert(block_env.number.to::(), block_hash.unwrap_or_default()); + if let Some(bal) = state.bal_state.bal_builder.take() { + if let Some(state_bal) = bal_test { + if &bal != state_bal.as_ref() { + println!("Bal mismatch"); + println!("Test bal"); + state_bal.pretty_print(); + println!("Bal:"); + bal.pretty_print(); + return Err(TestExecutionError::BalMismatchError); + } + } + } + parent_block_hash = block_hash; if let Some(excess_blob_gas) = this_excess_blob_gas { parent_excess_blob_gas = excess_blob_gas; @@ -983,7 +1013,8 @@ fn fork_to_spec_id(fork: ForkSpec) -> SpecId { ForkSpec::Cancun | ForkSpec::ShanghaiToCancunAtTime15k => SpecId::CANCUN, ForkSpec::Prague | ForkSpec::CancunToPragueAtTime15k => SpecId::PRAGUE, ForkSpec::Osaka | ForkSpec::PragueToOsakaAtTime15k => SpecId::OSAKA, - _ => SpecId::OSAKA, // For any unknown forks, use latest available + ForkSpec::Amsterdam => SpecId::AMSTERDAM, + _ => SpecId::AMSTERDAM, // For any unknown forks, use latest available } } @@ -1088,6 +1119,9 @@ pub enum TestExecutionError { gas_used: u64, }, + #[error("BAL error")] + BalMismatchError, + #[error( "Post-state validation failed for {address:?}.{field}: expected {expected}, got {actual}" )] diff --git a/bins/revme/src/cmd/blockchaintest/post_block.rs b/bins/revme/src/cmd/blockchaintest/post_block.rs index 62617acc05..509548e2a3 100644 --- a/bins/revme/src/cmd/blockchaintest/post_block.rs +++ b/bins/revme/src/cmd/blockchaintest/post_block.rs @@ -1,15 +1,15 @@ use revm::{ - context::{Block, ContextTr}, - database::{DatabaseCommitExt as _, State}, + context::{Block, ContextTr, JournalTr}, handler::EvmTr, - primitives::{hardfork::SpecId, ONE_ETHER, ONE_GWEI}, - Database, SystemCallCommitEvm, + primitives::{address, hardfork::SpecId, Address, Bytes, ONE_ETHER, ONE_GWEI, U256}, + Database, DatabaseCommit, SystemCallCommitEvm, }; use statetest_types::blockchain::Withdrawal; /// Post block transition that includes: /// * Block and uncle rewards before the Merge/Paris hardfork. -/// * system calls +/// * Withdrawals (EIP-4895) +/// * Post-block system calls: EIP-7002 (withdrawal requests) and EIP-7251 (consolidation requests) /// /// # Note /// @@ -17,9 +17,8 @@ use statetest_types::blockchain::Withdrawal; #[inline] pub fn post_block_transition< 'a, - DB: Database + 'a, - EVM: SystemCallCommitEvm - + EvmTr>>, + DB: Database + DatabaseCommit + 'a, + EVM: SystemCallCommitEvm + EvmTr>, >( evm: &mut EVM, block: impl Block, @@ -29,24 +28,36 @@ pub fn post_block_transition< // block reward let block_reward = block_reward(spec, 0); if block_reward != 0 { - let _ = evm - .ctx_mut() - .db_mut() - .increment_balances(vec![(block.beneficiary(), block_reward)]); + evm.ctx_mut() + .journal_mut() + .balance_incr(block.beneficiary(), U256::from(block_reward)) + .expect("Db actions to pass"); } // withdrawals if spec.is_enabled_in(SpecId::SHANGHAI) { for withdrawal in withdrawals { evm.ctx_mut() - .db_mut() - .increment_balances(vec![( + .journal_mut() + .balance_incr( withdrawal.address, - withdrawal.amount.to::().saturating_mul(ONE_GWEI), - )]) + withdrawal.amount.saturating_mul(U256::from(ONE_GWEI)), + ) .expect("Db actions to pass"); } } + + evm.commit_inner(); + + // EIP-7002: Withdrawal requests system call + if spec.is_enabled_in(SpecId::PRAGUE) { + system_call_eip7002_withdrawal_request(evm); + } + + // EIP-7251: Consolidation requests system call + if spec.is_enabled_in(SpecId::PRAGUE) { + system_call_eip7251_consolidation_request(evm); + } } /// Block reward for a block. @@ -66,3 +77,34 @@ pub const fn block_reward(spec: SpecId, ommers: usize) -> u128 { reward + (reward >> 5) * ommers as u128 } + +pub const WITHDRAWAL_REQUEST_ADDRESS: Address = + address!("0x00000961Ef480Eb55e80D19ad83579A64c007002"); + +/// EIP-7002: Withdrawal requests system call +pub(crate) fn system_call_eip7002_withdrawal_request( + evm: &mut impl SystemCallCommitEvm, +) { + // empty data is valid for EIP-7002 + let _ = match evm.system_call_commit(WITHDRAWAL_REQUEST_ADDRESS, Bytes::new()) { + Ok(res) => res, + Err(e) => { + panic!("System call failed: {e:?}"); + } + }; +} + +pub const CONSOLIDATION_REQUEST_ADDRESS: Address = + address!("0x0000BBdDc7CE488642fb579F8B00f3a590007251"); + +/// EIP-7251: Consolidation requests system call +pub(crate) fn system_call_eip7251_consolidation_request( + evm: &mut impl SystemCallCommitEvm, +) { + let _ = match evm.system_call_commit(CONSOLIDATION_REQUEST_ADDRESS, Bytes::new()) { + Ok(res) => res, + Err(e) => { + panic!("System call failed: {e:?}"); + } + }; +} diff --git a/bins/revme/src/cmd/blockchaintest/pre_block.rs b/bins/revme/src/cmd/blockchaintest/pre_block.rs index 90fb922740..06997d418c 100644 --- a/bins/revme/src/cmd/blockchaintest/pre_block.rs +++ b/bins/revme/src/cmd/blockchaintest/pre_block.rs @@ -2,22 +2,21 @@ use revm::{ context::{Block, ContextTr}, - database::{Database, State}, + database::Database, handler::EvmTr, primitives::{address, hardfork::SpecId, Address, B256}, - SystemCallCommitEvm, + DatabaseCommit, SystemCallCommitEvm, }; /// Pre block state transition /// /// # Note /// -/// Contains only withdrawal processing. And it is missing block hash system call. +/// Contains pre-block system calls: EIP-2935 (blockhash) and EIP-4788 (beacon root). pub fn pre_block_transition< 'a, - DB: Database + 'a, - EVM: SystemCallCommitEvm - + EvmTr>>, + DB: Database + DatabaseCommit + 'a, + EVM: SystemCallCommitEvm + EvmTr>, >( evm: &mut EVM, spec: SpecId, @@ -31,11 +30,15 @@ pub fn pre_block_transition< // blockhash system call if let Some(parent_block_hash) = parent_block_hash { - system_call_eip2935_blockhash(spec, parent_block_hash, evm); + if spec.is_enabled_in(SpecId::PRAGUE) { + system_call_eip2935_blockhash(evm, parent_block_hash); + } } if let Some(parent_beacon_block_root) = parent_beacon_block_root { - system_call_eip4788_beacon_root(spec, parent_beacon_block_root, evm); + if spec.is_enabled_in(SpecId::CANCUN) { + system_call_eip4788_beacon_root(evm, parent_beacon_block_root); + } } } @@ -44,42 +47,28 @@ pub const HISTORY_STORAGE_ADDRESS: Address = address!("0x0000F90827F1C53a10cb7A0 /// Blockhash system callEIP-2935 #[inline] pub(crate) fn system_call_eip2935_blockhash( - spec: SpecId, - parent_block_hash: B256, evm: &mut impl SystemCallCommitEvm, -) -> bool { - if !spec.is_enabled_in(SpecId::PRAGUE) { - return true; - } - + parent_block_hash: B256, +) { let _ = match evm.system_call_commit(HISTORY_STORAGE_ADDRESS, parent_block_hash.0.into()) { Ok(res) => res, Err(e) => { panic!("System call failed: {e:?}"); } }; - - true } pub const BEACON_ROOTS_ADDRESS: Address = address!("000F3df6D732807Ef1319fB7B8bB8522d0Beac02"); /// Beacon root system call EIP-4788 pub(crate) fn system_call_eip4788_beacon_root( - spec: SpecId, - parent_beacon_block_root: B256, evm: &mut impl SystemCallCommitEvm, -) -> bool { - if !spec.is_enabled_in(SpecId::CANCUN) { - return true; - } - + parent_beacon_block_root: B256, +) { let _ = match evm.system_call_commit(BEACON_ROOTS_ADDRESS, parent_beacon_block_root.0.into()) { Ok(res) => res, Err(e) => { panic!("System call failed: {e:?}"); } }; - - true } diff --git a/bins/revme/src/cmd/statetest/merkle_trie.rs b/bins/revme/src/cmd/statetest/merkle_trie.rs index 34ac105132..0ac3ffb093 100644 --- a/bins/revme/src/cmd/statetest/merkle_trie.rs +++ b/bins/revme/src/cmd/statetest/merkle_trie.rs @@ -5,7 +5,7 @@ use hash_db::Hasher; use plain_hasher::PlainHasher; use revm::{ context::result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, - database::{EmptyDB, PlainAccount, State}, + database::{bal::EvmDatabaseError, EmptyDB, PlainAccount, State}, primitives::{keccak256, Address, Log, B256, U256}, }; use triehash::sec_trie_root; @@ -16,7 +16,10 @@ pub struct TestValidationResult { } pub fn compute_test_roots( - exec_result: &Result, EVMError>, + exec_result: &Result< + ExecutionResult, + EVMError, InvalidTransaction>, + >, db: &State, ) -> TestValidationResult { TestValidationResult { diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 849748d51b..3e277f17fa 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -6,7 +6,7 @@ use revm::{ result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, Cfg, }, - database, + database::{self, bal::EvmDatabaseError}, database_interface::EmptyDB, inspector::{inspectors::TracerEip3155, InspectCommitEvm}, primitives::{hardfork::SpecId, Bytes, B256, U256}, @@ -152,7 +152,10 @@ struct DebugContext<'a> { fn build_json_output( test: &Test, test_name: &str, - exec_result: &Result, EVMError>, + exec_result: &Result< + ExecutionResult, + EVMError, InvalidTransaction>, + >, validation: &TestValidationResult, spec: SpecId, error: Option, @@ -175,7 +178,10 @@ fn build_json_output( } fn format_evm_result( - exec_result: &Result, EVMError>, + exec_result: &Result< + ExecutionResult, + EVMError, InvalidTransaction>, + >, ) -> String { match exec_result { Ok(r) => match r { @@ -189,7 +195,10 @@ fn format_evm_result( fn validate_exception( test: &Test, - exec_result: &Result, EVMError>, + exec_result: &Result< + ExecutionResult, + EVMError, InvalidTransaction>, + >, ) -> Result { match (&test.expect_exception, exec_result) { (None, Ok(_)) => Ok(false), // No exception expected, execution succeeded @@ -220,7 +229,10 @@ fn check_evm_execution( test: &Test, expected_output: Option<&Bytes>, test_name: &str, - exec_result: &Result, EVMError>, + exec_result: &Result< + ExecutionResult, + EVMError, InvalidTransaction>, + >, db: &mut database::State, spec: SpecId, print_json_outcome: bool, @@ -437,6 +449,7 @@ fn execute_single_test(ctx: TestExecutionContext) -> Result<(), TestErrorKind> { }; *ctx.elapsed.lock().unwrap() += timer.elapsed(); + let exec_result = exec_result; // Check results check_evm_execution( ctx.test, diff --git a/crates/bytecode/src/bytecode.rs b/crates/bytecode/src/bytecode.rs index d3af31d5a0..162d0839b4 100644 --- a/crates/bytecode/src/bytecode.rs +++ b/crates/bytecode/src/bytecode.rs @@ -8,16 +8,19 @@ use crate::{ eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES}, BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode, }; -use primitives::{alloy_primitives::Sealable, keccak256, Address, Bytes, B256, KECCAK_EMPTY}; +use primitives::{ + alloy_primitives::Sealable, keccak256, Address, Bytes, OnceLock, B256, KECCAK_EMPTY, +}; +use std::sync::Arc; /// Main bytecode structure with all variants. #[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Bytecode { /// EIP-7702 delegated bytecode - Eip7702(Eip7702Bytecode), + Eip7702(Arc), /// The bytecode has been analyzed for valid jump destinations. - LegacyAnalyzed(LegacyAnalyzedBytecode), + LegacyAnalyzed(Arc), } impl Default for Bytecode { @@ -38,7 +41,10 @@ impl Bytecode { /// Creates a new legacy analyzed [`Bytecode`] with exactly one STOP opcode. #[inline] pub fn new() -> Self { - Self::LegacyAnalyzed(LegacyAnalyzedBytecode::default()) + static DEFAULT_BYTECODE: OnceLock = OnceLock::new(); + DEFAULT_BYTECODE + .get_or_init(|| Self::LegacyAnalyzed(Arc::new(LegacyAnalyzedBytecode::default()))) + .clone() } /// Returns jump table if bytecode is analyzed. @@ -69,7 +75,7 @@ impl Bytecode { /// Creates a new legacy [`Bytecode`]. #[inline] pub fn new_legacy(raw: Bytes) -> Self { - Self::LegacyAnalyzed(LegacyRawBytecode(raw).into_analyzed()) + Self::LegacyAnalyzed(Arc::new(LegacyRawBytecode(raw).into_analyzed())) } /// Creates a new raw [`Bytecode`]. @@ -85,7 +91,7 @@ impl Bytecode { /// Creates a new EIP-7702 [`Bytecode`] from [`Address`]. #[inline] pub fn new_eip7702(address: Address) -> Self { - Self::Eip7702(Eip7702Bytecode::new(address)) + Self::Eip7702(Arc::new(Eip7702Bytecode::new(address))) } /// Creates a new raw [`Bytecode`]. @@ -97,7 +103,7 @@ impl Bytecode { match prefix { Some(prefix) if prefix == &EIP7702_MAGIC_BYTES => { let eip7702 = Eip7702Bytecode::new_raw(bytes)?; - Ok(Self::Eip7702(eip7702)) + Ok(Self::Eip7702(Arc::new(eip7702))) } _ => Ok(Self::new_legacy(bytes)), } @@ -110,11 +116,11 @@ impl Bytecode { /// For possible panics see [`LegacyAnalyzedBytecode::new`]. #[inline] pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self { - Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new( + Self::LegacyAnalyzed(Arc::new(LegacyAnalyzedBytecode::new( bytecode, original_len, jump_table, - )) + ))) } /// Returns a reference to the bytecode. diff --git a/crates/bytecode/src/iter.rs b/crates/bytecode/src/iter.rs index 7abc25cc0f..e8f7275f87 100644 --- a/crates/bytecode/src/iter.rs +++ b/crates/bytecode/src/iter.rs @@ -119,7 +119,7 @@ mod tests { opcode::STOP, ]; let raw_bytecode = LegacyRawBytecode(Bytes::from(bytecode_data)); - let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed()); + let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed_arc()); let opcodes: Vec = bytecode.iter_opcodes().collect(); // We should only see the opcodes, not the immediates assert_eq!( @@ -144,7 +144,7 @@ mod tests { opcode::STOP, ]; let raw_bytecode = LegacyRawBytecode(Bytes::from(bytecode_data)); - let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed()); + let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed_arc()); let opcodes: Vec = bytecode.iter_opcodes().collect(); @@ -207,7 +207,7 @@ mod tests { ]; let raw_bytecode = LegacyRawBytecode(Bytes::from(bytecode_data)); - let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed()); + let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed_arc()); // Use the iterator directly let iter = BytecodeIterator::new(&bytecode); @@ -255,7 +255,7 @@ mod tests { opcode::STOP, ]; let raw_bytecode = LegacyRawBytecode(Bytes::from(bytecode_data)); - let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed()); + let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed_arc()); let mut iter = bytecode.iter_opcodes(); @@ -287,7 +287,7 @@ mod tests { // Empty bytecode (just STOP) let bytecode_data = vec![opcode::STOP]; let raw_bytecode = LegacyRawBytecode(Bytes::from(bytecode_data)); - let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed()); + let bytecode = Bytecode::LegacyAnalyzed(raw_bytecode.into_analyzed_arc()); let opcodes: Vec = bytecode.iter_opcodes().collect(); assert_eq!(opcodes, vec![opcode::STOP]); diff --git a/crates/bytecode/src/legacy/raw.rs b/crates/bytecode/src/legacy/raw.rs index 20ef7ba885..00868430a2 100644 --- a/crates/bytecode/src/legacy/raw.rs +++ b/crates/bytecode/src/legacy/raw.rs @@ -1,6 +1,7 @@ use super::LegacyAnalyzedBytecode; use core::ops::Deref; use primitives::Bytes; +use std::sync::Arc; /// Used only as intermediate representation for legacy bytecode. /// @@ -14,6 +15,11 @@ impl LegacyRawBytecode { pub fn into_analyzed(self) -> LegacyAnalyzedBytecode { LegacyAnalyzedBytecode::analyze(self.0) } + + /// Analyzes the bytecode, instantiating a [`LegacyAnalyzedBytecode`] and wrapping it in an [`Arc`]. + pub fn into_analyzed_arc(self) -> Arc { + Arc::new(self.into_analyzed()) + } } impl From for LegacyRawBytecode { diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index 34f4e7d70e..a8755aa274 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -110,7 +110,7 @@ impl JournalInner { spec, warm_addresses, } = self; - // Spec precompiles and state are not changed. It is always set again execution. + // Spec, precompiles, BAL and state are not changed. It is always set again execution. let _ = spec; let _ = state; transient_storage.clear(); @@ -123,6 +123,7 @@ impl JournalInner { warm_addresses.clear_coinbase_and_access_list(); // increment transaction id. *transaction_id += 1; + logs.clear(); } @@ -436,7 +437,8 @@ impl JournalInner { target_acc.info.balance = new_balance; // safe to decrement for the caller as balance check is already done. - self.state.get_mut(&caller).unwrap().info.balance -= balance; + let caller_account = self.state.get_mut(&caller).unwrap(); + caller_account.info.balance -= balance; // add journal entry of transferred balance last_journal.push(ENTRY::balance_transfer(caller, target_address, balance)); @@ -750,6 +752,9 @@ impl JournalInner { account.selfdestruct(); account.unmark_selfdestructed_locally(); } + // set original info to current info. + *account.original_info = account.info.clone(); + // unmark locally created account.unmark_created_locally(); @@ -940,6 +945,7 @@ mod tests { nonce: 1, code_hash: KECCAK_EMPTY, code: Some(Bytecode::default()), + account_id: None, }; journal .state diff --git a/crates/database/interface/src/async_db.rs b/crates/database/interface/src/async_db.rs index db0325f739..c1cbb260c0 100644 --- a/crates/database/interface/src/async_db.rs +++ b/crates/database/interface/src/async_db.rs @@ -33,6 +33,20 @@ pub trait DatabaseAsync { index: StorageKey, ) -> impl Future> + Send; + /// Gets storage value of account by its id. + /// + /// Default implementation is to call [`DatabaseAsync::storage_async`] method. + #[inline] + fn storage_by_account_id_async( + &mut self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> impl Future> + Send { + let _ = account_id; + self.storage_async(address, storage_key) + } + /// Gets block hash by block number. fn block_hash_async( &mut self, @@ -68,6 +82,20 @@ pub trait DatabaseAsyncRef { index: StorageKey, ) -> impl Future> + Send; + /// Gets storage value of account by its id. + /// + /// Default implementation is to call [`DatabaseAsyncRef::storage_async_ref`] method. + #[inline] + fn storage_by_account_id_async_ref( + &self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> impl Future> + Send { + let _ = account_id; + self.storage_async_ref(address, storage_key) + } + /// Gets block hash by block number. fn block_hash_async_ref( &self, @@ -141,6 +169,22 @@ impl Database for WrapDatabaseAsync { self.rt.block_on(self.db.storage_async(address, index)) } + /// Gets storage value of account by its id. + /// + /// Default implementation is to call [`DatabaseRef::storage_ref`] method. + #[inline] + fn storage_by_account_id( + &mut self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + self.rt.block_on( + self.db + .storage_by_account_id_async(address, account_id, storage_key), + ) + } + #[inline] fn block_hash(&mut self, number: u64) -> Result { self.rt.block_on(self.db.block_hash_async(number)) @@ -169,6 +213,19 @@ impl DatabaseRef for WrapDatabaseAsync { self.rt.block_on(self.db.storage_async_ref(address, index)) } + #[inline] + fn storage_by_account_id_ref( + &self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + self.rt.block_on( + self.db + .storage_by_account_id_async_ref(address, account_id, storage_key), + ) + } + #[inline] fn block_hash_ref(&self, number: u64) -> Result { self.rt.block_on(self.db.block_hash_async_ref(number)) diff --git a/crates/database/interface/src/bal.rs b/crates/database/interface/src/bal.rs new file mode 100644 index 0000000000..e97768934a --- /dev/null +++ b/crates/database/interface/src/bal.rs @@ -0,0 +1,391 @@ +//! Database implementation for BAL. +use core::{ + error::Error, + fmt::Display, + ops::{Deref, DerefMut}, +}; +use primitives::{Address, StorageKey, StorageValue, B256}; +use state::{ + bal::{alloy::AlloyBal, Bal, BalError}, + Account, AccountInfo, Bytecode, EvmState, +}; +use std::sync::Arc; + +use crate::{DBErrorMarker, Database, DatabaseCommit}; + +/// Contains both the BAL for reads and BAL builders. +#[derive(Clone, Default, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BalState { + /// BAL used to execute transactions. + pub bal: Option>, + /// BAL builder that is used to build BAL. + /// It is create from State output of transaction execution. + pub bal_builder: Option, + /// BAL index, used by bal to fetch appropriate values and used by bal_builder on commit + /// to submit changes. + pub bal_index: u64, +} + +impl BalState { + /// Create a new BAL manager. + #[inline] + pub fn new() -> Self { + Self::default() + } + + /// Reset BAL index. + #[inline] + pub fn reset_bal_index(&mut self) { + self.bal_index = 0; + } + + /// Bump BAL index. + #[inline] + pub fn bump_bal_index(&mut self) { + self.bal_index += 1; + } + + /// Get BAL index. + #[inline] + pub fn bal_index(&self) -> u64 { + self.bal_index + } + + /// Get BAL. + #[inline] + pub fn bal(&self) -> Option> { + self.bal.clone() + } + + /// Get BAL builder. + #[inline] + pub fn bal_builder(&self) -> Option { + self.bal_builder.clone() + } + + /// Set BAL. + #[inline] + pub fn with_bal(mut self, bal: Arc) -> Self { + self.bal = Some(bal); + self + } + + /// Set BAL builder. + #[inline] + pub fn with_bal_builder(mut self) -> Self { + self.bal_builder = Some(Bal::new()); + self + } + + /// Take BAL builder. + #[inline] + pub fn take_built_bal(&mut self) -> Option { + self.reset_bal_index(); + self.bal_builder.take() + } + + /// Take built BAL as AlloyBAL. + #[inline] + pub fn take_built_alloy_bal(&mut self) -> Option { + self.take_built_bal().map(|bal| bal.into_alloy_bal()) + } + + /// Get account id from BAL. + /// + /// Return Error if BAL is not found and Account is not + #[inline] + pub fn get_account_id(&self, address: &Address) -> Result, BalError> { + self.bal + .as_ref() + .map(|bal| { + bal.accounts + .get_full(address) + .map(|i| i.0) + .ok_or(BalError::AccountNotFound) + }) + .transpose() + } + + /// Fetch account from database and apply bal changes to it. + /// + /// Return Some if BAL is existing, None if not. + /// Return Err if Accounts is not found inside BAL. + /// And return true + #[inline] + pub fn basic( + &self, + address: Address, + basic: &mut Option, + ) -> Result { + let Some(account_id) = self.get_account_id(&address)? else { + return Ok(false); + }; + Ok(self.basic_by_account_id(account_id, basic)) + } + + /// Fetch account from database and apply bal changes to it by account id. + /// + /// Panics if account_id is invalid + #[inline] + pub fn basic_by_account_id(&self, account_id: usize, basic: &mut Option) -> bool { + if let Some(bal) = &self.bal { + let is_none = basic.is_none(); + let mut bal_basic = core::mem::take(basic).unwrap_or_default(); + bal.populate_account_info(account_id, self.bal_index, &mut bal_basic) + .expect("Invalid account id"); + + // if it is not changed, check if it is none and return it. + if is_none { + return true; + } + + *basic = Some(bal_basic); + return true; + } + false + } + + /// Get storage value from BAL. + /// + /// Return Err if bal is present but account or storage is not found inside BAL. + #[inline] + pub fn storage( + &self, + account: &Address, + storage_key: StorageKey, + ) -> Result, BalError> { + let Some(bal) = &self.bal else { + return Ok(None); + }; + + let Some(bal_account) = bal.accounts.get(account) else { + return Err(BalError::AccountNotFound); + }; + + Ok(bal_account + .storage + .get_bal_writes(storage_key)? + .get(self.bal_index)) + } + + /// Get the storage value by account id. + /// + /// Return Err if bal is present but account or storage is not found inside BAL. + /// + /// + #[inline] + pub fn storage_by_account_id( + &self, + account_id: usize, + storage_key: StorageKey, + ) -> Result, BalError> { + let Some(bal) = &self.bal else { + return Ok(None); + }; + + let Some((_, bal_account)) = bal.accounts.get_index(account_id) else { + return Err(BalError::AccountNotFound); + }; + + Ok(bal_account + .storage + .get_bal_writes(storage_key)? + .get(self.bal_index)) + } + + /// Apply changed from EvmState to the bal_builder + #[inline] + pub fn commit(&mut self, changes: &EvmState) { + if let Some(bal_builder) = &mut self.bal_builder { + for (address, account) in changes.iter() { + bal_builder.update_account(self.bal_index, *address, account); + } + } + } + + /// Commit one account to the BAL builder. + #[inline] + pub fn commit_one(&mut self, address: Address, account: &Account) { + if let Some(bal_builder) = &mut self.bal_builder { + bal_builder.update_account(self.bal_index, address, account); + } + } +} + +/// Database implementation for BAL. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BalDatabase { + /// BAL manager. + pub bal_state: BalState, + /// Database. + pub db: DB, +} + +impl Deref for BalDatabase { + type Target = DB; + + fn deref(&self) -> &Self::Target { + &self.db + } +} + +impl DerefMut for BalDatabase { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.db + } +} + +impl BalDatabase { + /// Create a new BAL database. + #[inline] + pub fn new(db: DB) -> Self { + Self { + bal_state: BalState::default(), + db, + } + } + + /// With BAL. + #[inline] + pub fn with_bal_option(self, bal: Option>) -> Self { + Self { + bal_state: BalState { + bal, + ..self.bal_state + }, + ..self + } + } + + /// With BAL builder. + #[inline] + pub fn with_bal_builder(self) -> Self { + Self { + bal_state: self.bal_state.with_bal_builder(), + ..self + } + } + + /// Reset BAL index. + #[inline] + pub fn reset_bal_index(mut self) -> Self { + self.bal_state.reset_bal_index(); + self + } + + /// Bump BAL index. + #[inline] + pub fn bump_bal_index(&mut self) { + self.bal_state.bump_bal_index(); + } +} + +/// Error type from database. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum EvmDatabaseError { + /// BAL error. + Bal(BalError), + /// External database error. + Database(ERROR), +} + +impl From for EvmDatabaseError { + fn from(error: BalError) -> Self { + Self::Bal(error) + } +} + +impl DBErrorMarker for EvmDatabaseError {} + +impl Display for EvmDatabaseError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::Bal(error) => write!(f, "Bal error: {error}"), + Self::Database(error) => write!(f, "Database error: {error}"), + } + } +} + +impl Error for EvmDatabaseError {} + +impl EvmDatabaseError { + /// Convert BAL database error to database error. + /// + /// Panics if BAL error is present. + pub fn into_external_error(self) -> ERROR { + match self { + Self::Bal(_) => panic!("Expected database error, got BAL error"), + Self::Database(error) => error, + } + } +} + +impl Database for BalDatabase { + type Error = EvmDatabaseError; + + #[inline] + fn basic(&mut self, address: Address) -> Result, Self::Error> { + let account_id = self.bal_state.get_account_id(&address)?; + + let mut account = self.db.basic(address).map_err(EvmDatabaseError::Database)?; + + if let Some(account_id) = account_id { + self.bal_state.basic_by_account_id(account_id, &mut account); + } + + Ok(account) + } + + #[inline] + fn code_by_hash(&mut self, code_hash: B256) -> Result { + self.db + .code_by_hash(code_hash) + .map_err(EvmDatabaseError::Database) + } + + #[inline] + fn storage(&mut self, address: Address, key: StorageKey) -> Result { + if let Some(storage) = self.bal_state.storage(&address, key)? { + return Ok(storage); + } + + self.db + .storage(address, key) + .map_err(EvmDatabaseError::Database) + } + + #[inline] + fn storage_by_account_id( + &mut self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + if let Some(value) = self + .bal_state + .storage_by_account_id(account_id, storage_key)? + { + return Ok(value); + } + + self.db + .storage(address, storage_key) + .map_err(EvmDatabaseError::Database) + } + + fn block_hash(&mut self, number: u64) -> Result { + self.db + .block_hash(number) + .map_err(EvmDatabaseError::Database) + } +} + +impl DatabaseCommit for BalDatabase { + fn commit(&mut self, changes: EvmState) { + self.bal_state.commit(&changes); + self.db.commit(changes); + } +} diff --git a/crates/database/interface/src/either.rs b/crates/database/interface/src/either.rs index a22210cb4b..ce1e7d1336 100644 --- a/crates/database/interface/src/either.rs +++ b/crates/database/interface/src/either.rs @@ -43,6 +43,18 @@ where Self::Right(db) => db.block_hash(number), } } + + fn storage_by_account_id( + &mut self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + match self { + Self::Left(db) => db.storage_by_account_id(address, account_id, storage_key), + Self::Right(db) => db.storage_by_account_id(address, account_id, storage_key), + } + } } impl DatabaseCommit for Either @@ -96,4 +108,16 @@ where Self::Right(db) => db.block_hash_ref(number), } } + + fn storage_by_account_id_ref( + &self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + match self { + Self::Left(db) => db.storage_by_account_id_ref(address, account_id, storage_key), + Self::Right(db) => db.storage_by_account_id_ref(address, account_id, storage_key), + } + } } diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index 29d76df3eb..6a2427e609 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -29,6 +29,7 @@ pub const BENCH_CALLER_BALANCE: U256 = TEST_BALANCE; #[cfg(feature = "asyncdb")] pub mod async_db; +pub mod bal; pub mod either; pub mod empty_db; pub mod erased_error; @@ -63,6 +64,21 @@ pub trait Database { fn storage(&mut self, address: Address, index: StorageKey) -> Result; + /// Gets storage value of account by its id. By default call [`Database::storage`] method. + /// + /// If basic account sets account_id inside [`AccountInfo::account_id`], evm will call this + /// function with that given account_id. This can be useful if IndexMap is used to get faster access to the account. + #[inline] + fn storage_by_account_id( + &mut self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + let _ = account_id; + self.storage(address, storage_key) + } + /// Gets block hash by block number. fn block_hash(&mut self, number: u64) -> Result; } @@ -105,6 +121,20 @@ pub trait DatabaseRef { fn storage_ref(&self, address: Address, index: StorageKey) -> Result; + /// Gets storage value of account by its id. + /// + /// Default implementation is to call [`DatabaseRef::storage_ref`] method. + #[inline] + fn storage_by_account_id_ref( + &self, + address: Address, + account_id: usize, + storage_key: StorageKey, + ) -> Result { + let _ = account_id; + self.storage_ref(address, storage_key) + } + /// Gets block hash by block number. fn block_hash_ref(&self, number: u64) -> Result; } diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index a49e1e2189..e43f0dc2ca 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -85,6 +85,7 @@ impl CacheDB> { block_hashes, }, db: mut inner, + .. } = self; inner.cache.accounts.extend(accounts); @@ -469,6 +470,7 @@ impl Database for BenchmarkDB { balance: BENCH_TARGET_BALANCE, code: Some(self.0.clone()), code_hash: self.1, + ..Default::default() })); } if address == BENCH_CALLER { @@ -477,6 +479,7 @@ impl Database for BenchmarkDB { balance: BENCH_CALLER_BALANCE, code: None, code_hash: KECCAK_EMPTY, + ..Default::default() })); } Ok(None) diff --git a/crates/database/src/states/bundle_state.rs b/crates/database/src/states/bundle_state.rs index 79e9ad6b1f..8c28c7ff72 100644 --- a/crates/database/src/states/bundle_state.rs +++ b/crates/database/src/states/bundle_state.rs @@ -872,8 +872,7 @@ mod tests { let acc1 = AccountInfo { balance: U256::from(10), nonce: 1, - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }; let mut bundle_state = BundleState::default(); @@ -923,8 +922,7 @@ mod tests { Some(AccountInfo { nonce: 1, balance: U256::from(10), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }), HashMap::from_iter([ (slot1(), (StorageValue::from(0), StorageValue::from(10))), @@ -937,8 +935,7 @@ mod tests { Some(AccountInfo { nonce: 1, balance: U256::from(10), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }), HashMap::default(), ), @@ -968,8 +965,7 @@ mod tests { Some(AccountInfo { nonce: 3, balance: U256::from(20), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }), HashMap::from_iter([(slot1(), (StorageValue::from(0), StorageValue::from(15)))]), )], @@ -978,8 +974,7 @@ mod tests { Some(Some(AccountInfo { nonce: 1, balance: U256::from(10), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() })), vec![(slot1(), StorageValue::from(10))], )]], @@ -995,8 +990,7 @@ mod tests { AccountInfo { nonce: 1, balance: U256::from(10), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }, ) .state_storage( @@ -1009,8 +1003,7 @@ mod tests { AccountInfo { nonce: 1, balance: U256::from(10), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }, ) .revert_address(0, account1()) @@ -1028,8 +1021,7 @@ mod tests { AccountInfo { nonce: 3, balance: U256::from(20), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }, ) .state_storage( @@ -1043,8 +1035,7 @@ mod tests { Some(Some(AccountInfo { nonce: 1, balance: U256::from(10), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() })), ) .revert_storage(0, account1(), vec![(slot1(), StorageValue::from(10))]) diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index ebb75f6188..c58f9e60f6 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -90,13 +90,18 @@ impl CacheState { /// Applies output of revm execution and create account transitions that are used to build BundleState. #[inline] - pub fn apply_evm_state( + pub fn apply_evm_state( &mut self, evm_state: impl IntoIterator, - ) -> Vec<(Address, TransitionAccount)> { + mut inspect: F, + ) -> Vec<(Address, TransitionAccount)> + where + F: FnMut(&Address, &Account), + { evm_state .into_iter() .filter_map(|(address, account)| { + inspect(&address, &account); self.apply_account_state(address, account) .map(|transition| (address, transition)) }) @@ -169,7 +174,7 @@ impl CacheState { /// Applies updated account state to the cached account. /// /// Returns account transition if applicable. - fn apply_account_state( + pub(crate) fn apply_account_state( &mut self, address: Address, account: Account, diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index d1b752795a..775e6edcee 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -3,12 +3,19 @@ use super::{ CacheAccount, StateBuilder, TransitionAccount, TransitionState, }; use bytecode::Bytecode; -use database_interface::{Database, DatabaseCommit, DatabaseRef, EmptyDB}; +use database_interface::{ + bal::{BalState, EvmDatabaseError}, + Database, DatabaseCommit, DatabaseRef, EmptyDB, +}; use primitives::{hash_map, Address, HashMap, StorageKey, StorageValue, B256, BLOCK_HASH_HISTORY}; -use state::{Account, AccountInfo}; +use state::{ + bal::{alloy::AlloyBal, Bal}, + Account, AccountInfo, +}; use std::{ boxed::Box, collections::{btree_map, BTreeMap}, + sync::Arc, }; /// Database boxed with a lifetime and Send @@ -62,6 +69,10 @@ pub struct State { /// /// The fork block is different or some blocks are not saved inside database. pub block_hashes: BTreeMap, + /// BAL state. + /// + /// Can contain both the BAL for reads and BAL builder that is used to build BAL. + pub bal_state: BalState, } // Have ability to call State::builder without having to specify the type. @@ -194,39 +205,46 @@ impl State { pub fn take_bundle(&mut self) -> BundleState { core::mem::take(&mut self.bundle_state) } -} -impl Database for State { - type Error = DB::Error; + /// Takes build bal from bal state. + #[inline] + pub fn take_built_bal(&mut self) -> Option { + self.bal_state.take_built_bal() + } - fn basic(&mut self, address: Address) -> Result, Self::Error> { - self.load_cache_account(address).map(|a| a.account_info()) + /// Takes built alloy bal from bal state. + #[inline] + pub fn take_built_alloy_bal(&mut self) -> Option { + self.bal_state.take_built_alloy_bal() } - fn code_by_hash(&mut self, code_hash: B256) -> Result { - let res = match self.cache.contracts.entry(code_hash) { - hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()), - hash_map::Entry::Vacant(entry) => { - if self.use_preloaded_bundle { - if let Some(code) = self.bundle_state.contracts.get(&code_hash) { - entry.insert(code.clone()); - return Ok(code.clone()); - } - } - // If not found in bundle ask database - let code = self.database.code_by_hash(code_hash)?; - entry.insert(code.clone()); - Ok(code) - } - }; - res + /// Bump BAL index. + #[inline] + pub fn bump_bal_index(&mut self) { + self.bal_state.bump_bal_index(); } - fn storage( - &mut self, - address: Address, - index: StorageKey, - ) -> Result { + /// Set BAL index. + #[inline] + pub fn set_bal_index(&mut self, index: u64) { + self.bal_state.bal_index = index; + } + + /// Reset BAL index. + #[inline] + pub fn reset_bal_index(&mut self) { + self.bal_state.reset_bal_index(); + } + + /// Set BAL. + #[inline] + pub fn set_bal(&mut self, bal: Option>) { + self.bal_state.bal = bal; + } + + /// Gets storage value of address at index. + #[inline] + fn storage(&mut self, address: Address, index: StorageKey) -> Result { // If account is not found in cache, it will be loaded from database. let account = Self::load_cache_account_with( &mut self.cache, @@ -258,12 +276,93 @@ impl Database for State { .transpose()? .unwrap_or_default()) } +} + +impl Database for State { + type Error = EvmDatabaseError; + + fn basic(&mut self, address: Address) -> Result, Self::Error> { + // if bal is existing but account is not found, error will be returned. + let account_id = self + .bal_state + .get_account_id(&address) + .map_err(EvmDatabaseError::Bal)?; + + let mut basic = self + .load_cache_account(address) + .map(|a| a.account_info()) + .map_err(EvmDatabaseError::Database)?; + // will populate account code if there was a bal change to it. If there is no change + // it will be fetched in code_by_hash. + if let Some(account_id) = account_id { + self.bal_state.basic_by_account_id(account_id, &mut basic); + } + Ok(basic) + } + + fn code_by_hash(&mut self, code_hash: B256) -> Result { + let res = match self.cache.contracts.entry(code_hash) { + hash_map::Entry::Occupied(entry) => Ok(entry.get().clone()), + hash_map::Entry::Vacant(entry) => { + if self.use_preloaded_bundle { + if let Some(code) = self.bundle_state.contracts.get(&code_hash) { + entry.insert(code.clone()); + return Ok(code.clone()); + } + } + // If not found in bundle ask database + let code = self + .database + .code_by_hash(code_hash) + .map_err(EvmDatabaseError::Database)?; + entry.insert(code.clone()); + Ok(code) + } + }; + res + } + + fn storage( + &mut self, + address: Address, + index: StorageKey, + ) -> Result { + if let Some(storage) = self + .bal_state + .storage(&address, index) + .map_err(EvmDatabaseError::Bal)? + { + // return bal value if it is found + return Ok(storage); + } + self.storage(address, index) + .map_err(EvmDatabaseError::Database) + } + + fn storage_by_account_id( + &mut self, + address: Address, + account_id: usize, + key: StorageKey, + ) -> Result { + if let Some(storage) = self.bal_state.storage_by_account_id(account_id, key)? { + return Ok(storage); + } + + self.database + .storage(address, key) + .map_err(EvmDatabaseError::Database) + } fn block_hash(&mut self, number: u64) -> Result { match self.block_hashes.entry(number) { btree_map::Entry::Occupied(entry) => Ok(*entry.get()), btree_map::Entry::Vacant(entry) => { - let ret = *entry.insert(self.database.block_hash(number)?); + let ret = *entry.insert( + self.database + .block_hash(number) + .map_err(EvmDatabaseError::Database)?, + ); // Prune all hashes that are older than BLOCK_HASH_HISTORY let last_block = number.saturating_sub(BLOCK_HASH_HISTORY); @@ -283,14 +382,17 @@ impl Database for State { impl DatabaseCommit for State { fn commit(&mut self, changes: HashMap) { - let transitions = self.cache.apply_evm_state(changes); + self.bal_state.commit(&changes); + let transitions = self.cache.apply_evm_state(changes, |_, _| {}); if let Some(s) = self.transition_state.as_mut() { s.add_transitions(transitions) } } fn commit_iter(&mut self, changes: impl IntoIterator) { - let transitions = self.cache.apply_evm_state(changes); + let transitions = self.cache.apply_evm_state(changes, |address, account| { + self.bal_state.commit_one(*address, account); + }); if let Some(s) = self.transition_state.as_mut() { s.add_transitions(transitions) } @@ -298,21 +400,42 @@ impl DatabaseCommit for State { } impl DatabaseRef for State { - type Error = DB::Error; + type Error = EvmDatabaseError; fn basic_ref(&self, address: Address) -> Result, Self::Error> { + // if bal is present and account is not found, error will be returned. + let account_id = self.bal_state.get_account_id(&address)?; + // Account is already in cache + let mut loaded_account = None; if let Some(account) = self.cache.accounts.get(&address) { - return Ok(account.account_info()); - } + loaded_account = Some(account.account_info()); + }; + // If bundle state is used, check if account is in bundle state - if self.use_preloaded_bundle { + if self.use_preloaded_bundle && loaded_account.is_none() { if let Some(account) = self.bundle_state.account(&address) { - return Ok(account.account_info()); + loaded_account = Some(account.account_info()); } } + // If not found, load it from database - self.database.basic_ref(address) + if loaded_account.is_none() { + loaded_account = Some( + self.database + .basic_ref(address) + .map_err(EvmDatabaseError::Database)?, + ); + } + + // safe to unwrap as it in some in condition above + let mut account = loaded_account.unwrap(); + + // if it is inside bal, overwrite the account with the bal changes. + if let Some(account_id) = account_id { + self.bal_state.basic_by_account_id(account_id, &mut account); + } + Ok(account) } fn code_by_hash_ref(&self, code_hash: B256) -> Result { @@ -327,7 +450,9 @@ impl DatabaseRef for State { } } // If not found, load it from database - self.database.code_by_hash_ref(code_hash) + self.database + .code_by_hash_ref(code_hash) + .map_err(EvmDatabaseError::Database) } fn storage_ref( @@ -335,6 +460,11 @@ impl DatabaseRef for State { address: Address, index: StorageKey, ) -> Result { + // if bal has storage value, return it + if let Some(storage) = self.bal_state.storage(&address, index)? { + return Ok(storage); + } + // Check if account is in cache, the account is not guaranteed to be loaded if let Some(account) = self.cache.accounts.get(&address) { if let Some(plain_account) = &account.account { @@ -349,8 +479,11 @@ impl DatabaseRef for State { } } } + // If not found, load it from database - self.database.storage_ref(address, index) + self.database + .storage_ref(address, index) + .map_err(EvmDatabaseError::Database) } fn block_hash_ref(&self, number: u64) -> Result { @@ -358,7 +491,9 @@ impl DatabaseRef for State { return Ok(*entry); } // If not found, load it from database - self.database.block_hash_ref(number) + self.database + .block_hash_ref(number) + .map_err(EvmDatabaseError::Database) } } diff --git a/crates/database/src/states/state_builder.rs b/crates/database/src/states/state_builder.rs index 1b42990483..3148c271b7 100644 --- a/crates/database/src/states/state_builder.rs +++ b/crates/database/src/states/state_builder.rs @@ -1,7 +1,10 @@ use super::{cache::CacheState, state::DBBox, BundleState, State, TransitionState}; -use database_interface::{DBErrorMarker, Database, DatabaseRef, EmptyDB, WrapDatabaseRef}; +use database_interface::{ + bal::BalState, DBErrorMarker, Database, DatabaseRef, EmptyDB, WrapDatabaseRef, +}; use primitives::B256; -use std::collections::BTreeMap; +use state::bal::Bal; +use std::{collections::BTreeMap, sync::Arc}; /// Allows building of State and initializing it with different options. #[derive(Clone, Debug, PartialEq, Eq)] @@ -29,6 +32,8 @@ pub struct StateBuilder { with_background_transition_merge: bool, /// If we want to set different block hashes, with_block_hashes: BTreeMap, + /// BAL state. + bal_state: BalState, } impl StateBuilder { @@ -58,6 +63,7 @@ impl StateBuilder { with_bundle_update: false, with_background_transition_merge: false, with_block_hashes: BTreeMap::new(), + bal_state: BalState::default(), } } @@ -73,6 +79,7 @@ impl StateBuilder { with_bundle_update: self.with_bundle_update, with_background_transition_merge: self.with_background_transition_merge, with_block_hashes: self.with_block_hashes, + bal_state: self.bal_state, } } @@ -158,6 +165,18 @@ impl StateBuilder { } } + /// With BAL. + pub fn with_bal(mut self, bal: Arc) -> Self { + self.bal_state.bal = Some(bal); + self + } + + /// With BAL builder. + pub fn with_bal_builder(mut self) -> Self { + self.bal_state.bal_builder = Some(Bal::new()); + self + } + /// Builds the State with the configured settings. pub fn build(mut self) -> State { let use_preloaded_bundle = if self.with_cache_prestate.is_some() { @@ -175,6 +194,7 @@ impl StateBuilder { bundle_state: self.with_bundle_prestate.unwrap_or_default(), use_preloaded_bundle, block_hashes: self.with_block_hashes, + bal_state: self.bal_state, } } } diff --git a/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json index ce989e10db..372cec3c7b 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json @@ -32,6 +32,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json index 0769dd9c2f..58a09b2f05 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json @@ -27,6 +27,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched", "storage": {}, "transaction_id": 0 @@ -54,6 +74,28 @@ "code_hash": "0x7b2ab94bb7d45041581aa3757ae020084674ccad6f75dc3750eb2ea8a92c4e9a", "nonce": 1 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x5000", + "jump_table": { + "bits": 1, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 1 + } + }, + "code_hash": "0x7b2ab94bb7d45041581aa3757ae020084674ccad6f75dc3750eb2ea8a92c4e9a", + "nonce": 1 + }, "status": "Cold", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json index 9ab987baba..0e26bc9093 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json index 4d1f78ca80..950f569e48 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json index 5e9e175426..9455411d81 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json index d2a41cfed6..7c18145fba 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json index d825d723b8..7dc99a0591 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json index 58c506307a..63122526d7 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json index c050e75ec1..25010ee722 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json index bae68df493..4aeddf5b9c 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json index 59b81d7b5e..9cc62f89ea 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json index 87cb378c40..1d1909f9b0 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json index 25718c3549..853528fd5a 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json index 4e12839026..2c1db84393 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json index 250bcb34c5..fe3a4021ac 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json index cc66059ecf..89e9095030 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json index c550b7a9c7..17dc87be7f 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json index e3ecc1304f..1ba8f45422 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json index fadbf7cb6f..ae98ddb0f9 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json index 4f98b9d9ad..bf5699cb21 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json index b457155b93..26f2d94179 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json index a21e7ce5e3..60b5ebf8b4 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json @@ -31,6 +31,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -56,6 +76,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -81,6 +121,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -106,6 +166,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -131,6 +211,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json index 5dcc6cd143..a5bc954780 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_pre_regolith.json @@ -32,6 +32,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -57,6 +77,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -82,6 +122,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -107,6 +167,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -132,6 +212,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -157,6 +257,12 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": null, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json b/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json deleted file mode 100644 index 5dcc6cd143..0000000000 --- a/crates/ee-tests/tests/op_revm_testdata/test_l1block_load_for_regolit.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "result": { - "Success": { - "gas_refunded": 0, - "gas_used": 21000, - "logs": [], - "output": { - "Call": "0x" - }, - "reason": "Stop" - } - }, - "state": { - "0x0000000000000000000000000000000000000000": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x0000000000000000000000000000000000100000": { - "info": { - "balance": "0x1", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x4200000000000000000000000000000000000019": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001a": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0x420000000000000000000000000000000000001b": { - "info": { - "balance": "0x0", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 0 - }, - "status": "Touched | LoadedAsNotExisting", - "storage": {}, - "transaction_id": 0 - }, - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { - "info": { - "balance": "0x2386f26fc0ffff", - "code": { - "LegacyAnalyzed": { - "bytecode": "0x00", - "jump_table": { - "bits": 0, - "data": [], - "head": { - "index": 0, - "width": 8 - }, - "order": "bitvec::order::Lsb0" - }, - "original_len": 0 - } - }, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", - "nonce": 1 - }, - "status": "Touched", - "storage": {}, - "transaction_id": 0 - } - } -} \ No newline at end of file diff --git a/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json index 145505a365..f38b1174d6 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json @@ -38,6 +38,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -63,6 +83,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -88,6 +128,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -113,6 +173,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -138,6 +218,12 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": null, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched", "storage": {}, "transaction_id": 0 @@ -165,6 +251,28 @@ "code_hash": "0x8013c386d5a03c3fa0a6ccbfefcf7d91471dedba2bb94eefef57f916e5929a8d", "nonce": 1 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x600080a000", + "jump_table": { + "bits": 5, + "data": [ + 0 + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 5 + } + }, + "code_hash": "0x8013c386d5a03c3fa0a6ccbfefcf7d91471dedba2bb94eefef57f916e5929a8d", + "nonce": 1 + }, "status": "Touched", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json index 87cdf23853..99c993c263 100644 --- a/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json @@ -32,6 +32,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -57,6 +77,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -82,6 +122,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -107,6 +167,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -132,6 +212,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 diff --git a/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json index 60cff1e58f..bbb9aba179 100644 --- a/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json +++ b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json @@ -60,6 +60,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 2 @@ -85,9 +105,29 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, - "transaction_id": 1 + "transaction_id": 0 }, "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2": { "info": { @@ -112,6 +152,26 @@ "code_hash": "0x9125466aa9ef15459d85e7318f6d3bdc5f6978c0565bee37a8e768d7c202a67a", "nonce": 1 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Created | CreatedLocal | SelfDestructed | Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 2 @@ -137,6 +197,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 1 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched", "storage": {}, "transaction_id": 2 diff --git a/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json index ccc0fe6dd4..27bdb42e70 100644 --- a/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json +++ b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json @@ -43,6 +43,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 1 @@ -68,6 +88,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "Touched | LoadedAsNotExisting", "storage": {}, "transaction_id": 0 @@ -93,6 +133,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 2 }, + "original_info": { + "balance": "0x2386f26fc10000", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 + }, "status": "Touched", "storage": {}, "transaction_id": 1 @@ -118,6 +178,26 @@ "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "nonce": 0 }, + "original_info": { + "balance": "0x0", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "jump_table": { + "bits": 0, + "data": [], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 + } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 + }, "status": "SelfDestructed | Touched", "storage": {}, "transaction_id": 1 diff --git a/crates/inspector/src/inspector_tests.rs b/crates/inspector/src/inspector_tests.rs index ad831d43f1..3fc183d6cf 100644 --- a/crates/inspector/src/inspector_tests.rs +++ b/crates/inspector/src/inspector_tests.rs @@ -384,6 +384,7 @@ mod tests { nonce: 0, code_hash: primitives::keccak256(&caller_code), code: Some(Bytecode::new_raw(caller_code)), + ..Default::default() }, ); @@ -399,6 +400,7 @@ mod tests { nonce: 0, code_hash: primitives::keccak256(&callee_code), code: Some(Bytecode::new_raw(callee_code)), + ..Default::default() }, ); diff --git a/crates/interpreter/src/gas/params.rs b/crates/interpreter/src/gas/params.rs index 77db84955b..93bd8c9a80 100644 --- a/crates/interpreter/src/gas/params.rs +++ b/crates/interpreter/src/gas/params.rs @@ -205,6 +205,13 @@ impl GasParams { self.get(GasId::selfdestruct_refund()) as i64 } + /// Selfdestruct cold cost is calculated differently from other cold costs. + /// and it contains both cold and warm costs. + #[inline] + pub fn selfdestruct_cold_cost(&self) -> u64 { + self.cold_account_additional_cost() + self.warm_storage_read_cost() + } + /// Selfdestruct cost. #[inline] pub fn selfdestruct_cost(&self, should_charge_topup: bool, is_cold: bool) -> u64 { @@ -221,7 +228,7 @@ impl GasParams { // the changes small, a SELFDESTRUCT already costs 5K and is a no-op if invoked more than once. // // For GasParams both values are zero before BERLIN fork. - gas += self.cold_account_additional_cost() + self.warm_storage_read_cost(); + gas += self.selfdestruct_cold_cost(); } gas } diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 7324c39802..6dec54b8fd 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -358,10 +358,7 @@ pub fn selfdestruct( let target = target.into_address(); let spec = context.interpreter.runtime_flag.spec_id(); - let cold_load_gas = context - .interpreter - .gas_params - .cold_account_additional_cost(); + let cold_load_gas = context.interpreter.gas_params.selfdestruct_cold_cost(); let skip_cold_load = context.interpreter.gas.remaining() < cold_load_gas; let res = match context.host.selfdestruct( diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 13ee5c4f92..ef51d2eddc 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -378,7 +378,11 @@ where error: Self::Error, ) -> Result, Self::Error> { let is_deposit = evm.ctx().tx().tx_type() == DEPOSIT_TRANSACTION_TYPE; - let output = if error.is_tx_error() && is_deposit { + let is_tx_error = error.is_tx_error(); + let mut output = Err(error); + + // Deposit transaction can't fail so we manually handle it here. + if is_tx_error && is_deposit { let ctx = evm.ctx(); let spec = ctx.cfg().spec(); let tx = ctx.tx(); @@ -420,13 +424,12 @@ where 0 }; // clear the journal - Ok(ExecutionResult::Halt { + output = Ok(ExecutionResult::Halt { reason: OpHaltReason::FailedDeposit, gas_used, }) - } else { - Err(error) - }; + } + // do the cleanup evm.ctx().chain_mut().clear_tx_l1_cost(); evm.ctx().local_mut().clear(); diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 044b3eb21c..d77c9d4022 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -19,7 +19,11 @@ workspace = true [dependencies] # alloy -alloy-primitives = { workspace = true, features = ["rlp", "map"] } +alloy-primitives = { workspace = true, features = [ + "map-indexmap", + "rlp", + "map", +] } # mics num_enum = { version = "0.7", default-features = false } diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index cdbdabbad7..1504880dbf 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -34,7 +34,7 @@ pub use once_lock::OnceLock; pub use alloy_primitives::{ self, address, b256, bytes, fixed_bytes, hex, hex_literal, keccak256, - map::{self, hash_map, hash_set, AddressMap, B256Map, HashMap, HashSet}, + map::{self, hash_map, hash_set, indexmap, AddressMap, B256Map, HashMap, HashSet, IndexMap}, ruint, uint, Address, Bytes, FixedBytes, Log, LogData, TxKind, B256, I128, I256, U128, U256, }; diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index ff57aa2044..9c67155a27 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -22,13 +22,32 @@ workspace = true primitives.workspace = true bytecode.workspace = true +# alloy +alloy-eip7928.workspace = true + # misc bitflags.workspace = true # Optional serde = { workspace = true, features = ["derive", "rc"], optional = true } +[dev-dependencies] +serde_json = { workspace = true, features = ["alloc"] } + [features] default = ["std"] -std = ["serde?/std", "primitives/std", "bitflags/std", "bytecode/std"] -serde = ["dep:serde", "primitives/serde", "bitflags/serde", "bytecode/serde"] +std = [ + "serde?/std", + "serde_json/std", + "primitives/std", + "bitflags/std", + "bytecode/std", + "alloy-eip7928/std", +] +serde = [ + "dep:serde", + "primitives/serde", + "bitflags/serde", + "bytecode/serde", + "alloy-eip7928/serde", +] diff --git a/crates/state/src/account_info.rs b/crates/state/src/account_info.rs index 8c2a41aea8..74d42f26af 100644 --- a/crates/state/src/account_info.rs +++ b/crates/state/src/account_info.rs @@ -3,7 +3,7 @@ use core::{ cmp::Ordering, hash::{Hash, Hasher}, }; -use primitives::{B256, KECCAK_EMPTY, U256}; +use primitives::{OnceLock, B256, KECCAK_EMPTY, U256}; /// Account information that contains balance, nonce, code hash and code /// @@ -17,6 +17,12 @@ pub struct AccountInfo { pub nonce: u64, /// Hash of the raw bytes in `code`, or [`KECCAK_EMPTY`]. pub code_hash: B256, + /// Used as a hint to optimize the access to the storage of account. + /// + /// It is set when account is loaded from the database, and if it is `Some` it will called + /// by journal to ask database the storage with this account_id (It will still send the address to the database). + #[cfg_attr(feature = "serde", serde(skip))] + pub account_id: Option, /// [`Bytecode`] data associated with this account. /// /// If [`None`], `code_hash` will be used to fetch it from the database, if code needs to be @@ -28,12 +34,16 @@ pub struct AccountInfo { impl Default for AccountInfo { fn default() -> Self { - Self { - balance: U256::ZERO, - code_hash: KECCAK_EMPTY, - code: Some(Bytecode::default()), - nonce: 0, - } + static DEFAULT: OnceLock = OnceLock::new(); + DEFAULT + .get_or_init(|| Self { + balance: U256::ZERO, + code_hash: KECCAK_EMPTY, + account_id: None, + nonce: 0, + code: Some(Bytecode::default()), + }) + .clone() } } @@ -77,6 +87,7 @@ impl AccountInfo { nonce, code: Some(code), code_hash, + account_id: None, } } @@ -87,10 +98,9 @@ impl AccountInfo { /// As code hash is calculated with [`Bytecode::hash_slow`] there will be performance penalty if used frequently. pub fn with_code(self, code: Bytecode) -> Self { Self { - balance: self.balance, - nonce: self.nonce, code_hash: code.hash_slow(), code: Some(code), + ..self } } @@ -102,10 +112,9 @@ impl AccountInfo { /// also [Self::with_code_and_hash]. pub fn with_code_hash(self, code_hash: B256) -> Self { Self { - balance: self.balance, - nonce: self.nonce, code_hash, code: None, + ..self } } @@ -118,10 +127,9 @@ impl AccountInfo { pub fn with_code_and_hash(self, code: Bytecode, code_hash: B256) -> Self { debug_assert_eq!(code.hash_slow(), code_hash); Self { - balance: self.balance, - nonce: self.nonce, code_hash, code: Some(code), + ..self } } @@ -201,6 +209,7 @@ impl AccountInfo { balance: self.balance, nonce: self.nonce, code_hash: self.code_hash, + account_id: self.account_id, code: None, } } @@ -289,6 +298,7 @@ impl AccountInfo { nonce: 1, code: Some(bytecode), code_hash: hash, + account_id: None, } } } @@ -298,25 +308,17 @@ mod tests { use crate::AccountInfo; use bytecode::Bytecode; use core::cmp::Ordering; - use primitives::{KECCAK_EMPTY, U256}; use std::collections::BTreeSet; #[test] fn test_account_info_trait_consistency() { let bytecode = Bytecode::default(); let account1 = AccountInfo { - balance: U256::ZERO, - nonce: 0, - code_hash: KECCAK_EMPTY, code: Some(bytecode.clone()), + ..AccountInfo::default() }; - let account2 = AccountInfo { - balance: U256::ZERO, - nonce: 0, - code_hash: KECCAK_EMPTY, - code: None, - }; + let account2 = AccountInfo::default(); assert_eq!(account1, account2, "Accounts should be equal ignoring code"); diff --git a/crates/state/src/bal.rs b/crates/state/src/bal.rs new file mode 100644 index 0000000000..3f713d87c4 --- /dev/null +++ b/crates/state/src/bal.rs @@ -0,0 +1,242 @@ +//! Block Access List (BAL) data structures for efficient state access in blockchain execution. +//! +//! This module provides types for managing Block Access Lists, which optimize state access +//! by pre-computing and organizing data that will be accessed during block execution. +//! +//! ## Key Types +//! +//! - **`BalIndex`**: Block access index (0 for pre-execution, 1..n for transactions, n+1 for post-execution) +//! - **`Bal`**: Main BAL structure containing a map of accounts +//! - **`BalWrites`**: Array of (index, value) pairs representing sequential writes to a state item +//! - **`AccountBal`**: Complete BAL structure for an account (balance, nonce, code, and storage) +//! - **`AccountInfoBal`**: Account info BAL data (nonce, balance, code) +//! - **`StorageBal`**: Storage-level BAL data for an account + +pub mod account; +pub mod alloy; +pub mod writes; + +pub use account::{AccountBal, AccountInfoBal, StorageBal}; +pub use writes::BalWrites; + +use crate::{Account, AccountInfo}; +use alloy_eip7928::BlockAccessList as AlloyBal; +use primitives::{Address, IndexMap, StorageKey, StorageValue}; + +/// Block access index (0 for pre-execution, 1..n for transactions, n+1 for post-execution) +pub type BalIndex = u64; + +/// BAL structure. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Bal { + /// Accounts bal. + pub accounts: IndexMap, +} + +impl FromIterator<(Address, AccountBal)> for Bal { + fn from_iter>(iter: I) -> Self { + Self { + accounts: iter.into_iter().collect(), + } + } +} + +impl Bal { + /// Create a new BAL builder. + pub fn new() -> Self { + Self { + accounts: IndexMap::default(), + } + } + + /// Pretty print the entire BAL structure in a human-readable format. + #[cfg(feature = "std")] + pub fn pretty_print(&self) { + println!("=== Block Access List (BAL) ==="); + println!("Total accounts: {}", self.accounts.len()); + println!(); + + if self.accounts.is_empty() { + println!("(empty)"); + return; + } + + // Sort accounts by address before printing + let mut sorted_accounts: Vec<_> = self.accounts.iter().collect(); + sorted_accounts.sort_by_key(|(address, _)| *address); + + for (idx, (address, account)) in sorted_accounts.into_iter().enumerate() { + println!("Account #{idx} - Address: {address:?}"); + println!(" Account Info:"); + + // Print nonce writes + if account.account_info.nonce.is_empty() { + println!(" Nonce: (read-only, no writes)"); + } else { + println!(" Nonce writes:"); + for (bal_index, nonce) in &account.account_info.nonce.writes { + println!(" [{bal_index}] -> {nonce}"); + } + } + + // Print balance writes + if account.account_info.balance.is_empty() { + println!(" Balance: (read-only, no writes)"); + } else { + println!(" Balance writes:"); + for (bal_index, balance) in &account.account_info.balance.writes { + println!(" [{bal_index}] -> {balance}"); + } + } + + // Print code writes + if account.account_info.code.is_empty() { + println!(" Code: (read-only, no writes)"); + } else { + println!(" Code writes:"); + for (bal_index, (code_hash, bytecode)) in &account.account_info.code.writes { + println!( + " [{}] -> hash: {:?}, size: {} bytes", + bal_index, + code_hash, + bytecode.len() + ); + } + } + + // Print storage writes + println!(" Storage:"); + if account.storage.storage.is_empty() { + println!(" (no storage slots)"); + } else { + println!(" Total slots: {}", account.storage.storage.len()); + for (storage_key, storage_writes) in &account.storage.storage { + println!(" Slot: {storage_key:#x}"); + if storage_writes.is_empty() { + println!(" (read-only, no writes)"); + } else { + println!(" Writes:"); + for (bal_index, value) in &storage_writes.writes { + println!(" [{bal_index}] -> {value:?}"); + } + } + } + } + + println!(); + } + println!("=== End of BAL ==="); + } + + #[inline] + /// Extend BAL with account. + pub fn update_account(&mut self, bal_index: BalIndex, address: Address, account: &Account) { + let bal_account = self.accounts.entry(address).or_default(); + bal_account.update(bal_index, account); + } + + /// Populate account from BAL. Return true if account info got changed + pub fn populate_account_info( + &self, + account_id: usize, + bal_index: BalIndex, + account: &mut AccountInfo, + ) -> Result { + let Some((_, bal_account)) = self.accounts.get_index(account_id) else { + return Err(BalError::AccountNotFound); + }; + account.account_id = Some(account_id); + + Ok(bal_account.populate_account_info(bal_index, account)) + } + + /// Populate storage slot from BAL. + /// + /// If slot is not found in BAL, it will return an error. + #[inline] + pub fn populate_storage_slot_by_account_id( + &self, + account_index: usize, + bal_index: BalIndex, + key: StorageKey, + value: &mut StorageValue, + ) -> Result<(), BalError> { + let Some((_, bal_account)) = self.accounts.get_index(account_index) else { + return Err(BalError::AccountNotFound); + }; + + if let Some(bal_value) = bal_account.storage.get(key, bal_index)? { + *value = bal_value; + }; + + Ok(()) + } + + /// Populate storage slot from BAL by account address. + #[inline] + pub fn populate_storage_slot( + &self, + account_address: Address, + bal_index: BalIndex, + key: StorageKey, + value: &mut StorageValue, + ) -> Result<(), BalError> { + let Some(bal_account) = self.accounts.get(&account_address) else { + return Err(BalError::AccountNotFound); + }; + + if let Some(bal_value) = bal_account.storage.get(key, bal_index)? { + *value = bal_value; + }; + Ok(()) + } + + /// Get storage from BAL. + pub fn account_storage( + &self, + account_index: usize, + key: StorageKey, + bal_index: BalIndex, + ) -> Result { + let Some((_, bal_account)) = self.accounts.get_index(account_index) else { + return Err(BalError::AccountNotFound); + }; + + let Some(storage_value) = bal_account.storage.get(key, bal_index)? else { + return Err(BalError::SlotNotFound); + }; + + Ok(storage_value) + } + + /// Consume Bal and create [`AlloyBal`] + pub fn into_alloy_bal(self) -> AlloyBal { + let mut alloy_bal = AlloyBal::from_iter( + self.accounts + .into_iter() + .map(|(address, account)| account.into_alloy_account(address)), + ); + alloy_bal.sort_by_key(|a| a.address); + alloy_bal + } +} + +/// BAL error. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum BalError { + /// Account not found in BAL. + AccountNotFound, + /// Slot not found in BAL. + SlotNotFound, +} + +impl core::fmt::Display for BalError { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + match self { + Self::AccountNotFound => write!(f, "Account not found in BAL"), + Self::SlotNotFound => write!(f, "Slot not found in BAL"), + } + } +} diff --git a/crates/state/src/bal/account.rs b/crates/state/src/bal/account.rs new file mode 100644 index 0000000000..6ca4b7458a --- /dev/null +++ b/crates/state/src/bal/account.rs @@ -0,0 +1,320 @@ +//! BAL builder module + +use crate::{ + bal::{writes::BalWrites, BalError, BalIndex}, + Account, AccountInfo, EvmStorage, +}; +use alloy_eip7928::{ + AccountChanges as AlloyAccountChanges, BalanceChange as AlloyBalanceChange, + CodeChange as AlloyCodeChange, NonceChange as AlloyNonceChange, + SlotChanges as AlloySlotChanges, StorageChange as AlloyStorageChange, +}; +use bytecode::{Bytecode, BytecodeDecodeError}; +use core::ops::{Deref, DerefMut}; +use primitives::{Address, StorageKey, StorageValue, B256, U256}; +use std::{ + collections::{btree_map::Entry, BTreeMap}, + vec::Vec, +}; + +/// Account BAL structure. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AccountBal { + /// Account info bal. + pub account_info: AccountInfoBal, + /// Storage bal. + pub storage: StorageBal, +} + +impl Deref for AccountBal { + type Target = AccountInfoBal; + + fn deref(&self) -> &Self::Target { + &self.account_info + } +} + +impl DerefMut for AccountBal { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.account_info + } +} + +impl AccountBal { + /// Populate account from BAL. Return true if account info got changed + pub fn populate_account_info(&self, bal_index: BalIndex, account: &mut AccountInfo) -> bool { + self.account_info.populate_account_info(bal_index, account) + } + + /// Extend account from another account. + #[inline] + pub fn update(&mut self, bal_index: BalIndex, account: &Account) { + if account.is_selfdestructed_locally() { + let empty_info = AccountInfo::default(); + self.account_info + .update(bal_index, &account.original_info, &empty_info); + self.storage.update_reads(account.storage.keys().copied()); + return; + } + + self.account_info + .update(bal_index, &account.original_info, &account.info); + + self.storage.update(bal_index, &account.storage); + } + + /// Create account from alloy account changes. + #[inline] + pub fn try_from_alloy( + alloy_account: AlloyAccountChanges, + ) -> Result<(Address, Self), BytecodeDecodeError> { + Ok(( + alloy_account.address, + AccountBal { + account_info: AccountInfoBal { + nonce: BalWrites::from(alloy_account.nonce_changes), + balance: BalWrites::from(alloy_account.balance_changes), + code: BalWrites::try_from(alloy_account.code_changes)?, + }, + storage: StorageBal::from_iter( + alloy_account + .storage_changes + .into_iter() + .chain( + alloy_account + .storage_reads + .into_iter() + .map(|key| AlloySlotChanges::new(key, Default::default())), + ) + .map(|slot| (slot.slot, BalWrites::from(slot.changes))), + ), + }, + )) + } + + /// Consumes AccountBal and converts it into [`AlloyAccountChanges`]. + #[inline] + pub fn into_alloy_account(self, address: Address) -> AlloyAccountChanges { + let mut storage_reads = Vec::new(); + let mut storage_changes = Vec::new(); + for (key, value) in self.storage.storage { + if value.writes.is_empty() { + storage_reads.push(key); + } else { + storage_changes.push(AlloySlotChanges::new( + key, + value + .writes + .into_iter() + .map(|(index, value)| AlloyStorageChange::new(index, value)) + .collect(), + )); + } + } + + AlloyAccountChanges { + address, + storage_changes, + storage_reads, + balance_changes: self + .account_info + .balance + .writes + .into_iter() + .map(|(index, value)| AlloyBalanceChange::new(index, value)) + .collect(), + nonce_changes: self + .account_info + .nonce + .writes + .into_iter() + .map(|(index, value)| AlloyNonceChange::new(index, value)) + .collect(), + code_changes: self + .account_info + .code + .writes + .into_iter() + .map(|(index, (_, value))| AlloyCodeChange::new(index, value.original_bytes())) + .collect(), + } + } +} + +/// Account info bal structure. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct AccountInfoBal { + /// Nonce builder. + pub nonce: BalWrites, + /// Balance builder. + pub balance: BalWrites, + /// Code builder. + pub code: BalWrites<(B256, Bytecode)>, +} + +impl AccountInfoBal { + /// Populate account info from BAL. Return true if account info got changed + pub fn populate_account_info(&self, bal_index: BalIndex, account: &mut AccountInfo) -> bool { + let mut changed = false; + if let Some(nonce) = self.nonce.get(bal_index) { + account.nonce = nonce; + changed = true; + } + if let Some(balance) = self.balance.get(bal_index) { + account.balance = balance; + changed = true; + } + if let Some(code) = self.code.get(bal_index) { + account.code_hash = code.0; + account.code = Some(code.1); + changed = true; + } + changed + } + + /// Extend account info from another account info. + #[inline] + pub fn update(&mut self, index: BalIndex, original: &AccountInfo, present: &AccountInfo) { + self.nonce.update(index, &original.nonce, present.nonce); + self.balance + .update(index, &original.balance, present.balance); + self.code.update_with_key( + index, + &original.code_hash, + (present.code_hash, present.code.clone().unwrap_or_default()), + |i| &i.0, + ); + } + + /// Extend account info from another account info. + #[inline] + pub fn extend(&mut self, bal_account: AccountInfoBal) { + self.nonce.extend(bal_account.nonce); + self.balance.extend(bal_account.balance); + self.code.extend(bal_account.code); + } + + /// Update account balance in BAL. + #[inline] + pub fn balance_update(&mut self, bal_index: BalIndex, original_balance: &U256, balance: U256) { + self.balance.update(bal_index, original_balance, balance); + } + + /// Update account nonce in BAL. + #[inline] + pub fn nonce_update(&mut self, bal_index: BalIndex, original_nonce: &u64, nonce: u64) { + self.nonce.update(bal_index, original_nonce, nonce); + } + + /// Update account code in BAL. + #[inline] + pub fn code_update( + &mut self, + bal_index: BalIndex, + original_code_hash: &B256, + code_hash: B256, + code: Bytecode, + ) { + self.code + .update_with_key(bal_index, original_code_hash, (code_hash, code), |i| &i.0); + } +} + +/// Storage BAL +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct StorageBal { + /// Storage with writes and reads. + pub storage: BTreeMap>, +} + +impl StorageBal { + /// Get storage from the builder. + #[inline] + pub fn get( + &self, + key: StorageKey, + bal_index: BalIndex, + ) -> Result, BalError> { + Ok(self.get_bal_writes(key)?.get(bal_index)) + } + + /// Get storage writes from the builder. + #[inline] + pub fn get_bal_writes(&self, key: StorageKey) -> Result<&BalWrites, BalError> { + self.storage.get(&key).ok_or(BalError::SlotNotFound) + } + + /// Extend storage from another storage. + #[inline] + pub fn extend(&mut self, storage: StorageBal) { + for (key, value) in storage.storage { + match self.storage.entry(key) { + Entry::Occupied(mut entry) => { + entry.get_mut().extend(value); + } + Entry::Vacant(entry) => { + entry.insert(value); + } + } + } + } + + /// Update storage from [`EvmStorage`]. + #[inline] + pub fn update(&mut self, bal_index: BalIndex, storage: &EvmStorage) { + for (key, value) in storage { + self.storage.entry(*key).or_default().update( + bal_index, + &value.original_value, + value.present_value, + ); + } + } + + /// Update reads from [`EvmStorage`]. + /// + /// It will expend inner map with new reads. + #[inline] + pub fn update_reads(&mut self, storage: impl Iterator) { + for key in storage { + self.storage.entry(key).or_default(); + } + } + + /// Insert storage into the builder. + pub fn extend_iter( + &mut self, + storage: impl Iterator)>, + ) { + for (key, value) in storage { + self.storage.insert(key, value); + } + } + + /// Convert the storage into a vector of reads and writes + pub fn into_vecs(self) -> (Vec, Vec<(StorageKey, BalWrites)>) { + let mut reads = Vec::new(); + let mut writes = Vec::new(); + + for (key, value) in self.storage { + if value.writes.is_empty() { + reads.push(key); + } else { + writes.push((key, value)); + } + } + + (reads, writes) + } +} + +impl FromIterator<(StorageKey, BalWrites)> for StorageBal { + fn from_iter)>>(iter: I) -> Self { + Self { + storage: iter.into_iter().collect(), + } + } +} diff --git a/crates/state/src/bal/alloy.rs b/crates/state/src/bal/alloy.rs new file mode 100644 index 0000000000..f17288fd66 --- /dev/null +++ b/crates/state/src/bal/alloy.rs @@ -0,0 +1,80 @@ +//! Alloy BAL types conversions. + +// Re-export Alloy BAL types. +pub use alloy_eip7928::{ + BalanceChange as AlloyBalanceChange, BlockAccessList as AlloyBal, + CodeChange as AlloyCodeChange, NonceChange as AlloyNonceChange, + StorageChange as AlloyStorageChange, +}; + +use crate::bal::{AccountBal, Bal, BalWrites}; +use bytecode::{Bytecode, BytecodeDecodeError}; +use primitives::{IndexMap, B256, U256}; +use std::vec::Vec; + +impl TryFrom for Bal { + type Error = BytecodeDecodeError; + + fn try_from(alloy_bal: AlloyBal) -> Result { + let accounts = IndexMap::from_iter( + alloy_bal + .into_iter() + .map(AccountBal::try_from_alloy) + .collect::, _>>()?, + ); + + Ok(Self { accounts }) + } +} + +impl From> for BalWrites { + fn from(value: Vec) -> Self { + Self { + writes: value + .into_iter() + .map(|change| (change.block_access_index, change.post_balance)) + .collect(), + } + } +} + +impl From> for BalWrites { + fn from(value: Vec) -> Self { + Self { + writes: value + .into_iter() + .map(|change| (change.block_access_index, change.new_nonce)) + .collect(), + } + } +} + +impl From> for BalWrites { + fn from(value: Vec) -> Self { + Self { + writes: value + .into_iter() + .map(|change| (change.block_access_index, change.new_value)) + .collect(), + } + } +} + +impl TryFrom> for BalWrites<(B256, Bytecode)> { + type Error = BytecodeDecodeError; + + fn try_from(value: Vec) -> Result { + Ok(Self { + writes: value + .into_iter() + .map(|change| { + // convert bytes to bytecode. + Bytecode::new_raw_checked(change.new_code).map(|bytecode| { + let hash = bytecode.hash_slow(); + (change.block_access_index, (hash, bytecode)) + }) + }) + .collect::, Self::Error>>()?, + }) + } +} diff --git a/crates/state/src/bal/writes.rs b/crates/state/src/bal/writes.rs new file mode 100644 index 0000000000..db4f1efbfc --- /dev/null +++ b/crates/state/src/bal/writes.rs @@ -0,0 +1,184 @@ +//! BAL containing writes. + +use crate::bal::BalIndex; +use std::vec::Vec; + +/// Use to store values +/// +/// If empty it means that this item was read from database. +#[derive(Debug, Default, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct BalWrites { + /// List of writes with BalIndex. + pub writes: Vec<(BalIndex, T)>, +} + +impl BalWrites { + /// Create a new BalWrites. + pub fn new(mut writes: Vec<(BalIndex, T)>) -> Self { + writes.sort_by_key(|(index, _)| *index); + Self { writes } + } + + /// Linear search is used for small number of writes. It is faster than binary search. + #[inline(never)] + pub fn get_linear_search(&self, bal_index: BalIndex) -> Option { + let mut last_item = None; + for (index, item) in self.writes.iter() { + // if index is greater than bal_index we return the last item. + if index >= &bal_index { + return last_item; + } + last_item = Some(item.clone()); + } + last_item + } + + /// Get value from BAL. + pub fn get(&self, bal_index: BalIndex) -> Option { + if self.writes.len() < 5 { + return self.get_linear_search(bal_index); + } + // else do binary search. + let i = match self + .writes + .binary_search_by_key(&bal_index, |(index, _)| *index) + { + Ok(i) => i, + Err(i) => i, + }; + // only if i is not zero, we return the previous value. + (i != 0).then(|| self.writes[i - 1].1.clone()) + } + + /// Extend the builder with another builder. + pub fn extend(&mut self, other: BalWrites) { + self.writes.extend(other.writes); + } + + /// Returns true if the builder is empty. + pub fn is_empty(&self) -> bool { + self.writes.is_empty() + } + + /// Force insert a value into the BalWrites. + /// + /// Check if last index is same as the index to insert. + /// If it is, we override the value. + /// If it is not, we push the value to the end of the vector. + /// + /// No checks for original value is done. This is useful when we know that value is different. + #[inline] + pub fn force_update(&mut self, index: BalIndex, value: T) { + if let Some(last) = self.writes.last_mut() { + if index == last.0 { + last.1 = value; + return; + } + } + self.writes.push((index, value)); + } + + /// Insert a value into the builder. + /// + /// If BalIndex is same as last it will override the value. + pub fn update(&mut self, index: BalIndex, original_value: &T, value: T) { + self.update_with_key(index, original_value, value, |i| i); + } + + /// Insert a value into the builder. + /// + /// If BalIndex is same as last it will override the value. + /// + /// Assumes that index is always greater than last one and that Writes are updated in proper order. + #[inline] + pub fn update_with_key( + &mut self, + index: BalIndex, + original_subvalue: &K, + value: T, + f: F, + ) where + F: Fn(&T) -> &K, + { + // if index is different, we push the new value. + if let Some(last) = self.writes.last_mut() { + if last.0 != index { + // we push the new value only if it is changed. + if f(&last.1) != f(&value) { + self.writes.push((index, value)); + } + return; + } + } + + // extract previous (Can be original_subvalue or previous value) and last value. + let (previous, last) = match self.writes.as_mut_slice() { + [.., previous, last] => (f(&previous.1), last), + [last] => (original_subvalue, last), + [] => { + // if writes are empty check if original value is same as newly set value. + if original_subvalue != f(&value) { + self.writes.push((index, value)); + } + return; + } + }; + + // if previous value is same, we pop the last value. + if previous == f(&value) { + self.writes.pop(); + return; + } + + // if it is different, we update the last value. + last.1 = value; + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_get() { + let bal_writes = BalWrites::new(vec![(0, 1), (1, 2), (2, 3)]); + assert_eq!(bal_writes.get(0), None); + assert_eq!(bal_writes.get(1), Some(1)); + assert_eq!(bal_writes.get(2), Some(2)); + assert_eq!(bal_writes.get(3), Some(3)); + assert_eq!(bal_writes.get(4), Some(3)); + } + + fn get_binary_search(threshold: BalIndex) { + // Construct test data up to (threshold - 1), skipping one key to simulate a gap. + let entries: Vec<_> = (0..threshold - 1) + .map(|i| (i, i + 1)) + .chain(std::iter::once((threshold, threshold + 1))) + .collect(); + + let bal_writes = BalWrites::new(entries); + + // Case 1: lookup before any entries + assert_eq!(bal_writes.get(0), None); + + // Case 2: lookups for existing keys before the gap + for i in 1..threshold - 1 { + assert_eq!(bal_writes.get(i), Some(i)); + } + + // Case 3: lookup at the skipped key — should return the previous value + assert_eq!(bal_writes.get(threshold), Some(threshold - 1)); + + // Case 4: lookup after the skipped key — should return the next valid value + assert_eq!(bal_writes.get(threshold + 1), Some(threshold + 1)); + } + + #[test] + fn test_get_binary_search() { + get_binary_search(4); + get_binary_search(5); + get_binary_search(6); + get_binary_search(7); + } +} diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index 57ecb38c13..e7c229e45b 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -2,8 +2,13 @@ #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] +#[cfg(not(feature = "std"))] +extern crate alloc as std; + mod account_info; +pub mod bal; mod types; + pub use bytecode; pub use account_info::AccountInfo; @@ -12,14 +17,28 @@ pub use primitives; pub use types::{EvmState, EvmStorage, TransientStorage}; use bitflags::bitflags; -use primitives::{hardfork::SpecId, HashMap, StorageKey, StorageValue, U256}; - -/// Account type used inside Journal to track changed to state. +use primitives::{hardfork::SpecId, HashMap, OnceLock, StorageKey, StorageValue, U256}; +use std::boxed::Box; + +/// The main account type used inside Revm. It is stored inside Journal and contains all the information about the account. +/// +/// Other than standard Account information it contains its status that can be both cold and warm +/// additional to that it contains BAL that is used to load data for this particular account. +/// +/// On loading from database: +/// * If CompiledBal is present, load values from BAL into Account (Assume account has read data from database) +/// * In case of parallel execution, AccountInfo would be same over all parallel executions. +/// * Maybe use transaction_id as a way to notify user that this is obsolete data. +/// * Database needs to load account and tie to with BAL writes +/// If CompiledBal is not present, use loaded values +/// * Account is already up to date (uses present flow). #[derive(Debug, Clone, PartialEq, Eq, Default)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[cfg_attr(feature = "serde", derive(serde::Serialize))] pub struct Account { /// Balance, nonce, and code pub info: AccountInfo, + /// Original account info used by BAL, changed only on cold load by BAL. + pub original_info: Box, /// Transaction id, used to track when account was toched/loaded into journal. pub transaction_id: usize, /// Storage cache @@ -31,12 +50,16 @@ pub struct Account { impl Account { /// Creates new account and mark it as non existing. pub fn new_not_existing(transaction_id: usize) -> Self { - Self { - info: AccountInfo::default(), - storage: HashMap::default(), - transaction_id, - status: AccountStatus::LoadedAsNotExisting, - } + static DEFAULT: OnceLock = OnceLock::new(); + DEFAULT + .get_or_init(|| Self { + info: AccountInfo::default(), + storage: HashMap::default(), + transaction_id, + status: AccountStatus::LoadedAsNotExisting, + original_info: Box::new(AccountInfo::default()), + }) + .clone() } /// Make changes to the caller account. @@ -283,11 +306,54 @@ impl Account { impl From for Account { fn from(info: AccountInfo) -> Self { + let original_info = Box::new(info.clone()); Self { info, storage: HashMap::default(), transaction_id: 0, status: AccountStatus::empty(), + original_info, + } + } +} + +#[cfg(feature = "serde")] +mod serde_impl { + use super::*; + use serde::{Deserialize, Serialize}; + + #[derive(Serialize, Deserialize)] + struct AccountSerde { + info: AccountInfo, + original_info: Option, + storage: HashMap, + transaction_id: usize, + status: AccountStatus, + } + + impl<'de> Deserialize<'de> for super::Account { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let AccountSerde { + info, + original_info, + storage, + transaction_id, + status, + } = Deserialize::deserialize(deserializer)?; + + // If original info is not present, use info as original info + let original_info = original_info.unwrap_or_else(|| info.clone()); + + Ok(Account { + info, + original_info: Box::new(original_info), + storage, + transaction_id, + status, + }) } } } @@ -366,7 +432,7 @@ impl Default for AccountStatus { } /// This type keeps track of the current value of a storage slot. -#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EvmStorageSlot { /// Original value of the storage slot @@ -439,6 +505,10 @@ impl EvmStorageSlot { #[inline] pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { let is_cold = self.is_cold_transaction_id(transaction_id); + if is_cold { + // if slot is cold original value should be reset to present value. + self.original_value = self.present_value; + } self.transaction_id = transaction_id; self.is_cold = false; is_cold @@ -567,6 +637,27 @@ mod tests { assert!(!account.is_created()); } + #[test] + #[cfg(feature = "serde")] + fn test_account_serialize_deserialize() { + let account = Account::default().with_selfdestruct_mark(); + let serialized = serde_json::to_string(&account).unwrap(); + let deserialized: Account = serde_json::from_str(&serialized).unwrap(); + assert_eq!(account, deserialized); + } + + #[test] + #[cfg(feature = "serde")] + fn test_account_serialize_deserialize_without_original_info() { + let deserialize_without_original_info = r#" + {"info":{"balance":"0x0","nonce":0,"code_hash":"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470","storage_id":null,"code":{"LegacyAnalyzed":{"bytecode":"0x00","original_len":0,"jump_table":{"order":"bitvec::order::Lsb0","head":{"width":8,"index":0},"bits":0,"data":[]}}}},"transaction_id":0,"storage":{},"status":"SelfDestructed"}"#; + + let account = Account::default().with_selfdestruct_mark(); + let deserialized: Account = + serde_json::from_str(deserialize_without_original_info).unwrap(); + assert_eq!(account, deserialized); + } + #[test] fn test_account_with_touched_mark() { let account = Account::default().with_touched_mark(); diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 61eb508318..2df7f2764d 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -25,3 +25,6 @@ serde_json = { workspace = true, features = ["preserve_order"] } k256 = { workspace = true } thiserror = { workspace = true } alloy-eips = { workspace = true } + +# alloy +alloy-eip7928 = { workspace = true, features = ["std", "serde", "rlp"] } diff --git a/crates/statetest-types/src/blockchain.rs b/crates/statetest-types/src/blockchain.rs index 7637ebd731..e7e83c90a9 100644 --- a/crates/statetest-types/src/blockchain.rs +++ b/crates/statetest-types/src/blockchain.rs @@ -4,6 +4,7 @@ //! from the Ethereum test suite. use crate::{deserialize_maybe_empty, AccountInfo, TestAuthorization}; +use alloy_eip7928::BlockAccessList; use revm::{ context::{transaction::AccessList, BlockEnv, TxEnv}, context_interface::block::BlobExcessGasAndPrice, @@ -108,6 +109,12 @@ pub struct Block { pub uncle_headers: Option>, /// Withdrawals in the block (post-Shanghai) pub withdrawals: Option>, + /// Block access list + pub block_access_list: Option, + /// Withdrawal requests (EIP-7002) + pub withdrawal_requests: Option>, + /// Consolidation requests (EIP-7251) + pub consolidation_requests: Option>, } /// Transaction structure @@ -171,6 +178,34 @@ pub struct Withdrawal { pub amount: U256, } +/// Withdrawal request structure (EIP-7002) +/// +/// Represents an execution layer triggerable withdrawal request. +#[derive(Debug, PartialEq, Eq, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct WithdrawalRequest { + /// Address of the source of the exit + pub source_address: Address, + /// Validator public key (48 bytes) + pub validator_pubkey: FixedBytes<48>, + /// Amount of withdrawn ether in gwei + pub amount: U256, +} + +/// Consolidation request structure (EIP-7251) +/// +/// Represents a consolidation request for validator consolidation. +#[derive(Debug, PartialEq, Eq, Deserialize, Clone)] +#[serde(rename_all = "camelCase")] +pub struct ConsolidationRequest { + /// Source address + pub source_address: Address, + /// Source public key (48 bytes) + pub source_pubkey: FixedBytes<48>, + /// Target public key (48 bytes) + pub target_pubkey: FixedBytes<48>, +} + /// Ethereum blockchain test data state #[derive(Clone, Debug, Eq, PartialEq, Deserialize, Default)] pub struct State(pub BTreeMap); @@ -280,6 +315,8 @@ pub enum ForkSpec { Osaka, /// BPO1 to BPO2 transition BPO1ToBPO2AtTime15k, + /// Amsterdam + Amsterdam, } /// Possible seal engines @@ -470,6 +507,7 @@ mod test { ), ("\"Osaka\"", ForkSpec::Osaka), ("\"BPO1ToBPO2AtTime15k\"", ForkSpec::BPO1ToBPO2AtTime15k), + ("\"Amsterdam\"", ForkSpec::Amsterdam), ]; for (json, expected) in fork_specs { diff --git a/crates/statetest-types/src/spec.rs b/crates/statetest-types/src/spec.rs index 434b73bdcc..4bdfbab483 100644 --- a/crates/statetest-types/src/spec.rs +++ b/crates/statetest-types/src/spec.rs @@ -48,8 +48,10 @@ pub enum SpecName { Cancun, /// Prague hardfork (future) Prague, - /// Osaka hardfork (skipped) - Osaka, // SKIPPED + /// Osaka hardfork + Osaka, + /// Amsterdam hardfork + Amsterdam, /// Unknown or unsupported specification #[serde(other)] Unknown, @@ -75,6 +77,7 @@ impl SpecName { Self::Cancun => SpecId::CANCUN, Self::Prague => SpecId::PRAGUE, Self::Osaka => SpecId::OSAKA, + Self::Amsterdam => SpecId::AMSTERDAM, Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => { panic!("Overridden with PETERSBURG") } diff --git a/crates/statetest-types/src/test_unit.rs b/crates/statetest-types/src/test_unit.rs index 15d55d14dc..618e837272 100644 --- a/crates/statetest-types/src/test_unit.rs +++ b/crates/statetest-types/src/test_unit.rs @@ -76,6 +76,7 @@ impl TestUnit { code_hash, code: Some(bytecode), nonce: info.nonce, + ..Default::default() }; cache_state.insert_account_with_storage(*address, acc_info, info.storage.clone()); } diff --git a/examples/custom_precompile_journal/src/custom_evm.rs b/examples/custom_precompile_journal/src/custom_evm.rs index 5a453abc34..3974d6e490 100644 --- a/examples/custom_precompile_journal/src/custom_evm.rs +++ b/examples/custom_precompile_journal/src/custom_evm.rs @@ -210,6 +210,7 @@ mod tests { nonce: 0, code_hash: revm::primitives::KECCAK_EMPTY, code: None, + account_id: None, }, ); @@ -221,6 +222,7 @@ mod tests { nonce: 0, code_hash: revm::primitives::KECCAK_EMPTY, code: None, + account_id: None, }, ); @@ -344,6 +346,7 @@ mod tests { nonce: 0, code_hash: revm::primitives::KECCAK_EMPTY, code: None, + account_id: None, }, ); diff --git a/examples/custom_precompile_journal/src/main.rs b/examples/custom_precompile_journal/src/main.rs index 6a4595775c..1cf2189498 100644 --- a/examples/custom_precompile_journal/src/main.rs +++ b/examples/custom_precompile_journal/src/main.rs @@ -39,6 +39,7 @@ fn main() -> anyhow::Result<()> { nonce: 0, code_hash: revm::primitives::KECCAK_EMPTY, code: None, + ..Default::default() }, ); @@ -50,6 +51,7 @@ fn main() -> anyhow::Result<()> { nonce: 0, code_hash: revm::primitives::KECCAK_EMPTY, code: None, + ..Default::default() }, ); diff --git a/examples/erc20_gas/src/main.rs b/examples/erc20_gas/src/main.rs index 1f16c47f9a..9518b3830d 100644 --- a/examples/erc20_gas/src/main.rs +++ b/examples/erc20_gas/src/main.rs @@ -12,9 +12,7 @@ use revm::{ context::TxEnv, database::{AlloyDB, BlockId, CacheDB}, database_interface::WrapDatabaseAsync, - primitives::{ - address, hardfork::SpecId, keccak256, Address, StorageValue, TxKind, KECCAK_EMPTY, U256, - }, + primitives::{address, hardfork::SpecId, keccak256, Address, StorageValue, TxKind, U256}, state::AccountInfo, Context, Database, MainBuilder, MainContext, }; @@ -57,10 +55,8 @@ async fn main() -> Result<()> { cache_db.insert_account_info( account, AccountInfo { - nonce: 0, balance: hundred_tokens * U256::from(2), - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }, ); diff --git a/examples/uniswap_v2_usdc_swap/src/main.rs b/examples/uniswap_v2_usdc_swap/src/main.rs index 4b374ab537..2315698ef7 100644 --- a/examples/uniswap_v2_usdc_swap/src/main.rs +++ b/examples/uniswap_v2_usdc_swap/src/main.rs @@ -10,7 +10,7 @@ use revm::{ context_interface::result::{ExecutionResult, Output}, database::{AlloyDB, CacheDB}, database_interface::WrapDatabaseAsync, - primitives::{address, keccak256, Address, Bytes, StorageKey, TxKind, KECCAK_EMPTY, U256}, + primitives::{address, keccak256, Address, Bytes, StorageKey, TxKind, U256}, state::AccountInfo, Context, ExecuteCommitEvm, ExecuteEvm, MainBuilder, MainContext, }; @@ -44,10 +44,8 @@ async fn main() -> Result<()> { .unwrap(); let acc_info = AccountInfo { - nonce: 0_u64, balance: one_ether, - code_hash: KECCAK_EMPTY, - code: None, + ..Default::default() }; cache_db.insert_account_info(account, acc_info); From 7b505e686c4f23fc45dbadda5b0e621d0ff7523d Mon Sep 17 00:00:00 2001 From: anim001k <140460766+anim001k@users.noreply.github.com> Date: Thu, 18 Dec 2025 11:46:17 +0100 Subject: [PATCH 083/127] fix: deduplicate post-state validation error handling (#3228) * Update blockchaintest.rs * Update blockchaintest.rs * Apply suggestion from @rakita --- bins/revme/src/cmd/blockchaintest.rs | 137 ++++++++++++++++----------- 1 file changed, 82 insertions(+), 55 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 9ee6290ba3..7acb96f3a4 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -327,6 +327,28 @@ fn validate_post_state( debug_info: &DebugInfo, print_env_on_error: bool, ) -> Result<(), TestExecutionError> { + #[allow(clippy::too_many_arguments)] + fn make_failure( + state: &mut State, + debug_info: &DebugInfo, + expected_post_state: &BTreeMap, + print_env_on_error: bool, + address: Address, + field: String, + expected: String, + actual: String, + ) -> Result<(), TestExecutionError> { + if print_env_on_error { + print_error_with_state(debug_info, state, Some(expected_post_state)); + } + Err(TestExecutionError::PostStateValidation { + address, + field, + expected, + actual, + }) + } + for (address, expected_account) in expected_post_state { // Load account from final state let actual_account = state @@ -340,55 +362,59 @@ fn validate_post_state( // Validate balance if info.balance != expected_account.balance { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); - } - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: "balance".to_string(), - expected: format!("{}", expected_account.balance), - actual: format!("{}", info.balance), - }); + return make_failure( + state, + debug_info, + expected_post_state, + print_env_on_error, + *address, + "balance".to_string(), + format!("{}", expected_account.balance), + format!("{}", info.balance), + ); } // Validate nonce let expected_nonce = expected_account.nonce.to::(); if info.nonce != expected_nonce { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); - } - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: "nonce".to_string(), - expected: format!("{expected_nonce}"), - actual: format!("{}", info.nonce), - }); + return make_failure( + state, + debug_info, + expected_post_state, + print_env_on_error, + *address, + "nonce".to_string(), + format!("{expected_nonce}"), + format!("{}", info.nonce), + ); } // Validate code if present if !expected_account.code.is_empty() { if let Some(actual_code) = &info.code { if actual_code.original_bytes() != expected_account.code { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); - } - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: "code".to_string(), - expected: format!("0x{}", hex::encode(&expected_account.code)), - actual: format!("0x{}", hex::encode(actual_code.bytecode())), - }); + return make_failure( + state, + debug_info, + expected_post_state, + print_env_on_error, + *address, + "code".to_string(), + format!("0x{}", hex::encode(&expected_account.code)), + format!("0x{}", hex::encode(actual_code.bytecode())), + ); } } else { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); - } - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: "code".to_string(), - expected: format!("0x{}", hex::encode(&expected_account.code)), - actual: "empty".to_string(), - }); + return make_failure( + state, + debug_info, + expected_post_state, + print_env_on_error, + *address, + "code".to_string(), + format!("0x{}", hex::encode(&expected_account.code)), + "empty".to_string(), + ); } } @@ -398,15 +424,16 @@ fn validate_post_state( let slot = *slot; let actual_value = *actual_value; if !expected_account.storage.contains_key(&slot) && !actual_value.is_zero() { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); - } - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: format!("storage_unexpected[{slot}]"), - expected: "0x0".to_string(), - actual: format!("{actual_value}"), - }); + return make_failure( + state, + debug_info, + expected_post_state, + print_env_on_error, + *address, + format!("storage_unexpected[{slot}]"), + "0x0".to_string(), + format!("{actual_value}"), + ); } } } @@ -417,16 +444,16 @@ fn validate_post_state( let actual_value = actual_value.unwrap_or_default(); if actual_value != *expected_value { - if print_env_on_error { - print_error_with_state(debug_info, state, Some(expected_post_state)); - } - - return Err(TestExecutionError::PostStateValidation { - address: *address, - field: format!("storage_validation[{slot}]"), - expected: format!("{expected_value}"), - actual: format!("{actual_value}"), - }); + return make_failure( + state, + debug_info, + expected_post_state, + print_env_on_error, + *address, + format!("storage_validation[{slot}]"), + format!("{expected_value}"), + format!("{actual_value}"), + ); } } } From 0d86418b34a8b5bb4ecb281e1f0e27831cb74939 Mon Sep 17 00:00:00 2001 From: leopardracer <136604165+leopardracer@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:16:53 +0200 Subject: [PATCH 084/127] fix: remove redundant trace file creation in block_traces example (#3245) --- examples/block_traces/src/main.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/examples/block_traces/src/main.rs b/examples/block_traces/src/main.rs index 68940c9d2b..29e2667eca 100644 --- a/examples/block_traces/src/main.rs +++ b/examples/block_traces/src/main.rs @@ -91,16 +91,7 @@ async fn main() -> anyhow::Result<()> { c.chain_id = chain_id; }); - let write = OpenOptions::new() - .write(true) - .create(true) - .truncate(true) - .open("traces/0.json"); - let inner = Arc::new(Mutex::new(BufWriter::new( - write.expect("Failed to open file"), - ))); - let writer = FlushWriter::new(Arc::clone(&inner)); - let mut evm = ctx.build_mainnet_with_inspector(TracerEip3155::new(Box::new(writer))); + let mut evm = ctx.build_mainnet_with_inspector(TracerEip3155::new(Box::new(std::io::sink()))); let txs = block.transactions.len(); println!("Found {txs} transactions."); From ba5bb55ae6c7c1bd970d47699da69fd3c9f01c24 Mon Sep 17 00:00:00 2001 From: leopardracer <136604165+leopardracer@users.noreply.github.com> Date: Mon, 22 Dec 2025 10:18:15 +0200 Subject: [PATCH 085/127] fix: use expected_exception instead of error field for unexpected_success status (#3244) --- bins/revme/src/cmd/blockchaintest.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 7acb96f3a4..64bfe7e19c 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -885,19 +885,19 @@ fn execute_blockchain_test( test_case.post_state.as_ref(), ); } - let exception = block.expect_exception.clone().unwrap_or_default(); + let expected_exception = block.expect_exception.clone().unwrap_or_default(); if json_output { let output = json!({ "block": block_idx, "tx": tx_idx, - "error": format!("expected failure: {exception}"), + "expected_exception": expected_exception, "gas_used": result.result.gas_used(), "status": "unexpected_success" }); println!("{}", serde_json::to_string(&output).unwrap()); } else { eprintln!( - "⚠️ Skipping block {block_idx}: transaction unexpectedly succeeded (expected failure: {exception})" + "⚠️ Skipping block {block_idx}: transaction unexpectedly succeeded (expected failure: {expected_exception})" ); } break; // Skip to next block From 18bb8c0f403fecd7a64ca86ce1b00bac663e99e8 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Mon, 22 Dec 2025 13:53:40 +0300 Subject: [PATCH 086/127] refactor(handler): eliminate code duplication in transaction validation (#3243) * Update validation.rs * Update validation.rs * Update validation.rs * Update validation.rs --- crates/handler/src/validation.rs | 36 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index d9ba1c4415..a05a38031d 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -61,6 +61,21 @@ pub fn validate_priority_fee_tx( Ok(()) } +/// Validate priority fee for transactions that support EIP-1559 (Eip1559, Eip4844, Eip7702). +#[inline] +fn validate_priority_fee_for_tx( + tx: TX, + base_fee: Option, + disable_priority_fee_check: bool, +) -> Result<(), InvalidTransaction> { + validate_priority_fee_tx( + tx.max_fee_per_gas(), + tx.max_priority_fee_per_gas().unwrap_or_default(), + base_fee, + disable_priority_fee_check, + ) +} + /// Validate EIP-4844 transaction. pub fn validate_eip4844_tx( blobs: &[B256], @@ -157,24 +172,14 @@ pub fn validate_tx_env( if !spec_id.is_enabled_in(SpecId::LONDON) { return Err(InvalidTransaction::Eip1559NotSupported); } - validate_priority_fee_tx( - tx.max_fee_per_gas(), - tx.max_priority_fee_per_gas().unwrap_or_default(), - base_fee, - disable_priority_fee_check, - )?; + validate_priority_fee_for_tx(tx, base_fee, disable_priority_fee_check)?; } TransactionType::Eip4844 => { if !spec_id.is_enabled_in(SpecId::CANCUN) { return Err(InvalidTransaction::Eip4844NotSupported); } - validate_priority_fee_tx( - tx.max_fee_per_gas(), - tx.max_priority_fee_per_gas().unwrap_or_default(), - base_fee, - disable_priority_fee_check, - )?; + validate_priority_fee_for_tx(tx, base_fee, disable_priority_fee_check)?; validate_eip4844_tx( tx.blob_versioned_hashes(), @@ -189,12 +194,7 @@ pub fn validate_tx_env( return Err(InvalidTransaction::Eip7702NotSupported); } - validate_priority_fee_tx( - tx.max_fee_per_gas(), - tx.max_priority_fee_per_gas().unwrap_or_default(), - base_fee, - disable_priority_fee_check, - )?; + validate_priority_fee_for_tx(tx, base_fee, disable_priority_fee_check)?; let auth_list_len = tx.authorization_list_len(); // The transaction is considered invalid if the length of authorization_list is zero. From da12faecddf75938e2a8292332965ee2cd3a6d8b Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 22 Dec 2025 14:43:50 +0100 Subject: [PATCH 087/127] refactor: re-export statetest-types from revm crate behind test-types feature (#3247) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Update statetest-types to depend on individual revm crates (primitives, bytecode, state, context, context-interface, database) instead of revm to avoid circular dependency - Add statetest-types as optional dependency to revm crate - Add test-types feature flag to revm that enables statetest-types - Update revme to import statetest_types from revm instead of directly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.5 --- Cargo.lock | 10 ++++++--- bins/revme/Cargo.toml | 2 +- bins/revme/src/cmd/blockchaintest.rs | 6 ++--- .../src/cmd/blockchaintest/post_block.rs | 2 +- bins/revme/src/cmd/statetest/runner.rs | 2 +- crates/revm/Cargo.toml | 4 ++++ crates/revm/src/lib.rs | 4 ++++ crates/statetest-types/Cargo.toml | 11 +++++++--- crates/statetest-types/src/account_info.rs | 2 +- crates/statetest-types/src/blockchain.rs | 12 +++++----- crates/statetest-types/src/deserializer.rs | 2 +- crates/statetest-types/src/env.rs | 2 +- crates/statetest-types/src/error.rs | 2 +- crates/statetest-types/src/spec.rs | 2 +- crates/statetest-types/src/test.rs | 8 +++---- .../statetest-types/src/test_authorization.rs | 2 +- crates/statetest-types/src/test_unit.rs | 22 ++++++++----------- crates/statetest-types/src/transaction.rs | 8 +++---- crates/statetest-types/src/utils.rs | 4 ++-- 19 files changed, 57 insertions(+), 50 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3a7f74b491..b630d6d81f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3646,6 +3646,7 @@ dependencies = [ "revm-precompile", "revm-primitives", "revm-state", + "revm-statetest-types", "serde", "serde_json", ] @@ -3840,9 +3841,13 @@ name = "revm-statetest-types" version = "13.1.0" dependencies = [ "alloy-eip7928", - "alloy-eips", "k256", - "revm", + "revm-bytecode", + "revm-context", + "revm-context-interface", + "revm-database", + "revm-primitives", + "revm-state", "serde", "serde_json", "thiserror", @@ -3862,7 +3867,6 @@ dependencies = [ "k256", "plain_hasher", "revm", - "revm-statetest-types", "serde", "serde_json", "thiserror", diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index fd6296161b..80f954e492 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -17,8 +17,8 @@ revm = { workspace = true, features = [ "blst", "tracer", "parse", + "test-types", ] } -statetest-types.workspace = true # criterion criterion.workspace = true diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 64bfe7e19c..ee9b311d49 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -3,6 +3,9 @@ pub mod pre_block; use clap::Parser; +use revm::statetest_types::blockchain::{ + Account, BlockchainTest, BlockchainTestCase, ForkSpec, Withdrawal, +}; use revm::{ bytecode::Bytecode, context::{cfg::CfgEnv, ContextTr}, @@ -15,9 +18,6 @@ use revm::{ Context, Database, ExecuteCommitEvm, ExecuteEvm, InspectEvm, MainBuilder, MainContext, }; use serde_json::json; -use statetest_types::blockchain::{ - Account, BlockchainTest, BlockchainTestCase, ForkSpec, Withdrawal, -}; use std::{ collections::BTreeMap, fs, diff --git a/bins/revme/src/cmd/blockchaintest/post_block.rs b/bins/revme/src/cmd/blockchaintest/post_block.rs index 509548e2a3..22dc75a587 100644 --- a/bins/revme/src/cmd/blockchaintest/post_block.rs +++ b/bins/revme/src/cmd/blockchaintest/post_block.rs @@ -2,9 +2,9 @@ use revm::{ context::{Block, ContextTr, JournalTr}, handler::EvmTr, primitives::{address, hardfork::SpecId, Address, Bytes, ONE_ETHER, ONE_GWEI, U256}, + statetest_types::blockchain::Withdrawal, Database, DatabaseCommit, SystemCallCommitEvm, }; -use statetest_types::blockchain::Withdrawal; /// Post block transition that includes: /// * Block and uncle rewards before the Merge/Paris hardfork. diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 3e277f17fa..8db6eecb4b 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -10,10 +10,10 @@ use revm::{ database_interface::EmptyDB, inspector::{inspectors::TracerEip3155, InspectCommitEvm}, primitives::{hardfork::SpecId, Bytes, B256, U256}, + statetest_types::{SpecName, Test, TestSuite, TestUnit}, Context, ExecuteCommitEvm, MainBuilder, MainContext, }; use serde_json::json; -use statetest_types::{SpecName, Test, TestSuite, TestUnit}; use std::{ convert::Infallible, fmt::Debug, diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index c2c5ef0aed..3946ad1ca1 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -30,6 +30,7 @@ interpreter.workspace = true precompile.workspace = true primitives.workspace = true state.workspace = true +statetest-types = { workspace = true, optional = true } [dev-dependencies] serde_json = { workspace = true, features = ["alloc", "preserve_order"] } @@ -117,3 +118,6 @@ portable = ["precompile/portable"] # use gmp for modexp precompile. # It is faster library but licenced as GPL code, if enabled please make sure to follow the license. gmp = ["precompile/gmp"] + +# Statetest types for running ethereum tests +test-types = ["dep:statetest-types"] diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index befcc553f7..381004090a 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -26,6 +26,10 @@ pub use primitives; #[doc(inline)] pub use state; +#[cfg(feature = "test-types")] +#[doc(inline)] +pub use statetest_types; + // Export items. pub use context::{ diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 2df7f2764d..a3b7d5ab07 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -18,13 +18,18 @@ rustdoc-args = ["--cfg", "docsrs"] workspace = true [dependencies] -# revm -revm = { workspace = true, features = ["std", "serde"] } +# revm crates +primitives = { workspace = true, features = ["std", "serde"] } +bytecode = { workspace = true, features = ["std", "serde"] } +state = { workspace = true, features = ["std", "serde"] } +context = { workspace = true, features = ["std", "serde"] } +context-interface = { workspace = true, features = ["std", "serde"] } +database = { workspace = true, features = ["std", "serde"] } + serde = { workspace = true, features = ["derive", "rc"] } serde_json = { workspace = true, features = ["preserve_order"] } k256 = { workspace = true } thiserror = { workspace = true } -alloy-eips = { workspace = true } # alloy alloy-eip7928 = { workspace = true, features = ["std", "serde", "rlp"] } diff --git a/crates/statetest-types/src/account_info.rs b/crates/statetest-types/src/account_info.rs index df87ec10e8..0796800bea 100644 --- a/crates/statetest-types/src/account_info.rs +++ b/crates/statetest-types/src/account_info.rs @@ -1,4 +1,4 @@ -use revm::primitives::{Bytes, HashMap, StorageKey, StorageValue, U256}; +use primitives::{Bytes, HashMap, StorageKey, StorageValue, U256}; use serde::Deserialize; use crate::deserializer::deserialize_str_as_u64; diff --git a/crates/statetest-types/src/blockchain.rs b/crates/statetest-types/src/blockchain.rs index e7e83c90a9..494d014540 100644 --- a/crates/statetest-types/src/blockchain.rs +++ b/crates/statetest-types/src/blockchain.rs @@ -5,11 +5,9 @@ use crate::{deserialize_maybe_empty, AccountInfo, TestAuthorization}; use alloy_eip7928::BlockAccessList; -use revm::{ - context::{transaction::AccessList, BlockEnv, TxEnv}, - context_interface::block::BlobExcessGasAndPrice, - primitives::{Address, Bytes, FixedBytes, TxKind, B256, U256}, -}; +use context::{transaction::AccessList, BlockEnv, TxEnv}; +use context_interface::block::BlobExcessGasAndPrice; +use primitives::{Address, Bytes, FixedBytes, TxKind, B256, U256}; use serde::Deserialize; use std::collections::BTreeMap; @@ -444,7 +442,7 @@ impl BlockchainTestCase { #[cfg(test)] mod test { - use revm::primitives::address; + use primitives::address; use super::*; @@ -519,7 +517,7 @@ mod test { #[test] fn test_transaction_conversion() { use crate::blockchain::Transaction; - use revm::primitives::{Bytes, U256}; + use primitives::{Bytes, U256}; let tx = Transaction { transaction_type: Some(U256::from(0)), diff --git a/crates/statetest-types/src/deserializer.rs b/crates/statetest-types/src/deserializer.rs index 8ba97e928e..a092e4c40b 100644 --- a/crates/statetest-types/src/deserializer.rs +++ b/crates/statetest-types/src/deserializer.rs @@ -1,4 +1,4 @@ -use revm::primitives::Address; +use primitives::Address; use serde::{de, Deserialize}; /// Deserializes a [string][String] as a [u64]. diff --git a/crates/statetest-types/src/env.rs b/crates/statetest-types/src/env.rs index ae99f6538a..afda9af13d 100644 --- a/crates/statetest-types/src/env.rs +++ b/crates/statetest-types/src/env.rs @@ -1,4 +1,4 @@ -use revm::primitives::{Address, B256, U256}; +use primitives::{Address, B256, U256}; use serde::Deserialize; /// Environment variables diff --git a/crates/statetest-types/src/error.rs b/crates/statetest-types/src/error.rs index 3146a2f37a..9da12f77e5 100644 --- a/crates/statetest-types/src/error.rs +++ b/crates/statetest-types/src/error.rs @@ -1,4 +1,4 @@ -use revm::primitives::B256; +use primitives::B256; use thiserror::Error; /// Errors that can occur during test setup and execution diff --git a/crates/statetest-types/src/spec.rs b/crates/statetest-types/src/spec.rs index 4bdfbab483..c94db87f59 100644 --- a/crates/statetest-types/src/spec.rs +++ b/crates/statetest-types/src/spec.rs @@ -1,4 +1,4 @@ -use revm::primitives::hardfork::SpecId; +use primitives::hardfork::SpecId; use serde::Deserialize; /// Ethereum specification names diff --git a/crates/statetest-types/src/test.rs b/crates/statetest-types/src/test.rs index 8bc7cb9c42..72bf953c31 100644 --- a/crates/statetest-types/src/test.rs +++ b/crates/statetest-types/src/test.rs @@ -1,7 +1,5 @@ -use revm::{ - context::tx::TxEnv, - primitives::{Address, Bytes, HashMap, TxKind, B256}, -}; +use context::tx::TxEnv; +use primitives::{Address, Bytes, HashMap, TxKind, B256}; use serde::Deserialize; use crate::{ @@ -119,7 +117,7 @@ impl Test { .map(|auth_list| { auth_list .into_iter() - .map(|i| revm::context::either::Either::Left(i.into())) + .map(|i| context::either::Either::Left(i.into())) .collect::>() }) .unwrap_or_default(), diff --git a/crates/statetest-types/src/test_authorization.rs b/crates/statetest-types/src/test_authorization.rs index 10f1239608..1dd9d175ea 100644 --- a/crates/statetest-types/src/test_authorization.rs +++ b/crates/statetest-types/src/test_authorization.rs @@ -1,4 +1,4 @@ -use revm::context_interface::transaction::SignedAuthorization; +use context_interface::transaction::SignedAuthorization; use serde::{de::Error, Deserialize, Deserializer, Serialize}; /// Struct for test authorization diff --git a/crates/statetest-types/src/test_unit.rs b/crates/statetest-types/src/test_unit.rs index 618e837272..c09f720fb1 100644 --- a/crates/statetest-types/src/test_unit.rs +++ b/crates/statetest-types/src/test_unit.rs @@ -1,11 +1,9 @@ use crate::{AccountInfo, Env, SpecName, Test, TransactionParts}; -use revm::{ - context::{block::BlockEnv, cfg::CfgEnv}, - database::CacheState, - primitives::{hardfork::SpecId, keccak256, Address, Bytes, HashMap, B256}, - state::Bytecode, -}; +use context::{block::BlockEnv, cfg::CfgEnv}; +use database::CacheState; +use primitives::{hardfork::SpecId, keccak256, Address, Bytes, HashMap, B256}; use serde::Deserialize; +use state::Bytecode; use std::collections::BTreeMap; /// Single test unit struct @@ -71,7 +69,7 @@ impl TestUnit { let code_hash = keccak256(&info.code); let bytecode = Bytecode::new_raw_checked(info.code.clone()) .unwrap_or(Bytecode::new_legacy(info.code.clone())); - let acc_info = revm::state::AccountInfo { + let acc_info = state::AccountInfo { balance: info.balance, code_hash, code: Some(bytecode), @@ -133,12 +131,10 @@ impl TestUnit { #[cfg(test)] mod tests { use super::*; - use revm::{ - context_interface::block::calc_blob_gasprice, - primitives::{ - eip4844::{BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE}, - U256, - }, + use context_interface::block::calc_blob_gasprice; + use primitives::{ + eip4844::{BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN, BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE}, + U256, }; /// Creates a minimal TestUnit with excess blob gas set for testing blob fee calculation diff --git a/crates/statetest-types/src/transaction.rs b/crates/statetest-types/src/transaction.rs index 81a98a30a7..dc216d46ad 100644 --- a/crates/statetest-types/src/transaction.rs +++ b/crates/statetest-types/src/transaction.rs @@ -1,9 +1,7 @@ use crate::{deserializer::deserialize_maybe_empty, TestAuthorization}; -use revm::{ - context::TransactionType, - context_interface::transaction::AccessList, - primitives::{Address, Bytes, B256, U256}, -}; +use context::TransactionType; +use context_interface::transaction::AccessList; +use primitives::{Address, Bytes, B256, U256}; use serde::{Deserialize, Serialize}; /// Transaction parts. diff --git a/crates/statetest-types/src/utils.rs b/crates/statetest-types/src/utils.rs index 3ecc89594a..f9c30dd1cf 100644 --- a/crates/statetest-types/src/utils.rs +++ b/crates/statetest-types/src/utils.rs @@ -1,5 +1,5 @@ use k256::ecdsa::SigningKey; -use revm::primitives::Address; +use primitives::Address; /// Recover the address from a private key ([SigningKey]). pub fn recover_address(private_key: &[u8]) -> Option
{ @@ -11,7 +11,7 @@ pub fn recover_address(private_key: &[u8]) -> Option
{ #[cfg(test)] mod tests { use super::*; - use revm::primitives::{address, hex}; + use primitives::{address, hex}; #[test] fn sanity_test() { From cae8dd3e348a854541d68d565414837091d3b4c1 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Mon, 22 Dec 2025 22:56:28 +0400 Subject: [PATCH 088/127] perf: avoid collect in CacheState commit (#3242) * perf: avoid collect * fix * drain the iter --- crates/database/src/states/cache.rs | 29 ++++++++++++++++++++--------- crates/database/src/states/state.rs | 16 ++++++++++++---- 2 files changed, 32 insertions(+), 13 deletions(-) diff --git a/crates/database/src/states/cache.rs b/crates/database/src/states/cache.rs index c58f9e60f6..8b6870ef9b 100644 --- a/crates/database/src/states/cache.rs +++ b/crates/database/src/states/cache.rs @@ -93,19 +93,30 @@ impl CacheState { pub fn apply_evm_state( &mut self, evm_state: impl IntoIterator, - mut inspect: F, + inspect: F, ) -> Vec<(Address, TransitionAccount)> where F: FnMut(&Address, &Account), { - evm_state - .into_iter() - .filter_map(|(address, account)| { - inspect(&address, &account); - self.apply_account_state(address, account) - .map(|transition| (address, transition)) - }) - .collect() + self.apply_evm_state_iter(evm_state, inspect).collect() + } + + /// Applies output of revm execution and creates an iterator of account transitions. + #[inline] + pub(crate) fn apply_evm_state_iter<'a, F, T>( + &'a mut self, + evm_state: T, + mut inspect: F, + ) -> impl Iterator + use<'a, F, T> + where + F: FnMut(&Address, &Account), + T: IntoIterator, + { + evm_state.into_iter().filter_map(move |(address, account)| { + inspect(&address, &account); + self.apply_account_state(address, account) + .map(|transition| (address, transition)) + }) } /// Pretty print the cache state for debugging purposes. diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 775e6edcee..809b82d67d 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -383,18 +383,26 @@ impl Database for State { impl DatabaseCommit for State { fn commit(&mut self, changes: HashMap) { self.bal_state.commit(&changes); - let transitions = self.cache.apply_evm_state(changes, |_, _| {}); + let transitions = self.cache.apply_evm_state_iter(changes, |_, _| {}); if let Some(s) = self.transition_state.as_mut() { s.add_transitions(transitions) + } else { + // Advance the iter to apply all state updates. + transitions.for_each(|_| {}); } } fn commit_iter(&mut self, changes: impl IntoIterator) { - let transitions = self.cache.apply_evm_state(changes, |address, account| { - self.bal_state.commit_one(*address, account); - }); + let transitions = self + .cache + .apply_evm_state_iter(changes, |address, account| { + self.bal_state.commit_one(*address, account); + }); if let Some(s) = self.transition_state.as_mut() { s.add_transitions(transitions) + } else { + // Advance the iter to apply all state updates. + transitions.for_each(|_| {}); } } } From 481cf70960423c7012c3df761b937f30f0493441 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Tue, 23 Dec 2025 19:43:52 +0200 Subject: [PATCH 089/127] feat: dynamically link gmp (#3250) * feat: dynamically link gmp * ci: install gmp * fix(precompile): clean up gmp modexp clippy * Apply suggestion from @rakita * Update crates/precompile/Cargo.toml --------- Co-authored-by: rakita --- .github/workflows/ci.yml | 17 +++++ Cargo.lock | 20 +----- Cargo.toml | 2 +- crates/precompile/Cargo.toml | 12 ++-- crates/precompile/src/modexp.rs | 111 ++++++++++++++++++++++++++++---- crates/revm/Cargo.toml | 3 +- 6 files changed, 123 insertions(+), 42 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb348ab25f..e252d89b4d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,6 +29,11 @@ jobs: with: toolchain: ${{ matrix.rust }} - uses: Swatinem/rust-cache@v2 + - name: Install GMP (all-features) + if: contains(matrix.flags, '--all-features') + run: | + sudo apt-get update + sudo apt-get install -y libgmp-dev - run: cargo test --workspace ${{ matrix.flags }} check-no-std: @@ -74,6 +79,10 @@ jobs: - uses: Swatinem/rust-cache@v2 with: cache-on-failure: true + - name: Install GMP + run: | + sudo apt-get update + sudo apt-get install -y libgmp-dev - name: cargo hack run: cargo hack check --feature-powerset --depth 1 @@ -86,6 +95,10 @@ jobs: - uses: dtolnay/rust-toolchain@stable with: components: clippy + - name: Install GMP + run: | + sudo apt-get update + sudo apt-get install -y libgmp-dev - run: cargo clippy --workspace --all-targets --all-features env: RUSTFLAGS: -Dwarnings @@ -99,6 +112,10 @@ jobs: - uses: dtolnay/rust-toolchain@stable with: components: rust-docs + - name: Install GMP + run: | + sudo apt-get update + sudo apt-get install -y libgmp-dev - run: cargo doc --workspace --all-features --no-deps --document-private-items env: RUSTDOCFLAGS: "--cfg docsrs -D warnings" diff --git a/Cargo.lock b/Cargo.lock index b630d6d81f..b056d715b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1026,12 +1026,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "az" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" - [[package]] name = "backtrace" version = "0.3.75" @@ -3802,13 +3796,13 @@ dependencies = [ "c-kzg", "cfg-if", "codspeed-criterion-compat", + "gmp-mpfr-sys", "k256", "p256", "rand 0.9.2", "revm-primitives", "ripemd", "rstest", - "rug", "secp256k1 0.31.1", "sha2", "substrate-bn", @@ -3932,18 +3926,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "rug" -version = "1.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad2e973fe3c3214251a840a621812a4f40468da814b1a3d6947d433c2af11f" -dependencies = [ - "az", - "gmp-mpfr-sys", - "libc", - "libm", -] - [[package]] name = "ruint" version = "1.16.0" diff --git a/Cargo.toml b/Cargo.toml index 1bfb122ee9..867a136394 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -81,7 +81,7 @@ ark-ff = { version = "0.5", default-features = false } ark-serialize = { version = "0.5", default-features = false } ark-std = { version = "0.5", default-features = false } aurora-engine-modexp = { version = "1.2", default-features = false } -rug = { version = "1.28.0", default-features = false } +gmp-mpfr-sys = { version = "1.6", default-features = false } blst = "0.3.15" bn = { package = "substrate-bn", version = "0.6", default-features = false } c-kzg = { version = "2.1.4", default-features = false } diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index b17b1b3dba..0ee92291b8 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -23,8 +23,8 @@ primitives.workspace = true # modexp precompiles aurora-engine-modexp.workspace = true -# gmp wrapper -rug = { workspace = true, features = ["integer"], optional = true } +# gmp ffi +gmp-mpfr-sys = { workspace = true, default-features = false, optional = true } # ecRecover k256 = { workspace = true, features = ["ecdsa"] } @@ -75,6 +75,7 @@ rstest.workspace = true [features] default = ["std", "secp256k1", "blst", "c-kzg", "portable"] + std = [ "primitives/std", "k256/std", @@ -90,7 +91,6 @@ std = [ "ark-serialize/std", "ark-std/std", "p256/std", - "rug?/std", ] hashbrown = ["primitives/hashbrown"] asm-keccak = ["primitives/asm-keccak"] @@ -115,9 +115,9 @@ blst = ["dep:blst"] # Enables the substrate implementation of eip1962 bn = ["dep:bn"] -# Use rug (that wraps gmp) for modexp precompile. -# It is faster library but licences as GPL code, if enabled please make sure to follow the license. -gmp = ["dep:rug"] +# Use GMP (LGPL) for modexp precompile via gmp-mpfr-sys. +# This feature links to system GMP using the experimental `use-system-libs` flag. +gmp = ["dep:gmp-mpfr-sys", "gmp-mpfr-sys/use-system-libs"] [[bench]] name = "bench" diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index 7a4fde3ed2..2c209754bd 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -27,20 +27,103 @@ pub const OSAKA: Precompile = #[cfg(feature = "gmp")] /// GMP-based modular exponentiation implementation pub(crate) fn modexp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec { - use rug::{integer::Order::Msf, Integer}; - // Convert byte slices to GMP integers - let base_int = Integer::from_digits(base, Msf); - let exp_int = Integer::from_digits(exponent, Msf); - let mod_int = Integer::from_digits(modulus, Msf); - - // Perform modular exponentiation using GMP's pow_mod - let result = base_int.pow_mod(&exp_int, &mod_int).unwrap_or_default(); - - // Convert result back to bytes - let byte_count = result.significant_bits().div_ceil(8); - let mut output = vec![0u8; byte_count as usize]; - result.write_digits(&mut output, Msf); - output + use core::ffi::c_void; + use core::mem::MaybeUninit; + use gmp_mpfr_sys::gmp; + + struct Mpz(gmp::mpz_t); + + impl Mpz { + fn new() -> Self { + unsafe { + let mut inner = MaybeUninit::::uninit(); + gmp::mpz_init(inner.as_mut_ptr()); + Self(inner.assume_init()) + } + } + + fn as_ptr(&self) -> *const gmp::mpz_t { + &self.0 + } + + fn as_mut_ptr(&mut self) -> *mut gmp::mpz_t { + &mut self.0 + } + + fn set_from_be_bytes(&mut self, bytes: &[u8]) { + unsafe { + if bytes.is_empty() { + gmp::mpz_set_ui(self.as_mut_ptr(), 0); + return; + } + + gmp::mpz_import( + self.as_mut_ptr(), + bytes.len(), + 1, + 1, + 1, + 0, + bytes.as_ptr() as *const c_void, + ); + } + } + + fn to_be_bytes(&self) -> Vec { + unsafe { + if gmp::mpz_sgn(self.as_ptr()) == 0 { + return Vec::new(); + } + + let bits = gmp::mpz_sizeinbase(self.as_ptr(), 2); + let mut output = vec![0u8; bits.div_ceil(8)]; + let mut count: usize = 0; + gmp::mpz_export( + output.as_mut_ptr() as *mut c_void, + &mut count, + 1, + 1, + 1, + 0, + self.as_ptr(), + ); + output.truncate(count); + output + } + } + } + + impl Drop for Mpz { + fn drop(&mut self) { + unsafe { + gmp::mpz_clear(self.as_mut_ptr()); + } + } + } + + let mut base_int = Mpz::new(); + let mut exp_int = Mpz::new(); + let mut mod_int = Mpz::new(); + let mut result = Mpz::new(); + + base_int.set_from_be_bytes(base); + exp_int.set_from_be_bytes(exponent); + mod_int.set_from_be_bytes(modulus); + + unsafe { + if gmp::mpz_sgn(mod_int.as_ptr()) == 0 { + return Vec::new(); + } + + gmp::mpz_powm( + result.as_mut_ptr(), + base_int.as_ptr(), + exp_int.as_ptr(), + mod_int.as_ptr(), + ); + } + + result.to_be_bytes() } #[cfg(not(feature = "gmp"))] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 3946ad1ca1..eff908e784 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -115,8 +115,7 @@ asm-sha2 = ["precompile/asm-sha2"] # Binary can be executed on all systems. portable = ["precompile/portable"] -# use gmp for modexp precompile. -# It is faster library but licenced as GPL code, if enabled please make sure to follow the license. +# Use GMP for modexp precompile (LGPL; dynamically linked via system libs). gmp = ["precompile/gmp"] # Statetest types for running ethereum tests From b6cc5465aada3c1ffa05aa744d4616ab706507f1 Mon Sep 17 00:00:00 2001 From: Woojin Lee Date: Wed, 24 Dec 2025 08:06:08 +0900 Subject: [PATCH 090/127] fix(database): prevent deadlock in (#3251) async_db block_in_place usage Co-authored-by: WoojinLee --- crates/database/interface/src/async_db.rs | 36 ++++++++++++++++------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/crates/database/interface/src/async_db.rs b/crates/database/interface/src/async_db.rs index c1cbb260c0..6e35dac440 100644 --- a/crates/database/interface/src/async_db.rs +++ b/crates/database/interface/src/async_db.rs @@ -248,23 +248,37 @@ impl HandleOrRuntime { { match self { Self::Handle(handle) => { - // Use block_in_place only when we're currently inside a multi-threaded Tokio runtime - // and the handle belongs to the same runtime. Otherwise, call handle.block_on directly. - let can_block_in_place = match Handle::try_current() { - Ok(current) => { - // Only use block_in_place if we're in a multi-threaded runtime - // and the handle belongs to the current runtime (same handle instance). + // We use a conservative approach: if we're currently in a multi-threaded + // tokio runtime context, we use block_in_place. This works because: + // 1. If we're in the SAME runtime, block_in_place prevents deadlock + // 2. If we're in a DIFFERENT runtime, block_in_place still works safely + // (it just moves the work off the current worker thread before blocking) + // + // This approach is compatible with all tokio versions and doesn't require + // runtime identity comparison (Handle::id() is unstable feature). + let should_use_block_in_place = Handle::try_current() + .ok() + .map(|current| { + // Only use block_in_place for multi-threaded runtimes + // (block_in_place panics on current-thread runtime) !matches!( current.runtime_flavor(), tokio::runtime::RuntimeFlavor::CurrentThread - ) && core::ptr::eq(handle as *const _, ¤t as *const _) - } - Err(_) => false, - }; + ) + }) + .unwrap_or(false); - if can_block_in_place { + if should_use_block_in_place { + // We're in a multi-threaded runtime context. + // Use block_in_place to: + // 1. Move the blocking operation off the async worker thread + // 2. Prevent potential deadlock if this is the same runtime + // 3. Allow other tasks to continue executing tokio::task::block_in_place(move || handle.block_on(f)) } else { + // Safe to call block_on directly in these cases: + // - We're outside any runtime context + // - We're in a current-thread runtime (where block_in_place doesn't work) handle.block_on(f) } } From 5d7a353b482dd949396110b1e927ccad65d54d1c Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 24 Dec 2025 11:16:56 +0100 Subject: [PATCH 091/127] feat: rm gmp use-system-libs (#3253) --- crates/precompile/Cargo.toml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 0ee92291b8..d1ebbe473b 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -116,8 +116,9 @@ blst = ["dep:blst"] bn = ["dep:bn"] # Use GMP (LGPL) for modexp precompile via gmp-mpfr-sys. -# This feature links to system GMP using the experimental `use-system-libs` flag. -gmp = ["dep:gmp-mpfr-sys", "gmp-mpfr-sys/use-system-libs"] +# If you want to use a system libs and dynamic linking of GMP, include `gmp-mpfr-sys` in your project +# with a `features = ["use-system-libs"]` enabled. +gmp = ["dep:gmp-mpfr-sys"] [[bench]] name = "bench" From 3b17ee6dd6659934e662486c6996defc5f4cc5e2 Mon Sep 17 00:00:00 2001 From: Woojin Lee Date: Wed, 24 Dec 2025 21:29:58 +0900 Subject: [PATCH 092/127] feat: Propagate `map-foldhash` Feature Through Dependency Chain (#3252) * feat: propagate map-foldhash feature to revme and statetest-types * Make map-foldhash be default --------- Co-authored-by: WoojinLee --- bins/revme/Cargo.toml | 2 ++ crates/context/Cargo.toml | 1 + crates/database/Cargo.toml | 1 + crates/revm/Cargo.toml | 2 +- crates/state/Cargo.toml | 1 + crates/statetest-types/Cargo.toml | 8 ++++++++ 6 files changed, 14 insertions(+), 1 deletion(-) diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 80f954e492..c9eea11062 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -41,8 +41,10 @@ k256 = { workspace = true, features = ["ecdsa"] } csv = "1.1.6" [features] +default = ["map-foldhash"] # Optionally enable gmp because it doesn't work on i686 github actions runners gmp = ["revm/gmp"] +map-foldhash = ["revm/map-foldhash"] [[bench]] name = "evm" diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 26bce81389..6ffe809ff9 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -79,3 +79,4 @@ optional_eip7623 = [] optional_no_base_fee = [] optional_priority_fee_check = [] optional_fee_charge = [] +map-foldhash = ["primitives/map-foldhash", "state/map-foldhash"] diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 6481ebaaaa..11ff562fa8 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -65,3 +65,4 @@ alloydb = [ "dep:alloy-eips", "dep:alloy-transport", ] +map-foldhash = ["primitives/map-foldhash", "state/map-foldhash"] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index eff908e784..4b590aeeb1 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -54,7 +54,7 @@ std = [ "serde_json/std", ] hashbrown = ["interpreter/hashbrown", "precompile/hashbrown"] -map-foldhash = ["primitives/map-foldhash"] +map-foldhash = ["primitives/map-foldhash", "statetest-types?/map-foldhash"] serde = [ "interpreter/serde", "database-interface/serde", diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 9c67155a27..48f0efe1c4 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -51,3 +51,4 @@ serde = [ "bytecode/serde", "alloy-eip7928/serde", ] +map-foldhash = ["primitives/map-foldhash"] diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index a3b7d5ab07..df8dc9a686 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -33,3 +33,11 @@ thiserror = { workspace = true } # alloy alloy-eip7928 = { workspace = true, features = ["std", "serde", "rlp"] } + +[features] +map-foldhash = [ + "primitives/map-foldhash", + "state/map-foldhash", + "context/map-foldhash", + "database/map-foldhash", +] From fa5762c3884b971bf51283eea9426aa72dab30c4 Mon Sep 17 00:00:00 2001 From: Doohyun Cho <158799614+doocho@users.noreply.github.com> Date: Fri, 26 Dec 2025 19:23:10 +0900 Subject: [PATCH 093/127] refactor: remove redundant clone calls (#3258) Remove unnecessary `.clone()` calls where variables are not used after the clone, allowing direct ownership transfer instead of copying. Files modified: - examples/contract_deployment/src/main.rs - bins/revme/src/cmd/bench/burntpix.rs - bins/revme/src/cmd/bench/snailtracer.rs - bins/revme/src/cmd/blockchaintest.rs - bins/revme/src/cmd/statetest/runner.rs --- bins/revme/src/cmd/bench/burntpix.rs | 2 +- bins/revme/src/cmd/bench/snailtracer.rs | 2 +- bins/revme/src/cmd/blockchaintest.rs | 2 +- bins/revme/src/cmd/statetest/runner.rs | 12 ++++++------ examples/contract_deployment/src/main.rs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index 8d1a0641b0..cc19f7937c 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -43,7 +43,7 @@ pub fn run(criterion: &mut Criterion) { let tx = TxEnv::builder() .caller(BENCH_CALLER) .kind(TxKind::Call(BURNTPIX_MAIN_ADDRESS)) - .data(run_call_data.clone().into()) + .data(run_call_data.into()) .gas_limit(u64::MAX) .build() .unwrap(); diff --git a/bins/revme/src/cmd/bench/snailtracer.rs b/bins/revme/src/cmd/bench/snailtracer.rs index 222a7ecc7d..d9ea2d186a 100644 --- a/bins/revme/src/cmd/bench/snailtracer.rs +++ b/bins/revme/src/cmd/bench/snailtracer.rs @@ -13,7 +13,7 @@ pub fn run(criterion: &mut Criterion) { let bytecode = Bytecode::new_raw(Bytes::from(hex::decode(BYTES).unwrap())); let mut evm = Context::mainnet() - .with_db(BenchmarkDB::new_bytecode(bytecode.clone())) + .with_db(BenchmarkDB::new_bytecode(bytecode)) .modify_cfg_chained(|c| c.disable_nonce_check = true) .build_mainnet() .with_inspector(NoOpInspector {}); diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index ee9b311d49..070eec7a55 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -268,7 +268,7 @@ fn run_test_file( println!("{}", serde_json::to_string(&output).unwrap()); } return Err(Error::TestExecution { - test_name: test_name.clone(), + test_name, test_path: file_path.to_path_buf(), error: e.to_string(), }); diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 8db6eecb4b..183f599c70 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -361,8 +361,8 @@ pub fn execute_test_suite( Err(_) if test.expect_exception.is_some() => continue, Err(_) => { return Err(TestError { - name: name.clone(), - path: path.clone(), + name, + path, kind: TestErrorKind::UnknownPrivateKey(unit.transaction.secret_key), }); } @@ -387,8 +387,8 @@ pub fn execute_test_suite( static FAILED: AtomicBool = AtomicBool::new(false); if print_json_outcome || FAILED.swap(true, Ordering::SeqCst) { return Err(TestError { - name: name.clone(), - path: path.clone(), + name, + path, kind: e, }); } @@ -407,8 +407,8 @@ pub fn execute_test_suite( }); return Err(TestError { - path: path.clone(), - name: name.clone(), + path, + name, kind: e, }); } diff --git a/examples/contract_deployment/src/main.rs b/examples/contract_deployment/src/main.rs index 02bf76e96b..0fe18462b0 100644 --- a/examples/contract_deployment/src/main.rs +++ b/examples/contract_deployment/src/main.rs @@ -55,7 +55,7 @@ fn main() -> anyhow::Result<()> { let ref_tx = evm.transact_commit( TxEnv::builder() .kind(TxKind::Create) - .data(bytecode.clone()) + .data(bytecode) .build() .unwrap(), )?; From e5c8b25c3f9df8374722742871b603b77b74a8d7 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Fri, 26 Dec 2025 13:25:18 +0300 Subject: [PATCH 094/127] refactor(revme): extract JSON printing helper in blockchaintest (#3257) --- bins/revme/src/cmd/blockchaintest.rs | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 070eec7a55..ad0d2e4637 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -28,6 +28,11 @@ use std::{ use thiserror::Error; use walkdir::{DirEntry, WalkDir}; +/// Panics if the value cannot be serialized to JSON. +fn print_json(value: &T) { + println!("{}", serde_json::to_string(value).unwrap()); +} + /// `blockchaintest` subcommand #[derive(Parser, Debug)] pub struct Cmd { @@ -123,7 +128,7 @@ fn run_tests( "status": "skipped", "reason": "known_issue" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else if !omit_progress { println!( "Skipping ({}/{}): {}", @@ -163,7 +168,7 @@ fn run_tests( "error": e.to_string(), "status": "failed" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else if !omit_progress { eprintln!( "✗ ({}/{}) {} - {}", @@ -192,7 +197,7 @@ fn run_tests( "duration_secs": duration.as_secs_f64(), } }); - println!("{}", serde_json::to_string(&results).unwrap()); + print_json(&results); } else { // Print failed test paths if keep-going was enabled if keep_going && !failed_paths.is_empty() { @@ -238,7 +243,7 @@ fn run_test_file( "file": file_path.display().to_string(), "status": "running" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else { println!(" Running: {test_name}"); } @@ -253,7 +258,7 @@ fn run_test_file( "file": file_path.display().to_string(), "status": "passed" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } test_count += 1; } @@ -265,7 +270,7 @@ fn run_test_file( "status": "failed", "error": e.to_string() }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } return Err(Error::TestExecution { test_name, @@ -799,7 +804,7 @@ fn execute_blockchain_test( "error": "missing sender", "status": "skipped" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else { eprintln!("⚠️ Skipping block {block_idx} due to missing sender"); } @@ -836,7 +841,7 @@ fn execute_blockchain_test( "error": format!("tx env creation error: {e}"), "status": "skipped" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else { eprintln!( "⚠️ Skipping block {block_idx} due to transaction env creation error: {e}" @@ -894,7 +899,7 @@ fn execute_blockchain_test( "gas_used": result.result.gas_used(), "status": "unexpected_success" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else { eprintln!( "⚠️ Skipping block {block_idx}: transaction unexpectedly succeeded (expected failure: {expected_exception})" @@ -937,7 +942,7 @@ fn execute_blockchain_test( "error": format!("{e:?}"), "status": "unexpected_failure" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } else { eprintln!( "⚠️ Skipping block {block_idx} due to unexpected failure: {e:?}" @@ -952,7 +957,7 @@ fn execute_blockchain_test( "error": format!("{e:?}"), "status": "expected_failure" }); - println!("{}", serde_json::to_string(&output).unwrap()); + print_json(&output); } } } From 2b3a3aab62c1017c075e18fc128d1cfe1e356487 Mon Sep 17 00:00:00 2001 From: Preston Evans <32944016+preston-evans98@users.noreply.github.com> Date: Fri, 26 Dec 2025 02:25:55 -0800 Subject: [PATCH 095/127] docs: description of `Handler::validate_against_state_and_deduct_caller` should match responsibilities (#3256) * Fix doc comment on Handler::validate_against_state_and_deduct_caller * Fmt --- crates/handler/src/handler.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 1b96c3fbe7..96b1911345 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -295,7 +295,11 @@ pub trait Handler { apply_eip7702_auth_list(evm.ctx_mut()) } - /// Deducts maximum possible fee and transfer value from caller's balance. + /// Deducts the maximum possible fee from caller's balance. + /// + /// If cfg.is_balance_check_disabled, this method will add back enough funds to ensure that + /// the caller's balance is at least tx.value() before returning. Note that the amount of funds + /// added back in this case may exceed the maximum fee. /// /// Unused fees are returned to caller after execution completes. #[inline] From 949a8a82eb8a1a0c303f738102a2909b4ef011d2 Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 26 Dec 2025 18:47:47 +0800 Subject: [PATCH 096/127] chore: sort storage keys and test files in blockchaintest output (#3186) * chore: sort storage keys and test files in blockchaintest output * sort storage keys and print all slots in blockchaintest output * sort storage keys and print all slots in blockchaintest output --- bins/revme/src/cmd/blockchaintest.rs | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index ad0d2e4637..6c262a33b5 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -607,12 +607,11 @@ fn print_error_with_state( ); if !storage.is_empty() { eprintln!(" Storage ({} slots):", storage.len()); - for (key, value) in storage.iter().take(5) { + let mut sorted_storage: Vec<_> = storage.iter().collect(); + sorted_storage.sort_by_key(|(key, _)| *key); + for (key, value) in sorted_storage.iter() { eprintln!(" {key:?} => {value:?}"); } - if storage.len() > 5 { - eprintln!(" ... and {} more slots", storage.len() - 5); - } } } @@ -632,12 +631,11 @@ fn print_error_with_state( ); if !storage.is_empty() { eprintln!(" Storage ({} slots):", storage.len()); - for (key, value) in storage.iter().take(5) { + let mut sorted_storage: Vec<_> = storage.iter().collect(); + sorted_storage.sort_by_key(|(key, _)| *key); + for (key, value) in sorted_storage.iter() { eprintln!(" {key:?} => {value:?}"); } - if storage.len() > 5 { - eprintln!(" ... and {} more slots", storage.len() - 5); - } } } @@ -653,12 +651,9 @@ fn print_error_with_state( } if !account.storage.is_empty() { eprintln!(" Storage ({} slots):", account.storage.len()); - for (key, value) in account.storage.iter().take(5) { + for (key, value) in account.storage.iter() { eprintln!(" {key:?} => {value:?}"); } - if account.storage.len() > 5 { - eprintln!(" ... and {} more slots", account.storage.len() - 5); - } } } } From d510c46a36804ddb36942190239784b0038932d6 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Mon, 29 Dec 2025 16:44:10 +0300 Subject: [PATCH 097/127] refactor(revme): use unwrap_or_default for non-UTF8 path safety (#3259) --- bins/revme/src/cmd/blockchaintest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 6c262a33b5..10461e0779 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -1059,7 +1059,7 @@ fn skip_test(path: &Path) -> bool { return true; } - let name = path.file_name().unwrap().to_str().unwrap(); + let name = path.file_name().unwrap().to_str().unwrap_or_default(); // Add any problematic tests here that should be skipped matches!( name, From 2c1153b8c5645560b71c1ba3abc13d547488047e Mon Sep 17 00:00:00 2001 From: MoNyAvA Date: Tue, 30 Dec 2025 18:10:56 +0100 Subject: [PATCH 098/127] perf: avoid loading bytecode in extcodehash (#3261) --- crates/interpreter/src/instructions/host.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 6dec54b8fd..489be144b6 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -84,11 +84,11 @@ pub fn extcodehash( let spec_id = context.interpreter.runtime_flag.spec_id(); let account = if spec_id.is_enabled_in(BERLIN) { - berlin_load_account!(context, address, true) + berlin_load_account!(context, address, false) } else { let Ok(account) = context .host - .load_account_info_skip_cold_load(address, true, false) + .load_account_info_skip_cold_load(address, false, false) else { return context.interpreter.halt_fatal(); }; From 27664ca7c47d81ed82cb05aa62ea0e3d3878753c Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 31 Dec 2025 04:24:10 -0600 Subject: [PATCH 099/127] fix: the MLOAD opcode can resize memory (#3266) --- crates/bytecode/src/opcode.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index 4f1d4247f7..20a0aaad55 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -182,6 +182,7 @@ impl OpCode { matches!( *self, OpCode::EXTCODECOPY + | OpCode::MLOAD | OpCode::MSTORE | OpCode::MSTORE8 | OpCode::MCOPY @@ -768,7 +769,7 @@ mod tests { #[test] fn test_modifies_memory() { - assert!(!OpCode::new(MLOAD).unwrap().modifies_memory()); + assert!(OpCode::new(MLOAD).unwrap().modifies_memory()); assert!(OpCode::new(MSTORE).unwrap().modifies_memory()); assert!(!OpCode::new(ADD).unwrap().modifies_memory()); } From db8ce329052353becfb627bb1de2a8e69bf6c5c7 Mon Sep 17 00:00:00 2001 From: Ryan Date: Wed, 31 Dec 2025 18:24:40 +0800 Subject: [PATCH 100/127] add Display for HaltReason and OutOfGasError (#3265) --- crates/context/interface/src/result.rs | 46 ++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/crates/context/interface/src/result.rs b/crates/context/interface/src/result.rs index 2bbb99583c..8d20a68729 100644 --- a/crates/context/interface/src/result.rs +++ b/crates/context/interface/src/result.rs @@ -629,6 +629,37 @@ pub enum HaltReason { CallTooDeep, } +impl core::error::Error for HaltReason {} + +impl fmt::Display for HaltReason { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::OutOfGas(err) => write!(f, "{err}"), + Self::OpcodeNotFound => write!(f, "opcode not found"), + Self::InvalidFEOpcode => write!(f, "invalid 0xFE opcode"), + Self::InvalidJump => write!(f, "invalid jump destination"), + Self::NotActivated => write!(f, "feature or opcode not activated"), + Self::StackUnderflow => write!(f, "stack underflow"), + Self::StackOverflow => write!(f, "stack overflow"), + Self::OutOfOffset => write!(f, "out of offset"), + Self::CreateCollision => write!(f, "create collision"), + Self::PrecompileError => write!(f, "precompile error"), + Self::PrecompileErrorWithContext(msg) => write!(f, "precompile error: {msg}"), + Self::NonceOverflow => write!(f, "nonce overflow"), + Self::CreateContractSizeLimit => write!(f, "create contract size limit"), + Self::CreateContractStartingWithEF => { + write!(f, "create contract starting with 0xEF") + } + Self::CreateInitCodeSizeLimit => write!(f, "create initcode size limit"), + Self::OverflowPayment => write!(f, "overflow payment"), + Self::StateChangeDuringStaticCall => write!(f, "state change during static call"), + Self::CallNotAllowedInsideStatic => write!(f, "call not allowed inside static call"), + Self::OutOfFunds => write!(f, "out of funds"), + Self::CallTooDeep => write!(f, "call too deep"), + } + } +} + /// Out of gas errors. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -648,6 +679,21 @@ pub enum OutOfGasError { ReentrancySentry, } +impl core::error::Error for OutOfGasError {} + +impl fmt::Display for OutOfGasError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Basic => write!(f, "out of gas"), + Self::MemoryLimit => write!(f, "out of gas: memory limit exceeded"), + Self::Memory => write!(f, "out of gas: memory expansion"), + Self::Precompile => write!(f, "out of gas: precompile"), + Self::InvalidOperand => write!(f, "out of gas: invalid operand"), + Self::ReentrancySentry => write!(f, "out of gas: reentrancy sentry"), + } + } +} + /// Error that includes transaction index for batch transaction processing. #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] From 76a21b2c79cde3e41f06f3b2d06ad97c452d06b1 Mon Sep 17 00:00:00 2001 From: Ryan Date: Mon, 5 Jan 2026 03:33:55 +0800 Subject: [PATCH 101/127] chore: add Display trait for ExecutionResult and related types (#3267) * Add Display trait for ExecutionResult and related types * fix fmt --- crates/context/interface/src/result.rs | 112 +++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/crates/context/interface/src/result.rs b/crates/context/interface/src/result.rs index 8d20a68729..282495ce1a 100644 --- a/crates/context/interface/src/result.rs +++ b/crates/context/interface/src/result.rs @@ -176,6 +176,45 @@ impl ExecutionResult { } } +impl fmt::Display for ExecutionResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Success { + reason, + gas_used, + gas_refunded, + logs, + output, + } => { + write!( + f, + "Success ({}): {} gas used, {} refunded", + reason, gas_used, gas_refunded + )?; + if !logs.is_empty() { + write!( + f, + ", {} log{}", + logs.len(), + if logs.len() == 1 { "" } else { "s" } + )?; + } + write!(f, ", {}", output) + } + Self::Revert { gas_used, output } => { + write!(f, "Revert: {} gas used", gas_used)?; + if !output.is_empty() { + write!(f, ", {} bytes output", output.len())?; + } + Ok(()) + } + Self::Halt { reason, gas_used } => { + write!(f, "Halted: {} ({} gas used)", reason, gas_used) + } + } + } +} + /// Output of a transaction execution #[derive(Debug, Clone, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -212,6 +251,34 @@ impl Output { } } +impl fmt::Display for Output { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Output::Call(data) => { + if data.is_empty() { + write!(f, "no output") + } else { + write!(f, "{} bytes output", data.len()) + } + } + Output::Create(data, Some(addr)) => { + if data.is_empty() { + write!(f, "contract created at {}", addr) + } else { + write!(f, "contract created at {} ({} bytes)", addr, data.len()) + } + } + Output::Create(data, None) => { + if data.is_empty() { + write!(f, "contract creation (no address)") + } else { + write!(f, "contract creation (no address, {} bytes)", data.len()) + } + } + } + } +} + /// Main EVM error #[derive(Debug, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -579,6 +646,16 @@ pub enum SuccessReason { SelfDestruct, } +impl fmt::Display for SuccessReason { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Stop => write!(f, "Stop"), + Self::Return => write!(f, "Return"), + Self::SelfDestruct => write!(f, "SelfDestruct"), + } + } +} + /// Indicates that the EVM has experienced an exceptional halt. /// /// This causes execution to immediately end with all gas being consumed. @@ -753,3 +830,38 @@ impl From for InvalidTransaction { Self::Str(Cow::Owned(s)) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_execution_result_display() { + let result: ExecutionResult = ExecutionResult::Success { + reason: SuccessReason::Return, + gas_used: 21000, + gas_refunded: 5000, + logs: vec![Log::default(), Log::default()], + output: Output::Call(Bytes::from(vec![1, 2, 3])), + }; + assert_eq!( + result.to_string(), + "Success (Return): 21000 gas used, 5000 refunded, 2 logs, 3 bytes output" + ); + + let result: ExecutionResult = ExecutionResult::Revert { + gas_used: 100000, + output: Bytes::from(vec![1, 2, 3, 4]), + }; + assert_eq!( + result.to_string(), + "Revert: 100000 gas used, 4 bytes output" + ); + + let result: ExecutionResult = ExecutionResult::Halt { + reason: HaltReason::OutOfGas(OutOfGasError::Basic), + gas_used: 1000000, + }; + assert_eq!(result.to_string(), "Halted: out of gas (1000000 gas used)"); + } +} From d551ca7f051de417b95aa6b105fc981738a6ab64 Mon Sep 17 00:00:00 2001 From: Joey Bright Date: Mon, 5 Jan 2026 11:06:33 +0000 Subject: [PATCH 102/127] chore: the KECCAK256 opcode can resize memory (#3269) --- crates/bytecode/src/opcode.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index 20a0aaad55..95db0ad2d2 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -186,6 +186,7 @@ impl OpCode { | OpCode::MSTORE | OpCode::MSTORE8 | OpCode::MCOPY + | OpCode::KECCAK256 | OpCode::CODECOPY | OpCode::CALLDATACOPY | OpCode::RETURNDATACOPY @@ -771,6 +772,7 @@ mod tests { fn test_modifies_memory() { assert!(OpCode::new(MLOAD).unwrap().modifies_memory()); assert!(OpCode::new(MSTORE).unwrap().modifies_memory()); + assert!(OpCode::new(KECCAK256).unwrap().modifies_memory()); assert!(!OpCode::new(ADD).unwrap().modifies_memory()); } } From fd8d92032275d0cef5c5cc4aa29a8784febc2eb8 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 5 Jan 2026 13:59:16 +0100 Subject: [PATCH 103/127] chore: happy new year, 2026 licence (#3272) --- LICENSE | 2 +- bins/revme/LICENSE | 2 +- crates/bytecode/LICENSE | 2 +- crates/context/LICENSE | 2 +- crates/context/interface/LICENSE | 2 +- crates/database/LICENSE | 2 +- crates/database/interface/LICENSE | 2 +- crates/handler/LICENSE | 2 +- crates/inspector/LICENSE | 2 +- crates/interpreter/LICENSE | 2 +- crates/op-revm/LICENSE | 2 +- crates/precompile/LICENSE | 2 +- crates/primitives/LICENSE | 2 +- crates/revm/LICENSE | 2 +- crates/state/LICENSE | 2 +- crates/statetest-types/LICENSE | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/LICENSE b/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/bins/revme/LICENSE b/bins/revme/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/bins/revme/LICENSE +++ b/bins/revme/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/bytecode/LICENSE b/crates/bytecode/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/bytecode/LICENSE +++ b/crates/bytecode/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/context/LICENSE b/crates/context/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/context/LICENSE +++ b/crates/context/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/context/interface/LICENSE b/crates/context/interface/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/context/interface/LICENSE +++ b/crates/context/interface/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/database/LICENSE b/crates/database/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/database/LICENSE +++ b/crates/database/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/database/interface/LICENSE b/crates/database/interface/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/database/interface/LICENSE +++ b/crates/database/interface/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/handler/LICENSE b/crates/handler/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/handler/LICENSE +++ b/crates/handler/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/inspector/LICENSE b/crates/inspector/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/inspector/LICENSE +++ b/crates/inspector/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/interpreter/LICENSE b/crates/interpreter/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/interpreter/LICENSE +++ b/crates/interpreter/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/op-revm/LICENSE b/crates/op-revm/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/op-revm/LICENSE +++ b/crates/op-revm/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/precompile/LICENSE b/crates/precompile/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/precompile/LICENSE +++ b/crates/precompile/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/primitives/LICENSE b/crates/primitives/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/primitives/LICENSE +++ b/crates/primitives/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/revm/LICENSE b/crates/revm/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/revm/LICENSE +++ b/crates/revm/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/state/LICENSE b/crates/state/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/state/LICENSE +++ b/crates/state/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/crates/statetest-types/LICENSE b/crates/statetest-types/LICENSE index be6d350ebe..7edb0405ff 100644 --- a/crates/statetest-types/LICENSE +++ b/crates/statetest-types/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2021-2025 draganrakita +Copyright (c) 2021-2026 draganrakita Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 191e2e3955589b9617e02612c6b9d5b3c722dff6 Mon Sep 17 00:00:00 2001 From: malik Date: Mon, 5 Jan 2026 16:49:05 +0100 Subject: [PATCH 104/127] perf: add optimization for push and pop (#3263) * add optimization for push and pop * format * format * add assume and unlikely instrincts * revert * Update crates/interpreter/src/interpreter/stack.rs --- crates/interpreter/src/interpreter/stack.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index 761ec7da6c..62c4a7bf0c 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -153,7 +153,16 @@ impl Stack { #[inline] #[cfg_attr(debug_assertions, track_caller)] pub fn pop(&mut self) -> Result { - self.data.pop().ok_or(InstructionResult::StackUnderflow) + //Todo: can you likely instrincts to show the else branch is more likely to be hit + let len = self.data.len(); + if primitives::hints_util::unlikely(len == 0) { + Err(InstructionResult::StackUnderflow) + } else { + unsafe { + self.data.set_len(len - 1); + Ok(core::ptr::read(self.data.as_ptr().add(len - 1))) + } + } } /// Removes the topmost element from the stack and returns it. @@ -215,10 +224,15 @@ impl Stack { pub fn push(&mut self, value: U256) -> bool { // In debug builds, verify we have sufficient capacity provisioned. debug_assert!(self.data.capacity() >= STACK_LIMIT); - if self.data.len() == STACK_LIMIT { + let len = self.data.len(); + if len == STACK_LIMIT { return false; } - self.data.push(value); + unsafe { + let end = self.data.as_mut_ptr().add(len); + core::ptr::write(end, value); + self.data.set_len(len + 1); + } true } From 811b229447386fa8f610dd9f343bb3cb4c556f6a Mon Sep 17 00:00:00 2001 From: Fallengirl <155266340+Fallengirl@users.noreply.github.com> Date: Wed, 7 Jan 2026 23:56:35 +0100 Subject: [PATCH 105/127] fix(bytecode): remove duplicate implementation in bytes_ref method (#3276) --- crates/bytecode/src/bytecode.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bytecode/src/bytecode.rs b/crates/bytecode/src/bytecode.rs index 162d0839b4..259c3c1fa8 100644 --- a/crates/bytecode/src/bytecode.rs +++ b/crates/bytecode/src/bytecode.rs @@ -147,10 +147,7 @@ impl Bytecode { /// Returns raw bytes reference. #[inline] pub fn bytes_ref(&self) -> &Bytes { - match self { - Self::LegacyAnalyzed(analyzed) => analyzed.bytecode(), - Self::Eip7702(code) => code.raw(), - } + self.bytecode() } /// Returns raw bytes slice. From 68575927ead6d6789b0d3a5cc6f68f47f8bd2bc1 Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Thu, 8 Jan 2026 05:07:34 +0200 Subject: [PATCH 106/127] fix: incorrect bytecode value in blockchain test error output (#3288) --- bins/revme/src/cmd/blockchaintest.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 10461e0779..1ddc3da260 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -406,7 +406,7 @@ fn validate_post_state( *address, "code".to_string(), format!("0x{}", hex::encode(&expected_account.code)), - format!("0x{}", hex::encode(actual_code.bytecode())), + format!("0x{}", hex::encode(actual_code.original_byte_slice())), ); } } else { @@ -603,7 +603,7 @@ fn print_error_with_state( eprintln!(" Code hash: {:?}", info.code_hash); eprintln!( " Code size: {} bytes", - info.code.as_ref().map_or(0, |c| c.bytecode().len()) + info.code.as_ref().map_or(0, |c| c.len()) ); if !storage.is_empty() { eprintln!(" Storage ({} slots):", storage.len()); @@ -627,7 +627,7 @@ fn print_error_with_state( eprintln!(" Code hash: {:?}", info.code_hash); eprintln!( " Code size: {} bytes", - info.code.as_ref().map_or(0, |c| c.bytecode().len()) + info.code.as_ref().map_or(0, |c| c.len()) ); if !storage.is_empty() { eprintln!(" Storage ({} slots):", storage.len()); From 7f3083b9ac5d72f31519a853c3e51ede1ff8641f Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 8 Jan 2026 11:36:36 +0100 Subject: [PATCH 107/127] feat: move GasParams to Cfg (#3229) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: move GasParams to Cfg * propagate spec id * use cfg spec when evm is created * nits * nit * doc tests * use derive-where to skip fn * Move SetSpecTr and use it as main tr * remove SetSpecTr, introduce is_custom_gas_param flag * simplification * nits and tests fix * morf spec type * dont compare ptr * import fix * typo * ref alloy-eips * add core::error::Error impl to BalError 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * send/sync on GasParams * relex generic for some Cfg functions --------- Co-authored-by: Claude Opus 4.5 --- Cargo.lock | 5 +- Cargo.toml | 2 +- bins/revme/src/cmd/blockchaintest.rs | 6 +- bins/revme/src/cmd/statetest/runner.rs | 24 +- crates/context/interface/src/cfg.rs | 9 + crates/context/interface/src/cfg/gas.rs | 298 ++++++++++++++++++ .../interface/src/cfg/gas_params.rs} | 40 ++- crates/context/interface/src/host.rs | 25 +- .../interface/src/journaled_state/account.rs | 15 +- crates/context/src/cfg.rs | 151 +++++++-- crates/context/src/context.rs | 15 +- crates/ee-tests/src/op_revm_tests.rs | 46 +-- crates/ee-tests/src/revm_tests.rs | 8 +- crates/handler/src/evm.rs | 8 +- crates/handler/src/frame.rs | 20 +- crates/handler/src/handler.rs | 13 - crates/handler/src/instructions.rs | 42 +-- crates/handler/src/mainnet_builder.rs | 12 +- crates/handler/src/precompile_provider.rs | 8 + crates/handler/src/validation.rs | 2 +- crates/inspector/src/handler.rs | 3 - crates/interpreter/src/gas.rs | 14 +- crates/interpreter/src/gas/calc.rs | 39 +-- crates/interpreter/src/gas/constants.rs | 103 ------ crates/interpreter/src/instructions.rs | 5 +- .../src/instructions/arithmetic.rs | 5 +- .../interpreter/src/instructions/bitwise.rs | 13 +- .../interpreter/src/instructions/contract.rs | 33 +- .../src/instructions/contract/call_helpers.rs | 32 +- .../interpreter/src/instructions/control.rs | 20 +- crates/interpreter/src/instructions/host.rs | 41 ++- crates/interpreter/src/instructions/macros.rs | 13 +- crates/interpreter/src/instructions/memory.rs | 24 +- crates/interpreter/src/instructions/system.rs | 50 ++- crates/interpreter/src/interpreter.rs | 41 +-- .../src/interpreter/shared_memory.rs | 3 +- crates/op-revm/src/evm.rs | 18 +- crates/op-revm/src/handler.rs | 50 +-- crates/op-revm/src/l1block.rs | 6 +- crates/state/src/bal.rs | 2 + crates/statetest-types/src/test_unit.rs | 11 +- examples/erc20_gas/src/main.rs | 6 +- 42 files changed, 794 insertions(+), 487 deletions(-) create mode 100644 crates/context/interface/src/cfg/gas.rs rename crates/{interpreter/src/gas/params.rs => context/interface/src/cfg/gas_params.rs} (96%) delete mode 100644 crates/interpreter/src/gas/constants.rs diff --git a/Cargo.lock b/Cargo.lock index b056d715b1..9820c7f05a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -137,8 +137,9 @@ dependencies = [ [[package]] name = "alloy-eip7928" -version = "0.2.0" -source = "git+https://github.com/rakita/alloy-eips.git?rev=734beaf#734beafea409bdd87b3a4e33ac72ac68654bb8dd" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6adac476434bf024279164dcdca299309f0c7d1e3557024eb7a83f8d9d01c6b5" dependencies = [ "alloy-primitives", "alloy-rlp", diff --git a/Cargo.toml b/Cargo.toml index 867a136394..e2f10307c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,7 +60,7 @@ ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1 # alloy alloy-eip2930 = { version = "0.2.1", default-features = false } alloy-eip7702 = { version = "0.6.1", default-features = false } -alloy-eip7928 = { version = "0.2.0", default-features = false, git = "https://github.com/rakita/alloy-eips.git", rev = "734beaf" } +alloy-eip7928 = { version = "0.3.0", default-features = false } alloy-primitives = { version = "1.5.0", default-features = false } # alloy in examples, revme or feature flagged. diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 1ddc3da260..928043dd9c 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -481,7 +481,7 @@ fn print_error_with_state( // Print configuration environment eprintln!("\n📋 Configuration Environment:"); - eprintln!(" Spec ID: {:?}", debug_info.cfg_env.spec); + eprintln!(" Spec ID: {:?}", debug_info.cfg_env.spec()); eprintln!(" Chain ID: {}", debug_info.cfg_env.chain_id); eprintln!( " Limit contract code size: {:?}", @@ -714,7 +714,7 @@ fn execute_blockchain_test( // Setup configuration based on fork let spec_id = fork_to_spec_id(test_case.network); let mut cfg = CfgEnv::default(); - cfg.spec = spec_id; + cfg.set_spec_and_mainnet_gas_params(spec_id); // Genesis block is not used yet. let mut parent_block_hash = Some(test_case.genesis_block_header.hash); @@ -764,7 +764,7 @@ fn execute_blockchain_test( // Create EVM context for each transaction to ensure fresh state access let evm_context = Context::mainnet() .with_block(&block_env) - .with_cfg(&cfg) + .with_cfg(cfg.clone()) .with_db(&mut state); // Build and execute with EVM - always use inspector when JSON output is enabled diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 183f599c70..52e2c8efcb 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -2,10 +2,7 @@ use crate::cmd::statetest::merkle_trie::{compute_test_roots, TestValidationResul use indicatif::{ProgressBar, ProgressDrawTarget}; use revm::{ context::{block::BlockEnv, cfg::CfgEnv, tx::TxEnv}, - context_interface::{ - result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, - Cfg, - }, + context_interface::result::{EVMError, ExecutionResult, HaltReason, InvalidTransaction}, database::{self, bal::EvmDatabaseError}, database_interface::EmptyDB, inspector::{inspectors::TracerEip3155, InspectCommitEvm}, @@ -340,12 +337,12 @@ pub fn execute_test_suite( continue; } - cfg.spec = spec_name.to_spec_id(); + cfg.set_spec_and_mainnet_gas_params(spec_name.to_spec_id()); // Configure max blobs per spec - if cfg.spec.is_enabled_in(SpecId::OSAKA) { + if cfg.spec().is_enabled_in(SpecId::OSAKA) { cfg.set_max_blobs_per_tx(6); - } else if cfg.spec.is_enabled_in(SpecId::PRAGUE) { + } else if cfg.spec().is_enabled_in(SpecId::PRAGUE) { cfg.set_max_blobs_per_tx(9); } else { cfg.set_max_blobs_per_tx(6); @@ -421,7 +418,8 @@ pub fn execute_test_suite( fn execute_single_test(ctx: TestExecutionContext) -> Result<(), TestErrorKind> { // Prepare state let mut cache = ctx.cache_state.clone(); - cache.set_state_clear_flag(ctx.cfg.spec.is_enabled_in(SpecId::SPURIOUS_DRAGON)); + let spec = ctx.cfg.spec(); + cache.set_state_clear_flag(spec.is_enabled_in(SpecId::SPURIOUS_DRAGON)); let mut state = database::State::builder() .with_cached_prestate(cache) .with_bundle_update() @@ -430,7 +428,7 @@ fn execute_single_test(ctx: TestExecutionContext) -> Result<(), TestErrorKind> { let evm_context = Context::mainnet() .with_block(ctx.block) .with_tx(ctx.tx) - .with_cfg(ctx.cfg) + .with_cfg(ctx.cfg.clone()) .with_db(&mut state); // Execute @@ -457,7 +455,7 @@ fn execute_single_test(ctx: TestExecutionContext) -> Result<(), TestErrorKind> { ctx.name, &exec_result, db, - ctx.cfg.spec(), + *ctx.cfg.spec(), ctx.print_json_outcome, ) } @@ -467,7 +465,7 @@ fn debug_failed_test(ctx: DebugContext) { // Re-run with tracing let mut cache = ctx.cache_state.clone(); - cache.set_state_clear_flag(ctx.cfg.spec.is_enabled_in(SpecId::SPURIOUS_DRAGON)); + cache.set_state_clear_flag(ctx.cfg.spec().is_enabled_in(SpecId::SPURIOUS_DRAGON)); let mut state = database::State::builder() .with_cached_prestate(cache) .with_bundle_update() @@ -477,7 +475,7 @@ fn debug_failed_test(ctx: DebugContext) { .with_db(&mut state) .with_block(ctx.block) .with_tx(ctx.tx) - .with_cfg(ctx.cfg) + .with_cfg(ctx.cfg.clone()) .build_mainnet_with_inspector(TracerEip3155::buffered(stderr()).without_summary()); let exec_result = evm.inspect_tx_commit(ctx.tx); @@ -489,7 +487,7 @@ fn debug_failed_test(ctx: DebugContext) { "\nState after:\n{}", evm.ctx.journaled_state.database.cache.pretty_print() ); - println!("\nSpecification: {:?}", ctx.cfg.spec); + println!("\nSpecification: {:?}", ctx.cfg.spec()); println!("\nTx: {:#?}", ctx.tx); println!("Block: {:#?}", ctx.block); println!("Cfg: {:#?}", ctx.cfg); diff --git a/crates/context/interface/src/cfg.rs b/crates/context/interface/src/cfg.rs index 11e5d99659..cb107693d6 100644 --- a/crates/context/interface/src/cfg.rs +++ b/crates/context/interface/src/cfg.rs @@ -1,4 +1,10 @@ //! Configuration for the EVM. Containing [`SpecId`]. + +pub mod gas; +pub mod gas_params; + +pub use gas_params::{GasId, GasParams}; + use auto_impl::auto_impl; use core::{fmt::Debug, hash::Hash}; use primitives::{hardfork::SpecId, Address, TxKind, U256}; @@ -66,6 +72,9 @@ pub trait Cfg { /// Returns the limit in bytes for the memory buffer. fn memory_limit(&self) -> u64; + + /// Returns the gas params for the EVM. + fn gas_params(&self) -> &GasParams; } /// What bytecode analysis to perform diff --git a/crates/context/interface/src/cfg/gas.rs b/crates/context/interface/src/cfg/gas.rs new file mode 100644 index 0000000000..5b122b7657 --- /dev/null +++ b/crates/context/interface/src/cfg/gas.rs @@ -0,0 +1,298 @@ +//! Gas constants and functions for gas calculation. + +use crate::{transaction::AccessListItemTr as _, Transaction, TransactionType}; +use primitives::{eip7702, hardfork::SpecId, U256}; + +/// Gas cost for operations that consume zero gas. +pub const ZERO: u64 = 0; +/// Base gas cost for basic operations. +pub const BASE: u64 = 2; + +/// Gas cost for very low-cost operations. +pub const VERYLOW: u64 = 3; +/// Gas cost for DATALOADN instruction. +pub const DATA_LOADN_GAS: u64 = 3; + +/// Gas cost for conditional jump instructions. +pub const CONDITION_JUMP_GAS: u64 = 4; +/// Gas cost for RETF instruction. +pub const RETF_GAS: u64 = 3; +/// Gas cost for DATALOAD instruction. +pub const DATA_LOAD_GAS: u64 = 4; + +/// Gas cost for low-cost operations. +pub const LOW: u64 = 5; +/// Gas cost for medium-cost operations. +pub const MID: u64 = 8; +/// Gas cost for high-cost operations. +pub const HIGH: u64 = 10; +/// Gas cost for JUMPDEST instruction. +pub const JUMPDEST: u64 = 1; +/// Gas cost for REFUND SELFDESTRUCT instruction. +pub const SELFDESTRUCT_REFUND: i64 = 24000; +/// Gas cost for CREATE instruction. +pub const CREATE: u64 = 32000; +/// Additional gas cost when a call transfers value. +pub const CALLVALUE: u64 = 9000; +/// Gas cost for creating a new account. +pub const NEWACCOUNT: u64 = 25000; +/// Base gas cost for EXP instruction. +pub const EXP: u64 = 10; +/// Gas cost per word for memory operations. +pub const MEMORY: u64 = 3; +/// Base gas cost for LOG instructions. +pub const LOG: u64 = 375; +/// Gas cost per byte of data in LOG instructions. +pub const LOGDATA: u64 = 8; +/// Gas cost per topic in LOG instructions. +pub const LOGTOPIC: u64 = 375; +/// Base gas cost for KECCAK256 instruction. +pub const KECCAK256: u64 = 30; +/// Gas cost per word for KECCAK256 instruction. +pub const KECCAK256WORD: u64 = 6; +/// Gas cost per word for copy operations. +pub const COPY: u64 = 3; +/// Gas cost for BLOCKHASH instruction. +pub const BLOCKHASH: u64 = 20; +/// Gas cost per byte for code deposit during contract creation. +pub const CODEDEPOSIT: u64 = 200; + +/// EIP-1884: Repricing for trie-size-dependent opcodes +pub const ISTANBUL_SLOAD_GAS: u64 = 800; +/// Gas cost for SSTORE when setting a storage slot from zero to non-zero. +pub const SSTORE_SET: u64 = 20000; +/// Gas cost for SSTORE when modifying an existing non-zero storage slot. +pub const SSTORE_RESET: u64 = 5000; +/// Gas refund for SSTORE when clearing a storage slot (setting to zero). +pub const REFUND_SSTORE_CLEARS: i64 = 15000; + +/// The standard cost of calldata token. +pub const STANDARD_TOKEN_COST: u64 = 4; +/// The cost of a non-zero byte in calldata. +pub const NON_ZERO_BYTE_DATA_COST: u64 = 68; +/// The multiplier for a non zero byte in calldata. +pub const NON_ZERO_BYTE_MULTIPLIER: u64 = NON_ZERO_BYTE_DATA_COST / STANDARD_TOKEN_COST; +/// The cost of a non-zero byte in calldata adjusted by [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028). +pub const NON_ZERO_BYTE_DATA_COST_ISTANBUL: u64 = 16; +/// The multiplier for a non zero byte in calldata adjusted by [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028). +pub const NON_ZERO_BYTE_MULTIPLIER_ISTANBUL: u64 = + NON_ZERO_BYTE_DATA_COST_ISTANBUL / STANDARD_TOKEN_COST; +/// The cost floor per token as defined by EIP-2028. +pub const TOTAL_COST_FLOOR_PER_TOKEN: u64 = 10; + +/// Gas cost for EOF CREATE instruction. +pub const EOF_CREATE_GAS: u64 = 32000; + +// Berlin EIP-2929/EIP-2930 constants +/// Gas cost for accessing an address in the access list (EIP-2930). +pub const ACCESS_LIST_ADDRESS: u64 = 2400; +/// Gas cost for accessing a storage key in the access list (EIP-2930). +pub const ACCESS_LIST_STORAGE_KEY: u64 = 1900; + +/// Gas cost for SLOAD when accessing a cold storage slot (EIP-2929). +pub const COLD_SLOAD_COST: u64 = 2100; +/// Gas cost for accessing a cold account (EIP-2929). +pub const COLD_ACCOUNT_ACCESS_COST: u64 = 2600; +/// Additional gas cost for accessing a cold account. +pub const COLD_ACCOUNT_ACCESS_COST_ADDITIONAL: u64 = + COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST; +/// Gas cost for reading from a warm storage slot (EIP-2929). +pub const WARM_STORAGE_READ_COST: u64 = 100; +/// Gas cost for SSTORE reset operation on a warm storage slot. +pub const WARM_SSTORE_RESET: u64 = SSTORE_RESET - COLD_SLOAD_COST; + +/// EIP-3860 : Limit and meter initcode +pub const INITCODE_WORD_COST: u64 = 2; + +/// Gas stipend provided to the recipient of a CALL with value transfer. +pub const CALL_STIPEND: u64 = 2300; + +#[inline] +pub(crate) const fn log2floor(value: U256) -> u64 { + let mut l: u64 = 256; + let mut i = 3; + loop { + if value.as_limbs()[i] == 0u64 { + l -= 64; + } else { + l -= value.as_limbs()[i].leading_zeros() as u64; + if l == 0 { + return l; + } else { + return l - 1; + } + } + if i == 0 { + break; + } + i -= 1; + } + l +} + +/// Calculate the cost of buffer per word. +#[inline] +pub const fn cost_per_word(len: usize, multiple: u64) -> Option { + multiple.checked_mul(num_words(len) as u64) +} + +/// EIP-3860: Limit and meter initcode +/// +/// Apply extra gas cost of 2 for every 32-byte chunk of initcode. +/// +/// This cannot overflow as the initcode length is assumed to be checked. +#[inline] +pub const fn initcode_cost(len: usize) -> u64 { + let Some(cost) = cost_per_word(len, INITCODE_WORD_COST) else { + panic!("initcode cost overflow") + }; + cost +} + +/// Memory expansion cost calculation for a given number of words. +#[inline] +pub const fn memory_gas(num_words: usize, linear_cost: u64, quadratic_cost: u64) -> u64 { + let num_words = num_words as u64; + linear_cost + .saturating_mul(num_words) + .saturating_add(num_words.saturating_mul(num_words) / quadratic_cost) +} + +/// Init and floor gas from transaction +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct InitialAndFloorGas { + /// Initial gas for transaction. + pub initial_gas: u64, + /// If transaction is a Call and Prague is enabled + /// floor_gas is at least amount of gas that is going to be spent. + pub floor_gas: u64, +} + +impl InitialAndFloorGas { + /// Create a new InitialAndFloorGas instance. + #[inline] + pub const fn new(initial_gas: u64, floor_gas: u64) -> Self { + Self { + initial_gas, + floor_gas, + } + } +} + +/// Initial gas that is deducted for transaction to be included. +/// Initial gas contains initial stipend gas, gas for access list and input data. +/// +/// # Returns +/// +/// - Intrinsic gas +/// - Number of tokens in calldata +pub fn calculate_initial_tx_gas( + spec_id: SpecId, + input: &[u8], + is_create: bool, + access_list_accounts: u64, + access_list_storages: u64, + authorization_list_num: u64, +) -> InitialAndFloorGas { + let mut gas = InitialAndFloorGas::default(); + + // Initdate stipend + let tokens_in_calldata = get_tokens_in_calldata(input, spec_id.is_enabled_in(SpecId::ISTANBUL)); + + gas.initial_gas += tokens_in_calldata * STANDARD_TOKEN_COST; + + // Get number of access list account and storages. + gas.initial_gas += access_list_accounts * ACCESS_LIST_ADDRESS; + gas.initial_gas += access_list_storages * ACCESS_LIST_STORAGE_KEY; + + // Base stipend + gas.initial_gas += if is_create { + if spec_id.is_enabled_in(SpecId::HOMESTEAD) { + // EIP-2: Homestead Hard-fork Changes + 53000 + } else { + 21000 + } + } else { + 21000 + }; + + // EIP-3860: Limit and meter initcode + // Init code stipend for bytecode analysis + if spec_id.is_enabled_in(SpecId::SHANGHAI) && is_create { + gas.initial_gas += initcode_cost(input.len()) + } + + // EIP-7702 + if spec_id.is_enabled_in(SpecId::PRAGUE) { + gas.initial_gas += authorization_list_num * eip7702::PER_EMPTY_ACCOUNT_COST; + + // Calculate gas floor for EIP-7623 + gas.floor_gas = calc_tx_floor_cost(tokens_in_calldata); + } + + gas +} + +/// Initial gas that is deducted for transaction to be included. +/// Initial gas contains initial stipend gas, gas for access list and input data. +/// +/// # Returns +/// +/// - Intrinsic gas +/// - Number of tokens in calldata +pub fn calculate_initial_tx_gas_for_tx(tx: impl Transaction, spec: SpecId) -> InitialAndFloorGas { + let mut accounts = 0; + let mut storages = 0; + // legacy is only tx type that does not have access list. + if tx.tx_type() != TransactionType::Legacy { + (accounts, storages) = tx + .access_list() + .map(|al| { + al.fold((0, 0), |(mut num_accounts, mut num_storage_slots), item| { + num_accounts += 1; + num_storage_slots += item.storage_slots().count(); + + (num_accounts, num_storage_slots) + }) + }) + .unwrap_or_default(); + } + + calculate_initial_tx_gas( + spec, + tx.input(), + tx.kind().is_create(), + accounts as u64, + storages as u64, + tx.authorization_list_len() as u64, + ) +} + +/// Retrieve the total number of tokens in calldata. +#[inline] +pub fn get_tokens_in_calldata(input: &[u8], is_istanbul: bool) -> u64 { + let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; + let non_zero_data_len = input.len() as u64 - zero_data_len; + let non_zero_data_multiplier = if is_istanbul { + // EIP-2028: Transaction data gas cost reduction + NON_ZERO_BYTE_MULTIPLIER_ISTANBUL + } else { + NON_ZERO_BYTE_MULTIPLIER + }; + zero_data_len + non_zero_data_len * non_zero_data_multiplier +} + +/// Calculate the transaction cost floor as specified in EIP-7623. +#[inline] +pub fn calc_tx_floor_cost(tokens_in_calldata: u64) -> u64 { + tokens_in_calldata * TOTAL_COST_FLOOR_PER_TOKEN + 21_000 +} + +/// Returns number of words what would fit to provided number of bytes, +/// i.e. it rounds up the number bytes to number of words. +#[inline] +pub const fn num_words(len: usize) -> usize { + len.div_ceil(32) +} diff --git a/crates/interpreter/src/gas/params.rs b/crates/context/interface/src/cfg/gas_params.rs similarity index 96% rename from crates/interpreter/src/gas/params.rs rename to crates/context/interface/src/cfg/gas_params.rs index 93bd8c9a80..68e195eb49 100644 --- a/crates/interpreter/src/gas/params.rs +++ b/crates/context/interface/src/cfg/gas_params.rs @@ -1,10 +1,12 @@ //! Gas table for dynamic gas constants. use crate::{ - gas::{self, log2floor, ISTANBUL_SLOAD_GAS, SSTORE_RESET, SSTORE_SET, WARM_SSTORE_RESET}, - num_words, + cfg::gas::{ + self, log2floor, num_words, ISTANBUL_SLOAD_GAS, SSTORE_RESET, SSTORE_SET, WARM_SSTORE_RESET, + }, + context::SStoreResult, }; -use context_interface::context::SStoreResult; +use core::hash::{Hash, Hasher}; use primitives::{ hardfork::SpecId::{self}, U256, @@ -12,7 +14,7 @@ use primitives::{ use std::sync::Arc; /// Gas table for dynamic gas constants. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] +#[derive(Clone)] pub struct GasParams { /// Table of gas costs for operations table: Arc<[u64; 256]>, @@ -20,6 +22,30 @@ pub struct GasParams { ptr: *const u64, } +impl PartialEq for GasParams { + fn eq(&self, other: &GasParams) -> bool { + self.table == other.table + } +} + +impl Hash for GasParams { + fn hash(&self, hasher: &mut H) { + self.table.hash(hasher); + } +} + +/// Pointer points to Arc so it is safe to send across threads +unsafe impl Send for GasParams {} +/// Pointer points to Arc so it is safe to access +unsafe impl Sync for GasParams {} + +impl core::fmt::Debug for GasParams { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "GasParams {{ table: {:?} }}", self.table) + } +} + +impl Eq for GasParams {} #[cfg(feature = "serde")] mod serde { use super::{Arc, GasParams}; @@ -80,7 +106,7 @@ impl GasParams { /// Use to override default gas cost /// /// ```rust - /// use revm_interpreter::gas::params::{GasParams, GasId}; + /// use revm_context_interface::cfg::gas_params::{GasParams, GasId}; /// use primitives::hardfork::SpecId; /// /// let mut gas_table = GasParams::new_spec(SpecId::default()); @@ -509,7 +535,7 @@ impl GasId { /// # Examples /// /// ``` - /// use revm_interpreter::gas::params::GasId; + /// use revm_context_interface::cfg::gas_params::GasId; /// /// assert_eq!(GasId::exp_byte_gas().name(), "exp_byte_gas"); /// assert_eq!(GasId::memory_linear_cost().name(), "memory_linear_cost"); @@ -563,7 +589,7 @@ impl GasId { /// # Examples /// /// ``` - /// use revm_interpreter::gas::params::GasId; + /// use revm_context_interface::cfg::gas_params::GasId; /// /// assert_eq!(GasId::from_name("exp_byte_gas"), Some(GasId::exp_byte_gas())); /// assert_eq!(GasId::from_name("memory_linear_cost"), Some(GasId::memory_linear_cost())); diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index 833346696a..e4efb22081 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -1,11 +1,12 @@ //! Host interface for external blockchain state access. use crate::{ + cfg::GasParams, context::{SStoreResult, SelfDestructResult, StateLoad}, journaled_state::{AccountInfoLoad, AccountLoad}, }; use auto_impl::auto_impl; -use primitives::{Address, Bytes, Log, StorageKey, StorageValue, B256, U256}; +use primitives::{hardfork::SpecId, Address, Bytes, Log, StorageKey, StorageValue, B256, U256}; use state::Bytecode; /// Error that can happen when loading account info. @@ -60,6 +61,9 @@ pub trait Host { /// Max initcode size, calls `ContextTr::cfg().max_code_size().saturating_mul(2)` fn max_initcode_size(&self) -> usize; + /// Gas params contains the dynamic gas constants for the EVM. + fn gas_params(&self) -> &GasParams; + /* Database */ /// Block hash, calls `ContextTr::journal_mut().db().block_hash(number)` @@ -200,8 +204,19 @@ pub trait Host { } /// Dummy host that implements [`Host`] trait and returns all default values. -#[derive(Debug)] -pub struct DummyHost; +#[derive(Default, Debug)] +pub struct DummyHost { + gas_params: GasParams, +} + +impl DummyHost { + /// Create a new dummy host with the given spec. + pub fn new(spec: SpecId) -> Self { + Self { + gas_params: GasParams::new_spec(spec), + } + } +} impl Host for DummyHost { fn basefee(&self) -> U256 { @@ -216,6 +231,10 @@ impl Host for DummyHost { U256::ZERO } + fn gas_params(&self) -> &GasParams { + &self.gas_params + } + fn difficulty(&self) -> U256 { U256::ZERO } diff --git a/crates/context/interface/src/journaled_state/account.rs b/crates/context/interface/src/journaled_state/account.rs index ae5691f7a0..ecba313060 100644 --- a/crates/context/interface/src/journaled_state/account.rs +++ b/crates/context/interface/src/journaled_state/account.rs @@ -173,9 +173,18 @@ impl<'a, DB: Database, ENTRY: JournalEntryTr> JournaledAccount<'a, DB, ENTRY> { Entry::Occupied(occ) => { let slot = occ.into_mut(); // skip load if account is cold. - let is_cold = slot.is_cold_transaction_id(self.transaction_id); - if is_cold && skip_cold_load { - return Err(JournalLoadError::ColdLoadSkipped); + let mut is_cold = false; + if slot.is_cold_transaction_id(self.transaction_id) { + // is storage cold + is_cold = self + .access_list + .get(&self.address) + .and_then(|v| v.get(&key)) + .is_none(); + + if is_cold && skip_cold_load { + return Err(JournalLoadError::ColdLoadSkipped); + } } slot.mark_warm_with_transaction_id(self.transaction_id); (slot, is_cold) diff --git a/crates/context/src/cfg.rs b/crates/context/src/cfg.rs index 2aea1efcf6..5a320ea660 100644 --- a/crates/context/src/cfg.rs +++ b/crates/context/src/cfg.rs @@ -1,12 +1,26 @@ //! This module contains [`CfgEnv`] and implements [`Cfg`] trait for it. pub use context_interface::Cfg; +use context_interface::cfg::GasParams; use primitives::{eip170, eip3860, eip7825, hardfork::SpecId}; + /// EVM configuration #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct CfgEnv { + /// Specification for EVM represent the hardfork + /// + /// [`CfgEnv::new_with_spec`] is going to set both gas params and spec. + /// + /// As GasParams is spec dependent, it is recommended to use one of following function to set both of them. + /// [`CfgEnv::set_spec_and_mainnet_gas_params`], [`CfgEnv::with_mainnet_gas_params`], [`CfgEnv::with_mainnet_gas_params`] + pub spec: SPEC, + + /// Gas params for the EVM. Use [`CfgEnv::set_gas_params`] to set the gas params. + /// If gas_params was not set it will be set to the default gas params for the spec. + pub gas_params: GasParams, + /// Chain ID of the EVM. Used in CHAINID opcode and transaction's chain ID check. /// /// Chain ID is introduced EIP-155. @@ -17,8 +31,6 @@ pub struct CfgEnv { /// If set to `false`, the transaction's chain ID check will be skipped. pub tx_chain_id_check: bool, - /// Specification for EVM represent the hardfork - pub spec: SPEC, /// Contract code size limit override. /// /// If None, the limit will be determined by the SpecId (EIP-170 or EIP-7907) at runtime. @@ -127,28 +139,9 @@ impl CfgEnv { } } -impl + Copy> CfgEnv { - /// Returns the blob base fee update fraction from [CfgEnv::blob_base_fee_update_fraction]. - /// - /// If this field is not set, return the default value for the spec. - /// - /// Default values for Cancun is [`primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN`] - /// and for Prague is [`primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE`]. - pub fn blob_base_fee_update_fraction(&mut self) -> u64 { - self.blob_base_fee_update_fraction.unwrap_or_else(|| { - let spec: SpecId = self.spec.into(); - if spec.is_enabled_in(SpecId::PRAGUE) { - primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE - } else { - primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN - } - }) - } -} - impl CfgEnv { /// Create new `CfgEnv` with default values and specified spec. - pub fn new_with_spec(spec: SPEC) -> Self { + pub fn new_with_spec_and_gas_params(spec: SPEC, gas_params: GasParams) -> Self { Self { chain_id: 1, tx_chain_id_check: true, @@ -159,6 +152,7 @@ impl CfgEnv { max_blobs_per_tx: None, tx_gas_limit_cap: None, blob_base_fee_update_fraction: None, + gas_params, #[cfg(feature = "memory_limit")] memory_limit: (1 << 32) - 1, #[cfg(feature = "optional_balance_check")] @@ -180,12 +174,37 @@ impl CfgEnv { } } + /// Returns the spec for the `CfgEnv`. + #[inline] + pub fn spec(&self) -> &SPEC { + &self.spec + } + /// Consumes `self` and returns a new `CfgEnv` with the specified chain ID. pub fn with_chain_id(mut self, chain_id: u64) -> Self { self.chain_id = chain_id; self } + /// Sets the gas params for the `CfgEnv`. + #[inline] + pub fn with_gas_params(mut self, gas_params: GasParams) -> Self { + self.set_gas_params(gas_params); + self + } + + /// Sets the spec for the `CfgEnv`. + #[inline] + pub fn set_spec(&mut self, spec: SPEC) { + self.spec = spec; + } + + /// Sets the gas params for the `CfgEnv`. + #[inline] + pub fn set_gas_params(&mut self, gas_params: GasParams) { + self.gas_params = gas_params; + } + /// Enables the transaction's chain ID check. pub fn enable_tx_chain_id_check(mut self) -> Self { self.tx_chain_id_check = true; @@ -198,8 +217,33 @@ impl CfgEnv { self } + /// Sets the spec for the `CfgEnv`. + #[inline] + #[deprecated( + since = "0.1.0", + note = "Use [`CfgEnv::with_spec_and_mainnet_gas_params`] instead" + )] + pub fn with_spec(mut self, spec: SPEC) -> Self { + self.spec = spec; + self + } + + /// Sets the spec for the `CfgEnv` and the gas params to the mainnet gas params. + pub fn with_spec_and_mainnet_gas_params + Clone>( + self, + spec: OSPEC, + ) -> CfgEnv { + self.with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into())) + } + /// Consumes `self` and returns a new `CfgEnv` with the specified spec. - pub fn with_spec>(self, spec: OSPEC) -> CfgEnv { + /// + /// Resets the gas params override function as it is generic over SPEC. + pub fn with_spec_and_gas_params + Clone>( + self, + spec: OSPEC, + gas_params: GasParams, + ) -> CfgEnv { CfgEnv { chain_id: self.chain_id, tx_chain_id_check: self.tx_chain_id_check, @@ -210,6 +254,7 @@ impl CfgEnv { tx_gas_limit_cap: self.tx_gas_limit_cap, max_blobs_per_tx: self.max_blobs_per_tx, blob_base_fee_update_fraction: self.blob_base_fee_update_fraction, + gas_params, #[cfg(feature = "memory_limit")] memory_limit: self.memory_limit, #[cfg(feature = "optional_balance_check")] @@ -269,7 +314,49 @@ impl CfgEnv { } } -impl + Copy> Cfg for CfgEnv { +impl + Clone> CfgEnv { + /// Returns the blob base fee update fraction from [CfgEnv::blob_base_fee_update_fraction]. + /// + /// If this field is not set, return the default value for the spec. + /// + /// Default values for Cancun is [`primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN`] + /// and for Prague is [`primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE`]. + pub fn blob_base_fee_update_fraction(&mut self) -> u64 { + self.blob_base_fee_update_fraction.unwrap_or_else(|| { + let spec: SpecId = self.spec.clone().into(); + if spec.is_enabled_in(SpecId::PRAGUE) { + primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_PRAGUE + } else { + primitives::eip4844::BLOB_BASE_FEE_UPDATE_FRACTION_CANCUN + } + }) + } + + /// Create new `CfgEnv` with default values and specified spec. + /// It will create a new gas params based on mainnet spec. + /// + /// Internally it will call [`CfgEnv::new_with_spec_and_gas_params`] with the mainnet gas params. + pub fn new_with_spec(spec: SPEC) -> Self { + Self::new_with_spec_and_gas_params(spec.clone(), GasParams::new_spec(spec.into())) + } + + /// Sets the gas params for the `CfgEnv` to the mainnet gas params. + /// + /// If spec gets changed, calling this function would use this spec to set the mainnetF gas params. + pub fn with_mainnet_gas_params(mut self) -> Self { + self.set_gas_params(GasParams::new_spec(self.spec.clone().into())); + self + } + + /// Sets the spec for the `CfgEnv` and the gas params to the mainnet gas params. + #[inline] + pub fn set_spec_and_mainnet_gas_params(&mut self, spec: SPEC) { + self.set_spec(spec.clone()); + self.set_gas_params(GasParams::new_spec(spec.into())); + } +} + +impl + Clone> Cfg for CfgEnv { type Spec = SPEC; #[inline] @@ -279,7 +366,7 @@ impl + Copy> Cfg for CfgEnv { #[inline] fn spec(&self) -> Self::Spec { - self.spec + self.spec.clone() } #[inline] @@ -290,7 +377,7 @@ impl + Copy> Cfg for CfgEnv { #[inline] fn tx_gas_limit_cap(&self) -> u64 { self.tx_gas_limit_cap - .unwrap_or(if self.spec.into().is_enabled_in(SpecId::OSAKA) { + .unwrap_or(if self.spec.clone().into().is_enabled_in(SpecId::OSAKA) { eip7825::TX_GAS_LIMIT_CAP } else { u64::MAX @@ -410,11 +497,19 @@ impl + Copy> Cfg for CfgEnv { } } } + + #[inline] + fn gas_params(&self) -> &GasParams { + &self.gas_params + } } -impl Default for CfgEnv { +impl> Default for CfgEnv { fn default() -> Self { - Self::new_with_spec(SPEC::default()) + Self::new_with_spec_and_gas_params( + SPEC::default(), + GasParams::new_spec(SPEC::default().into()), + ) } } diff --git a/crates/context/src/context.rs b/crates/context/src/context.rs index 5bf1832fa3..de226f3342 100644 --- a/crates/context/src/context.rs +++ b/crates/context/src/context.rs @@ -1,6 +1,7 @@ //! This module contains [`Context`] struct and implements [`ContextTr`] trait for it. use crate::{block::BlockEnv, cfg::CfgEnv, journal::Journal, tx::TxEnv, LocalContext}; use context_interface::{ + cfg::GasParams, context::{ContextError, ContextSetters, SStoreResult, SelfDestructResult, StateLoad}, host::LoadError, journaled_state::AccountInfoLoad, @@ -133,7 +134,7 @@ impl< JOURNAL: JournalTr, CHAIN: Default, LOCAL: LocalContextTr + Default, - SPEC: Default + Copy + Into, + SPEC: Default + Into + Clone, > Context, DB, JOURNAL, CHAIN, LOCAL> { /// Creates a new context with a new database type. @@ -141,14 +142,11 @@ impl< /// This will create a new [`Journal`] object. pub fn new(db: DB, spec: SPEC) -> Self { let mut journaled_state = JOURNAL::new(db); - journaled_state.set_spec_id(spec.into()); + journaled_state.set_spec_id(spec.clone().into()); Self { tx: TX::default(), block: BLOCK::default(), - cfg: CfgEnv { - spec, - ..Default::default() - }, + cfg: CfgEnv::new_with_spec(spec), local: LOCAL::default(), journaled_state, chain: Default::default(), @@ -452,6 +450,11 @@ impl< self.block().prevrandao().map(|r| r.into()) } + #[inline] + fn gas_params(&self) -> &GasParams { + self.cfg().gas_params() + } + fn block_number(&self) -> U256 { self.block().number() } diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index 1e44ad1f67..525a199a8a 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -51,7 +51,7 @@ fn test_deposit_tx() { .source_hash(revm::primitives::B256::from([1u8; 32])) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::HOLOCENE); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::HOLOCENE)); let mut evm = ctx.build_op(); @@ -83,7 +83,7 @@ fn test_halted_deposit_tx() { .source_hash(revm::primitives::B256::from([1u8; 32])) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::HOLOCENE) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::HOLOCENE)) .with_db(BenchmarkDB::new_bytecode(Bytecode::new_legacy( [opcode::POP].into(), ))); @@ -127,7 +127,7 @@ fn p256verify_test_tx( ) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID) + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)) } #[test] @@ -160,7 +160,7 @@ fn test_halted_tx_call_p256verify() { ) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -196,7 +196,7 @@ fn bn254_pair_test_tx( ) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = spec) + .with_cfg(CfgEnv::new_with_spec(spec)) } #[test] @@ -253,7 +253,7 @@ fn test_halted_tx_call_bls12_381_g1_add_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); @@ -290,7 +290,7 @@ fn test_halted_tx_call_bls12_381_g1_add_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -339,7 +339,7 @@ fn g1_msm_test_tx( l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID) + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)) } #[test] @@ -369,7 +369,7 @@ fn test_halted_tx_call_bls12_381_g1_msm_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -416,7 +416,7 @@ fn test_halted_tx_call_bls12_381_g1_msm_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -474,7 +474,7 @@ fn test_halted_tx_call_bls12_381_g2_add_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); @@ -511,7 +511,7 @@ fn test_halted_tx_call_bls12_381_g2_add_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); @@ -561,7 +561,7 @@ fn g2_msm_test_tx( l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID) + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)) } #[test] @@ -591,7 +591,7 @@ fn test_halted_tx_call_bls12_381_g2_msm_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -638,7 +638,7 @@ fn test_halted_tx_call_bls12_381_g2_msm_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -707,7 +707,7 @@ fn bl12_381_pairing_test_tx( l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)) } #[test] @@ -734,7 +734,7 @@ fn test_halted_tx_call_bls12_381_pairing_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -778,7 +778,7 @@ fn test_halted_tx_call_bls12_381_pairing_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -842,7 +842,7 @@ fn test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -884,7 +884,7 @@ fn test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -926,7 +926,7 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -967,7 +967,7 @@ fn test_l1block_load_for_pre_regolith() { .modify_chain_chained(|l1_block| { l1_block.l2_block = None; }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx .with_db( @@ -1006,7 +1006,7 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size() { l1_block.operator_fee_constant = Some(U256::ZERO); l1_block.operator_fee_scalar = Some(U256::ZERO) }) - .modify_cfg_chained(|cfg| cfg.spec = SPEC_ID); + .with_cfg(CfgEnv::new_with_spec(SPEC_ID)); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); diff --git a/crates/ee-tests/src/revm_tests.rs b/crates/ee-tests/src/revm_tests.rs index b89459ebfc..fc66a77dfe 100644 --- a/crates/ee-tests/src/revm_tests.rs +++ b/crates/ee-tests/src/revm_tests.rs @@ -3,7 +3,7 @@ use crate::TestdataConfig; use revm::{ bytecode::opcode, - context::{ContextTr, TxEnv}, + context::{CfgEnv, ContextTr, TxEnv}, database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}, primitives::{address, b256, hardfork::SpecId, Bytes, TxKind, KECCAK_EMPTY, U256}, state::{AccountStatus, Bytecode}, @@ -38,7 +38,7 @@ const SELFDESTRUCT_BYTECODE: &[u8] = &[ #[test] fn test_selfdestruct_multi_tx() { let mut evm = Context::mainnet() - .modify_cfg_chained(|cfg| cfg.spec = SpecId::BERLIN) + .with_cfg(CfgEnv::new_with_spec(SpecId::BERLIN)) .with_db(BenchmarkDB::new_bytecode(Bytecode::new_legacy( SELFDESTRUCT_BYTECODE.into(), ))) @@ -85,7 +85,7 @@ fn test_selfdestruct_multi_tx() { fn test_multi_tx_create() { let mut evm = Context::mainnet() .modify_cfg_chained(|cfg| { - cfg.spec = SpecId::BERLIN; + cfg.set_spec_and_mainnet_gas_params(SpecId::BERLIN); cfg.disable_nonce_check = true; }) .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) @@ -217,7 +217,7 @@ fn deployment_contract(bytes: &[u8]) -> Bytes { #[test] fn test_frame_stack_index() { let mut evm = Context::mainnet() - .modify_cfg_chained(|cfg| cfg.spec = SpecId::BERLIN) + .with_cfg(CfgEnv::new_with_spec(SpecId::BERLIN)) .with_db(BenchmarkDB::new_bytecode(Bytecode::new_legacy( SELFDESTRUCT_BYTECODE.into(), ))) diff --git a/crates/handler/src/evm.rs b/crates/handler/src/evm.rs index 8607f48dce..0ad3130f0c 100644 --- a/crates/handler/src/evm.rs +++ b/crates/handler/src/evm.rs @@ -183,13 +183,7 @@ where let ctx = &mut self.ctx; let precompiles = &mut self.precompiles; - let res = Self::Frame::init_with_context( - new_frame, - ctx, - precompiles, - frame_input, - self.instruction.gas_params(), - )?; + let res = Self::Frame::init_with_context(new_frame, ctx, precompiles, frame_input)?; Ok(res.map_frame(|token| { if is_first_init { diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 479e4093c1..2b3ced2c1b 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -4,6 +4,7 @@ use crate::{ }; use context::result::FromStringError; use context_interface::{ + cfg::gas::CODEDEPOSIT, context::ContextError, journaled_state::{account::JournaledAccountTr, JournalCheckpoint, JournalTr}, local::{FrameToken, OutFrame}, @@ -12,7 +13,6 @@ use context_interface::{ use core::cmp::min; use derive_where::derive_where; use interpreter::{ - gas::{self, params::GasParams}, interpreter::{EthInterpreter, ExtBytecode}, interpreter_action::FrameInit, interpreter_types::ReturnData, @@ -114,7 +114,6 @@ impl EthFrame { spec_id: SpecId, gas_limit: u64, checkpoint: JournalCheckpoint, - gas_params: GasParams, ) { let Self { data: data_ref, @@ -128,9 +127,7 @@ impl EthFrame { *input_ref = input; *depth_ref = depth; *is_finished_ref = false; - interpreter.clear( - memory, bytecode, inputs, is_static, spec_id, gas_limit, gas_params, - ); + interpreter.clear(memory, bytecode, inputs, is_static, spec_id, gas_limit); *checkpoint_ref = checkpoint; } @@ -147,7 +144,6 @@ impl EthFrame { depth: usize, memory: SharedMemory, inputs: Box, - gas_params: GasParams, ) -> Result, ERROR> { let gas = Gas::new(inputs.gas_limit); let return_result = |instruction_result: InstructionResult| { @@ -247,7 +243,6 @@ impl EthFrame { ctx.cfg().spec().into(), gas_limit, checkpoint, - gas_params, ); Ok(ItemOrResult::Item(this.consume())) } @@ -263,7 +258,6 @@ impl EthFrame { depth: usize, memory: SharedMemory, inputs: Box, - gas_params: GasParams, ) -> Result, ERROR> { let spec = context.cfg().spec().into(); let return_error = |e| { @@ -350,7 +344,6 @@ impl EthFrame { spec, gas_limit, checkpoint, - gas_params, ); Ok(ItemOrResult::Item(this.consume())) } @@ -364,7 +357,6 @@ impl EthFrame { ctx: &mut CTX, precompiles: &mut PRECOMPILES, frame_init: FrameInit, - gas_params: GasParams, ) -> Result< ItemOrResult, ContextError<<::Db as Database>::Error>, @@ -378,11 +370,9 @@ impl EthFrame { match frame_input { FrameInput::Call(inputs) => { - Self::make_call_frame(this, ctx, precompiles, depth, memory, inputs, gas_params) - } - FrameInput::Create(inputs) => { - Self::make_create_frame(this, ctx, depth, memory, inputs, gas_params) + Self::make_call_frame(this, ctx, precompiles, depth, memory, inputs) } + FrameInput::Create(inputs) => Self::make_create_frame(this, ctx, depth, memory, inputs), FrameInput::Empty => unreachable!(), } } @@ -579,7 +569,7 @@ pub fn return_create( interpreter_result.result = InstructionResult::CreateContractSizeLimit; return; } - let gas_for_code = interpreter_result.output.len() as u64 * gas::CODEDEPOSIT; + let gas_for_code = interpreter_result.output.len() as u64 * CODEDEPOSIT; if !interpreter_result.gas.record_cost(gas_for_code) { // Record code deposit gas cost and check if we are out of gas. // EIP-2 point 3: If contract creation does not have enough gas to pay for the diff --git a/crates/handler/src/handler.rs b/crates/handler/src/handler.rs index 96b1911345..6530e1e64d 100644 --- a/crates/handler/src/handler.rs +++ b/crates/handler/src/handler.rs @@ -1,4 +1,3 @@ -use crate::instructions::InstructionProvider; use crate::{ evm::FrameTr, execution, post_execution, @@ -99,7 +98,6 @@ pub trait Handler { &mut self, evm: &mut Self::Evm, ) -> Result, Self::Error> { - self.configure(evm); // Run inner handler and catch all errors to handle cleanup. match self.run_without_catch_error(evm) { Ok(output) => Ok(output), @@ -107,15 +105,6 @@ pub trait Handler { } } - /// Configure the handler: - /// * Set Instruction gas table to the spec id. - #[inline] - fn configure(&mut self, evm: &mut Self::Evm) { - let spec_id = evm.ctx().cfg().spec().into(); - // sets static gas depending on the spec id. - evm.ctx_instructions().1.set_spec(spec_id); - } - /// Runs the system call. /// /// System call is a special transaction where caller is a [`crate::SYSTEM_ADDRESS`] @@ -137,8 +126,6 @@ pub trait Handler { ) -> Result, Self::Error> { // dummy values that are not used. let init_and_floor_gas = InitialAndFloorGas::new(0, 0); - // configure the evm for system call. - self.configure(evm); // call execution and than output. match self .execution(evm, &init_and_floor_gas) diff --git a/crates/handler/src/instructions.rs b/crates/handler/src/instructions.rs index ebe5a2d319..89bcf663c0 100644 --- a/crates/handler/src/instructions.rs +++ b/crates/handler/src/instructions.rs @@ -1,6 +1,5 @@ use auto_impl::auto_impl; use interpreter::{ - gas::params::GasParams, instructions::{instruction_table_gas_changes_spec, InstructionTable}, Host, Instruction, InterpreterTypes, }; @@ -17,12 +16,6 @@ pub trait InstructionProvider { /// Returns the instruction table that is used by EvmTr to execute instructions. fn instruction_table(&self) -> &InstructionTable; - - /// Returns the gas params that is used by EvmTr to execute instructions. - fn gas_params(&self) -> GasParams; - - /// Sets the spec. Return true if the spec was changed. - fn set_spec(&mut self, spec: SpecId) -> bool; } /// Ethereum instruction contains list of mainnet instructions that is used for Interpreter execution. @@ -30,8 +23,6 @@ pub trait InstructionProvider { pub struct EthInstructions { /// Table containing instruction implementations indexed by opcode. pub instruction_table: Box>, - /// Gas params that sets gas costs for instructions. - pub gas_params: GasParams, /// Spec that is used to set gas costs for instructions. pub spec: SpecId, } @@ -43,7 +34,6 @@ where fn clone(&self) -> Self { Self { instruction_table: self.instruction_table.clone(), - gas_params: self.gas_params.clone(), spec: self.spec, } } @@ -57,23 +47,19 @@ where /// Returns `EthInstructions` with mainnet spec. pub fn new_mainnet() -> Self { let spec = SpecId::default(); - Self::new( - instruction_table_gas_changes_spec(spec), - GasParams::new_spec(spec), - spec, - ) + Self::new(instruction_table_gas_changes_spec(spec), spec) + } + + /// Returns `EthInstructions` with mainnet spec. + pub fn new_mainnet_with_spec(spec: SpecId) -> Self { + Self::new(instruction_table_gas_changes_spec(spec), spec) } /// Returns a new instance of `EthInstructions` with custom instruction table. #[inline] - pub fn new( - base_table: InstructionTable, - gas_params: GasParams, - spec: SpecId, - ) -> Self { + pub fn new(base_table: InstructionTable, spec: SpecId) -> Self { Self { instruction_table: Box::new(base_table), - gas_params, spec, } } @@ -96,20 +82,6 @@ where fn instruction_table(&self) -> &InstructionTable { &self.instruction_table } - - fn gas_params(&self) -> GasParams { - self.gas_params.clone() - } - - fn set_spec(&mut self, spec: SpecId) -> bool { - if spec == self.spec { - return false; - } - *self.instruction_table = instruction_table_gas_changes_spec(spec); - self.gas_params = GasParams::new_spec(spec); - - true - } } impl Default for EthInstructions diff --git a/crates/handler/src/mainnet_builder.rs b/crates/handler/src/mainnet_builder.rs index a640da1aca..46baa54fc8 100644 --- a/crates/handler/src/mainnet_builder.rs +++ b/crates/handler/src/mainnet_builder.rs @@ -36,11 +36,12 @@ where type Context = Self; fn build_mainnet(self) -> MainnetEvm { + let spec = self.cfg.spec().into(); Evm { ctx: self, inspector: (), - instruction: EthInstructions::default(), - precompiles: EthPrecompiles::default(), + instruction: EthInstructions::new_mainnet_with_spec(spec), + precompiles: EthPrecompiles::new(spec), frame_stack: FrameStack::new_prealloc(8), } } @@ -49,11 +50,12 @@ where self, inspector: INSP, ) -> MainnetEvm { + let spec = self.cfg.spec().into(); Evm { ctx: self, inspector, - instruction: EthInstructions::default(), - precompiles: EthPrecompiles::default(), + instruction: EthInstructions::new_mainnet_with_spec(spec), + precompiles: EthPrecompiles::new(spec), frame_stack: FrameStack::new_prealloc(8), } } @@ -99,7 +101,7 @@ mod test { let bytecode = Bytecode::new_legacy([PUSH1, 0x01, PUSH1, 0x01, SSTORE].into()); let ctx = Context::mainnet() - .modify_cfg_chained(|cfg| cfg.spec = SpecId::PRAGUE) + .modify_cfg_chained(|cfg| cfg.set_spec_and_mainnet_gas_params(SpecId::PRAGUE)) .with_db(BenchmarkDB::new_bytecode(bytecode)); let mut evm = ctx.build_mainnet(); diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index c3ac4a3e0c..dab165140f 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -44,6 +44,14 @@ pub struct EthPrecompiles { } impl EthPrecompiles { + /// Create a new precompile provider with the given spec. + pub fn new(spec: SpecId) -> Self { + Self { + precompiles: Precompiles::new(PrecompileSpecId::from_spec_id(spec)), + spec, + } + } + /// Returns addresses of the precompiles. pub fn warm_addresses(&self) -> Box> { Box::new(self.precompiles.addresses().cloned()) diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index a05a38031d..d038cd3f87 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -275,7 +275,7 @@ mod tests { let ctx = Context::mainnet() .modify_cfg_chained(|c| { if let Some(spec_id) = spec_id { - c.spec = spec_id; + c.set_spec_and_mainnet_gas_params(spec_id); } }) .with_db(CacheDB::::default()); diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index fe43a71b46..53bdf436db 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -42,7 +42,6 @@ where &mut self, evm: &mut Self::Evm, ) -> Result, Self::Error> { - self.configure(evm); match self.inspect_run_without_catch_error(evm) { Ok(output) => Ok(output), Err(e) => self.catch_error(evm, e), @@ -137,8 +136,6 @@ where ) -> Result, Self::Error> { // dummy values that are not used. let init_and_floor_gas = InitialAndFloorGas::new(0, 0); - // configure - self.configure(evm); // call execution with inspection and then output. match self .inspect_execution(evm, &init_and_floor_gas) diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index a8ac93a37c..68dbc24103 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -1,11 +1,8 @@ //! EVM gas calculation utilities. mod calc; -mod constants; -pub mod params; pub use calc::*; -pub use constants::*; /// Represents the state of gas during execution. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] @@ -218,10 +215,19 @@ impl MemoryGas { return None; } self.words_num = new_num; - let mut cost = crate::gas::calc::memory_gas(new_num, linear_cost, quadratic_cost); + let mut cost = memory_gas(new_num, linear_cost, quadratic_cost); core::mem::swap(&mut self.expansion_cost, &mut cost); // Safe to subtract because we know that new_len > length // Notice the swap above. Some(self.expansion_cost - cost) } } + +/// Memory expansion cost calculation for a given number of words. +#[inline] +pub const fn memory_gas(num_words: usize, linear_cost: u64, quadratic_cost: u64) -> u64 { + let num_words = num_words as u64; + linear_cost + .saturating_mul(num_words) + .saturating_add(num_words.saturating_mul(num_words) / quadratic_cost) +} diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 06d9e6550d..ef4e79469b 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,30 +1,8 @@ -use super::constants::*; use crate::num_words; -use context_interface::{transaction::AccessListItemTr as _, Transaction, TransactionType}; -use primitives::{eip7702, hardfork::SpecId, U256}; - -#[inline] -pub(crate) const fn log2floor(value: U256) -> u64 { - let mut l: u64 = 256; - let mut i = 3; - loop { - if value.as_limbs()[i] == 0u64 { - l -= 64; - } else { - l -= value.as_limbs()[i].leading_zeros() as u64; - if l == 0 { - return l; - } else { - return l - 1; - } - } - if i == 0 { - break; - } - i -= 1; - } - l -} +use context_interface::{ + cfg::gas::*, transaction::AccessListItemTr as _, Transaction, TransactionType, +}; +use primitives::{eip7702, hardfork::SpecId}; /// Calculate the cost of buffer per word. #[inline] @@ -45,15 +23,6 @@ pub const fn initcode_cost(len: usize) -> u64 { cost } -/// Memory expansion cost calculation for a given number of words. -#[inline] -pub const fn memory_gas(num_words: usize, linear_cost: u64, quadratic_cost: u64) -> u64 { - let num_words = num_words as u64; - linear_cost - .saturating_mul(num_words) - .saturating_add(num_words.saturating_mul(num_words) / quadratic_cost) -} - /// Init and floor gas from transaction #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/crates/interpreter/src/gas/constants.rs b/crates/interpreter/src/gas/constants.rs deleted file mode 100644 index a4a101a985..0000000000 --- a/crates/interpreter/src/gas/constants.rs +++ /dev/null @@ -1,103 +0,0 @@ -/// Gas cost for operations that consume zero gas. -pub const ZERO: u64 = 0; -/// Base gas cost for basic operations. -pub const BASE: u64 = 2; - -/// Gas cost for very low-cost operations. -pub const VERYLOW: u64 = 3; -/// Gas cost for DATALOADN instruction. -pub const DATA_LOADN_GAS: u64 = 3; - -/// Gas cost for conditional jump instructions. -pub const CONDITION_JUMP_GAS: u64 = 4; -/// Gas cost for RETF instruction. -pub const RETF_GAS: u64 = 3; -/// Gas cost for DATALOAD instruction. -pub const DATA_LOAD_GAS: u64 = 4; - -/// Gas cost for low-cost operations. -pub const LOW: u64 = 5; -/// Gas cost for medium-cost operations. -pub const MID: u64 = 8; -/// Gas cost for high-cost operations. -pub const HIGH: u64 = 10; -/// Gas cost for JUMPDEST instruction. -pub const JUMPDEST: u64 = 1; -/// Gas cost for REFUND SELFDESTRUCT instruction. -pub const SELFDESTRUCT_REFUND: i64 = 24000; -/// Gas cost for CREATE instruction. -pub const CREATE: u64 = 32000; -/// Additional gas cost when a call transfers value. -pub const CALLVALUE: u64 = 9000; -/// Gas cost for creating a new account. -pub const NEWACCOUNT: u64 = 25000; -/// Base gas cost for EXP instruction. -pub const EXP: u64 = 10; -/// Gas cost per word for memory operations. -pub const MEMORY: u64 = 3; -/// Base gas cost for LOG instructions. -pub const LOG: u64 = 375; -/// Gas cost per byte of data in LOG instructions. -pub const LOGDATA: u64 = 8; -/// Gas cost per topic in LOG instructions. -pub const LOGTOPIC: u64 = 375; -/// Base gas cost for KECCAK256 instruction. -pub const KECCAK256: u64 = 30; -/// Gas cost per word for KECCAK256 instruction. -pub const KECCAK256WORD: u64 = 6; -/// Gas cost per word for copy operations. -pub const COPY: u64 = 3; -/// Gas cost for BLOCKHASH instruction. -pub const BLOCKHASH: u64 = 20; -/// Gas cost per byte for code deposit during contract creation. -pub const CODEDEPOSIT: u64 = 200; - -/// EIP-1884: Repricing for trie-size-dependent opcodes -pub const ISTANBUL_SLOAD_GAS: u64 = 800; -/// Gas cost for SSTORE when setting a storage slot from zero to non-zero. -pub const SSTORE_SET: u64 = 20000; -/// Gas cost for SSTORE when modifying an existing non-zero storage slot. -pub const SSTORE_RESET: u64 = 5000; -/// Gas refund for SSTORE when clearing a storage slot (setting to zero). -pub const REFUND_SSTORE_CLEARS: i64 = 15000; - -/// The standard cost of calldata token. -pub const STANDARD_TOKEN_COST: u64 = 4; -/// The cost of a non-zero byte in calldata. -pub const NON_ZERO_BYTE_DATA_COST: u64 = 68; -/// The multiplier for a non zero byte in calldata. -pub const NON_ZERO_BYTE_MULTIPLIER: u64 = NON_ZERO_BYTE_DATA_COST / STANDARD_TOKEN_COST; -/// The cost of a non-zero byte in calldata adjusted by [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028). -pub const NON_ZERO_BYTE_DATA_COST_ISTANBUL: u64 = 16; -/// The multiplier for a non zero byte in calldata adjusted by [EIP-2028](https://eips.ethereum.org/EIPS/eip-2028). -pub const NON_ZERO_BYTE_MULTIPLIER_ISTANBUL: u64 = - NON_ZERO_BYTE_DATA_COST_ISTANBUL / STANDARD_TOKEN_COST; -/// The cost floor per token as defined by EIP-2028. -pub const TOTAL_COST_FLOOR_PER_TOKEN: u64 = 10; - -/// Gas cost for EOF CREATE instruction. -pub const EOF_CREATE_GAS: u64 = 32000; - -// Berlin EIP-2929/EIP-2930 constants -/// Gas cost for accessing an address in the access list (EIP-2930). -pub const ACCESS_LIST_ADDRESS: u64 = 2400; -/// Gas cost for accessing a storage key in the access list (EIP-2930). -pub const ACCESS_LIST_STORAGE_KEY: u64 = 1900; - -/// Gas cost for SLOAD when accessing a cold storage slot (EIP-2929). -pub const COLD_SLOAD_COST: u64 = 2100; -/// Gas cost for accessing a cold account (EIP-2929). -pub const COLD_ACCOUNT_ACCESS_COST: u64 = 2600; -/// Additional gas cost for accessing a cold account. -pub const COLD_ACCOUNT_ACCESS_COST_ADDITIONAL: u64 = - COLD_ACCOUNT_ACCESS_COST - WARM_STORAGE_READ_COST; -/// Gas cost for reading from a warm storage slot (EIP-2929). -pub const WARM_STORAGE_READ_COST: u64 = 100; -/// Gas cost for SSTORE reset operation on a warm storage slot. -pub const WARM_SSTORE_RESET: u64 = SSTORE_RESET - COLD_SLOAD_COST; - -/// EIP-3860 : Limit and meter initcode -pub const INITCODE_WORD_COST: u64 = 2; - -/// Gas stipend provided to the recipient of a CALL with value transfer. -pub const CALL_STIPEND: u64 = 2300; diff --git a/crates/interpreter/src/instructions.rs b/crates/interpreter/src/instructions.rs index cae338c29f..969805b583 100644 --- a/crates/interpreter/src/instructions.rs +++ b/crates/interpreter/src/instructions.rs @@ -27,9 +27,10 @@ pub mod tx_info; /// Utility functions and helpers for instruction implementation. pub mod utility; -use primitives::hardfork::SpecId; +pub use context_interface::cfg::gas::{self, *}; -use crate::{gas, interpreter_types::InterpreterTypes, Host, InstructionContext}; +use crate::{interpreter_types::InterpreterTypes, Host, InstructionContext}; +use primitives::hardfork::SpecId; /// EVM opcode function signature. #[derive(Debug)] diff --git a/crates/interpreter/src/instructions/arithmetic.rs b/crates/interpreter/src/instructions/arithmetic.rs index 024938ad8d..9692adce74 100644 --- a/crates/interpreter/src/instructions/arithmetic.rs +++ b/crates/interpreter/src/instructions/arithmetic.rs @@ -3,6 +3,7 @@ use crate::{ interpreter_types::{InterpreterTypes, StackTr}, InstructionContext, }; +use context_interface::Host; use primitives::U256; /// Implements the ADD instruction - adds two values from stack. @@ -74,11 +75,11 @@ pub fn mulmod(context: InstructionContext<'_, } /// Implements the EXP instruction - exponentiates two values from stack. -pub fn exp(context: InstructionContext<'_, H, WIRE>) { +pub fn exp(context: InstructionContext<'_, H, WIRE>) { popn_top!([op1], op2, context.interpreter); gas!( context.interpreter, - context.interpreter.gas_params.exp_cost(*op2) + context.host.gas_params().exp_cost(*op2) ); *op2 = op1.pow(*op2); } diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 170fbe56bd..57972a2de2 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -225,7 +225,7 @@ mod tests { push!(interpreter, test.value); push!(interpreter, test.shift); let context = InstructionContext { - host: &mut DummyHost, + host: &mut DummyHost::default(), interpreter: &mut interpreter, }; shl(context); @@ -308,7 +308,7 @@ mod tests { push!(interpreter, test.value); push!(interpreter, test.shift); let context = InstructionContext { - host: &mut DummyHost, + host: &mut DummyHost::default(), interpreter: &mut interpreter, }; shr(context); @@ -416,7 +416,7 @@ mod tests { push!(interpreter, test.value); push!(interpreter, test.shift); let context = InstructionContext { - host: &mut DummyHost, + host: &mut DummyHost::default(), interpreter: &mut interpreter, }; sar(context); @@ -454,7 +454,7 @@ mod tests { push!(interpreter, test.input); push!(interpreter, U256::from(test.index)); let context = InstructionContext { - host: &mut DummyHost, + host: &mut DummyHost::default(), interpreter: &mut interpreter, }; byte(context); @@ -466,7 +466,8 @@ mod tests { #[test] fn test_clz() { let mut interpreter = Interpreter::default(); - interpreter.set_spec_id(SpecId::OSAKA); + interpreter.runtime_flag.spec_id = SpecId::OSAKA; + let mut host = DummyHost::new(SpecId::OSAKA); struct TestCase { value: U256, @@ -507,7 +508,7 @@ mod tests { for test in test_cases { push!(interpreter, test.value); let context = InstructionContext { - host: &mut DummyHost, + host: &mut host, interpreter: &mut interpreter, }; clz(context); diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index dbcefcc426..b7a7cc9927 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -52,12 +52,17 @@ pub fn create( } gas!( context.interpreter, - context.interpreter.gas_params.initcode_cost(len) + context.host.gas_params().initcode_cost(len) ); } let code_offset = as_usize_or_fail!(context.interpreter, code_offset); - resize_memory!(context.interpreter, code_offset, len); + resize_memory!( + context.interpreter, + context.host.gas_params(), + code_offset, + len + ); code = Bytes::copy_from_slice( context @@ -74,14 +79,11 @@ pub fn create( // SAFETY: `len` is reasonable in size as gas for it is already deducted. gas!( context.interpreter, - context.interpreter.gas_params.create2_cost(len) + context.host.gas_params().create2_cost(len) ); CreateScheme::Create2 { salt } } else { - gas!( - context.interpreter, - context.interpreter.gas_params.create_cost() - ); + gas!(context.interpreter, context.host.gas_params().create_cost()); CreateScheme::Create }; @@ -95,10 +97,7 @@ pub fn create( .is_enabled_in(SpecId::TANGERINE) { // Take remaining gas and deduce l64 part of it. - gas_limit = context - .interpreter - .gas_params - .call_stipend_reduction(gas_limit); + gas_limit = context.host.gas_params().call_stipend_reduction(gas_limit); } gas!(context.interpreter, gas_limit); @@ -136,7 +135,8 @@ pub fn call( return; } - let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter) + let Some((input, return_memory_offset)) = + get_memory_input_and_out_ranges(context.interpreter, context.host.gas_params()) else { return; }; @@ -179,7 +179,8 @@ pub fn call_code( let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); let has_transfer = !value.is_zero(); - let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter) + let Some((input, return_memory_offset)) = + get_memory_input_and_out_ranges(context.interpreter, context.host.gas_params()) else { return; }; @@ -222,7 +223,8 @@ pub fn delegate_call( // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); - let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter) + let Some((input, return_memory_offset)) = + get_memory_input_and_out_ranges(context.interpreter, context.host.gas_params()) else { return; }; @@ -265,7 +267,8 @@ pub fn static_call( // Max gas limit is not possible in real ethereum situation. let local_gas_limit = u64::try_from(local_gas_limit).unwrap_or(u64::MAX); - let Some((input, return_memory_offset)) = get_memory_input_and_out_ranges(context.interpreter) + let Some((input, return_memory_offset)) = + get_memory_input_and_out_ranges(context.interpreter, context.host.gas_params()) else { return; }; diff --git a/crates/interpreter/src/instructions/contract/call_helpers.rs b/crates/interpreter/src/instructions/contract/call_helpers.rs index f58ad3ae7a..47d49305fc 100644 --- a/crates/interpreter/src/instructions/contract/call_helpers.rs +++ b/crates/interpreter/src/instructions/contract/call_helpers.rs @@ -1,10 +1,9 @@ use crate::{ - gas::params::GasParams, interpreter::Interpreter, interpreter_types::{InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}, InstructionContext, }; -use context_interface::{host::LoadError, Host}; +use context_interface::{cfg::GasParams, host::LoadError, Host}; use core::{cmp::min, ops::Range}; use primitives::{ hardfork::SpecId::{self, *}, @@ -16,17 +15,18 @@ use state::Bytecode; #[inline] pub fn get_memory_input_and_out_ranges( interpreter: &mut Interpreter, + gas_params: &GasParams, ) -> Option<(Range, Range)> { popn!([in_offset, in_len, out_offset, out_len], interpreter, None); - let mut in_range = resize_memory(interpreter, in_offset, in_len)?; + let mut in_range = resize_memory(interpreter, gas_params, in_offset, in_len)?; if !in_range.is_empty() { let offset = interpreter.memory.local_memory_offset(); in_range = in_range.start.saturating_add(offset)..in_range.end.saturating_add(offset); } - let ret_range = resize_memory(interpreter, out_offset, out_len)?; + let ret_range = resize_memory(interpreter, gas_params, out_offset, out_len)?; Some((in_range, ret_range)) } @@ -35,13 +35,14 @@ pub fn get_memory_input_and_out_ranges( #[inline] pub fn resize_memory( interpreter: &mut Interpreter, + gas_params: &GasParams, offset: U256, len: U256, ) -> Option> { let len = as_usize_or_fail_ret!(interpreter, len, None); let offset = if len != 0 { let offset = as_usize_or_fail_ret!(interpreter, offset, None); - resize_memory!(interpreter, offset, len, None); + resize_memory!(interpreter, gas_params, offset, len, None); offset } else { usize::MAX //unrealistic value so we are sure it is not used @@ -62,7 +63,7 @@ pub fn load_acc_and_calc_gas( if transfers_value { gas!( context.interpreter, - context.interpreter.gas_params.transfer_value_cost(), + context.host.gas_params().transfer_value_cost(), None ); } @@ -76,12 +77,13 @@ pub fn load_acc_and_calc_gas( gas!(interpreter, gas, None); let interpreter = &mut context.interpreter; + let host = &mut context.host; // EIP-150: Gas cost changes for IO-heavy operations let mut gas_limit = if interpreter.runtime_flag.spec_id().is_enabled_in(TANGERINE) { // On mainnet this will take return 63/64 of gas_limit. - let reduced_gas_limit = interpreter - .gas_params + let reduced_gas_limit = host + .gas_params() .call_stipend_reduction(interpreter.gas.remaining()); min(reduced_gas_limit, stack_gas_limit) } else { @@ -91,7 +93,7 @@ pub fn load_acc_and_calc_gas( // Add call stipend if there is value to be transferred. if transfers_value { - gas_limit = gas_limit.saturating_add(interpreter.gas_params.call_stipend()); + gas_limit = gas_limit.saturating_add(host.gas_params().call_stipend()); } Some((gas_limit, bytecode, code_hash)) @@ -107,10 +109,8 @@ pub fn load_account_delegated_handle_error( ) -> Option<(u64, Bytecode, B256)> { // move this to static gas. let remaining_gas = context.interpreter.gas.remaining(); - let gas_table = &context.interpreter.gas_params; match load_account_delegated( context.host, - gas_table, context.interpreter.runtime_flag.spec_id(), remaining_gas, to, @@ -134,7 +134,6 @@ pub fn load_account_delegated_handle_error( #[inline] pub fn load_account_delegated( host: &mut H, - gas_table: &GasParams, spec: SpecId, remaining_gas: u64, address: Address, @@ -145,7 +144,8 @@ pub fn load_account_delegated( let is_berlin = spec.is_enabled_in(SpecId::BERLIN); let is_spurious_dragon = spec.is_enabled_in(SpecId::SPURIOUS_DRAGON); - let additional_cold_cost = gas_table.cold_account_additional_cost(); + let additional_cold_cost = host.gas_params().cold_account_additional_cost(); + let warm_storage_read_cost = host.gas_params().warm_storage_read_cost(); let skip_cold_load = is_berlin && remaining_gas < additional_cold_cost; let account = host.load_account_info_skip_cold_load(address, true, skip_cold_load)?; @@ -156,14 +156,16 @@ pub fn load_account_delegated( let mut code_hash = account.code_hash(); // New account cost, as account is empty there is no delegated account and we can return early. if create_empty_account && account.is_empty { - cost += gas_table.new_account_cost(is_spurious_dragon, transfers_value); + cost += host + .gas_params() + .new_account_cost(is_spurious_dragon, transfers_value); return Ok((cost, bytecode, code_hash)); } // load delegate code if account is EIP-7702 if let Some(Bytecode::Eip7702(code)) = &account.code { // EIP-7702 is enabled after berlin hardfork. - cost += gas_table.warm_storage_read_cost(); + cost += warm_storage_read_cost; if cost > remaining_gas { return Err(LoadError::ColdLoadSkipped); } diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 32ff53ca81..bb85393b6b 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -3,6 +3,7 @@ use crate::{ interpreter_types::{InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr}, InstructionResult, InterpreterAction, }; +use context_interface::{cfg::GasParams, Host}; use primitives::{Bytes, U256}; use crate::InstructionContext; @@ -61,6 +62,7 @@ pub fn pc(context: InstructionContext<'_, H, /// Handles memory data retrieval and sets the return action. fn return_inner( interpreter: &mut Interpreter, + gas_params: &GasParams, instruction_result: InstructionResult, ) { popn!([offset, len], interpreter); @@ -69,7 +71,7 @@ fn return_inner( let mut output = Bytes::default(); if len != 0 { let offset = as_usize_or_fail!(interpreter, offset); - if !interpreter.resize_memory(offset, len) { + if !interpreter.resize_memory(gas_params, offset, len) { return; } output = interpreter.memory.slice_len(offset, len).to_vec().into() @@ -87,14 +89,22 @@ fn return_inner( /// Implements the RETURN instruction. /// /// Halts execution and returns data from memory. -pub fn ret(context: InstructionContext<'_, H, WIRE>) { - return_inner(context.interpreter, InstructionResult::Return); +pub fn ret(context: InstructionContext<'_, H, WIRE>) { + return_inner( + context.interpreter, + context.host.gas_params(), + InstructionResult::Return, + ); } /// EIP-140: REVERT instruction -pub fn revert(context: InstructionContext<'_, H, WIRE>) { +pub fn revert(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, BYZANTIUM); - return_inner(context.interpreter, InstructionResult::Revert); + return_inner( + context.interpreter, + context.host.gas_params(), + InstructionResult::Revert, + ); } /// Stop opcode. This opcode halts the execution. diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 489be144b6..99f5c007bd 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -120,7 +120,7 @@ pub fn extcodecopy( let len = as_usize_or_fail!(context.interpreter, len_u256); gas!( context.interpreter, - context.interpreter.gas_params.extcodecopy(len) + context.host.gas_params().extcodecopy(len) ); let mut memory_offset_usize = 0; @@ -129,7 +129,12 @@ pub fn extcodecopy( // fail on casting of memory_offset only if len is not zero. memory_offset_usize = as_usize_or_fail!(context.interpreter, memory_offset); // Resize memory to fit the code - resize_memory!(context.interpreter, memory_offset_usize, len); + resize_memory!( + context.interpreter, + context.host.gas_params(), + memory_offset_usize, + len + ); } let code = if spec_id.is_enabled_in(BERLIN) { @@ -195,10 +200,7 @@ pub fn sload(context: InstructionConte let target = context.interpreter.input.target_address(); if spec_id.is_enabled_in(BERLIN) { - let additional_cold_cost = context - .interpreter - .gas_params - .cold_storage_additional_cost(); + let additional_cold_cost = context.host.gas_params().cold_storage_additional_cost(); let skip_cold = context.interpreter.gas.remaining() < additional_cold_cost; let res = context.host.sload_skip_cold_load(target, *index, skip_cold); match res { @@ -233,7 +235,7 @@ pub fn sstore(context: InstructionCont // EIP-2200: Structured Definitions for Net Gas Metering // If gasleft is less than or equal to gas stipend, fail the current call frame with ‘out of gas’ exception. if spec_id.is_enabled_in(ISTANBUL) - && context.interpreter.gas.remaining() <= context.interpreter.gas_params.call_stipend() + && context.interpreter.gas.remaining() <= context.host.gas_params().call_stipend() { context .interpreter @@ -243,14 +245,11 @@ pub fn sstore(context: InstructionCont gas!( context.interpreter, - context.interpreter.gas_params.sstore_static_gas() + context.host.gas_params().sstore_static_gas() ); let state_load = if spec_id.is_enabled_in(BERLIN) { - let additional_cold_cost = context - .interpreter - .gas_params - .cold_storage_additional_cost(); + let additional_cold_cost = context.host.gas_params().cold_storage_additional_cost(); let skip_cold = context.interpreter.gas.remaining() < additional_cold_cost; let res = context .host @@ -272,7 +271,7 @@ pub fn sstore(context: InstructionCont // dynamic gas gas!( context.interpreter, - context.interpreter.gas_params.sstore_dynamic_gas( + context.host.gas_params().sstore_dynamic_gas( is_istanbul, &state_load.data, state_load.is_cold @@ -282,8 +281,8 @@ pub fn sstore(context: InstructionCont // refund context.interpreter.gas.record_refund( context - .interpreter - .gas_params + .host + .gas_params() .sstore_refund(is_istanbul, &state_load.data), ); } @@ -323,14 +322,14 @@ pub fn log( let len = as_usize_or_fail!(context.interpreter, len); gas!( context.interpreter, - context.interpreter.gas_params.log_cost(N as u8, len as u64) + context.host.gas_params().log_cost(N as u8, len as u64) ); let data = if len == 0 { Bytes::new() } else { let offset = as_usize_or_fail!(context.interpreter, offset); // Resize memory to fit the data - resize_memory!(context.interpreter, offset, len); + resize_memory!(context.interpreter, context.host.gas_params(), offset, len); Bytes::copy_from_slice(context.interpreter.memory.slice_len(offset, len).as_ref()) }; let Some(topics) = context.interpreter.stack.popn::() else { @@ -358,7 +357,7 @@ pub fn selfdestruct( let target = target.into_address(); let spec = context.interpreter.runtime_flag.spec_id(); - let cold_load_gas = context.interpreter.gas_params.selfdestruct_cold_cost(); + let cold_load_gas = context.host.gas_params().selfdestruct_cold_cost(); let skip_cold_load = context.interpreter.gas.remaining() < cold_load_gas; let res = match context.host.selfdestruct( @@ -381,8 +380,8 @@ pub fn selfdestruct( gas!( context.interpreter, context - .interpreter - .gas_params + .host + .gas_params() .selfdestruct_cost(should_charge_topup, res.is_cold) ); @@ -390,7 +389,7 @@ pub fn selfdestruct( context .interpreter .gas - .record_refund(context.interpreter.gas_params.selfdestruct_refund()); + .record_refund(context.host.gas_params().selfdestruct_refund()); } context.interpreter.halt(InstructionResult::SelfDestruct); diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 30e30fd949..a45648a52f 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -51,10 +51,7 @@ macro_rules! berlin_load_account { $crate::berlin_load_account!($context, $address, $load_code, ()) }; ($context:expr, $address:expr, $load_code:expr, $ret:expr) => {{ - let cold_load_gas = $context - .interpreter - .gas_params - .cold_account_additional_cost(); + let cold_load_gas = $context.host.gas_params().cold_account_additional_cost(); let skip_cold_load = $context.interpreter.gas.remaining() < cold_load_gas; match $context .host @@ -83,14 +80,14 @@ macro_rules! berlin_load_account { #[macro_export] #[collapse_debuginfo(yes)] macro_rules! resize_memory { - ($interpreter:expr, $offset:expr, $len:expr) => { - $crate::resize_memory!($interpreter, $offset, $len, ()) + ($interpreter:expr, $gas_params:expr, $offset:expr, $len:expr) => { + $crate::resize_memory!($interpreter, $gas_params, $offset, $len, ()) }; - ($interpreter:expr, $offset:expr, $len:expr, $ret:expr) => { + ($interpreter:expr, $gas_params:expr, $offset:expr, $len:expr, $ret:expr) => { if let Err(result) = $crate::interpreter::resize_memory( &mut $interpreter.gas, &mut $interpreter.memory, - &$interpreter.gas_params, + $gas_params, $offset, $len, ) { diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index 81d7e0c46a..f6856fc634 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -1,4 +1,5 @@ use crate::interpreter_types::{InterpreterTypes, MemoryTr, RuntimeFlag, StackTr}; +use context_interface::Host; use core::cmp::max; use primitives::U256; @@ -7,10 +8,10 @@ use crate::InstructionContext; /// Implements the MLOAD instruction. /// /// Loads a 32-byte word from memory. -pub fn mload(context: InstructionContext<'_, H, WIRE>) { +pub fn mload(context: InstructionContext<'_, H, WIRE>) { popn_top!([], top, context.interpreter); let offset = as_usize_or_fail!(context.interpreter, top); - resize_memory!(context.interpreter, offset, 32); + resize_memory!(context.interpreter, context.host.gas_params(), offset, 32); *top = U256::try_from_be_slice(context.interpreter.memory.slice_len(offset, 32).as_ref()).unwrap() } @@ -18,10 +19,10 @@ pub fn mload(context: InstructionContext<'_, /// Implements the MSTORE instruction. /// /// Stores a 32-byte word to memory. -pub fn mstore(context: InstructionContext<'_, H, WIRE>) { +pub fn mstore(context: InstructionContext<'_, H, WIRE>) { popn!([offset, value], context.interpreter); let offset = as_usize_or_fail!(context.interpreter, offset); - resize_memory!(context.interpreter, offset, 32); + resize_memory!(context.interpreter, context.host.gas_params(), offset, 32); context .interpreter .memory @@ -31,10 +32,10 @@ pub fn mstore(context: InstructionContext<'_, /// Implements the MSTORE8 instruction. /// /// Stores a single byte to memory. -pub fn mstore8(context: InstructionContext<'_, H, WIRE>) { +pub fn mstore8(context: InstructionContext<'_, H, WIRE>) { popn!([offset, value], context.interpreter); let offset = as_usize_or_fail!(context.interpreter, offset); - resize_memory!(context.interpreter, offset, 1); + resize_memory!(context.interpreter, context.host.gas_params(), offset, 1); context.interpreter.memory.set(offset, &[value.byte(0)]); } @@ -51,7 +52,7 @@ pub fn msize(context: InstructionContext<'_, /// Implements the MCOPY instruction. /// /// EIP-5656: Memory copying instruction that copies memory from one location to another. -pub fn mcopy(context: InstructionContext<'_, H, WIRE>) { +pub fn mcopy(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, CANCUN); popn!([dst, src, len], context.interpreter); @@ -60,7 +61,7 @@ pub fn mcopy(context: InstructionContext<'_, // Deduce gas gas!( context.interpreter, - context.interpreter.gas_params.mcopy_cost(len) + context.host.gas_params().mcopy_cost(len) ); if len == 0 { @@ -70,7 +71,12 @@ pub fn mcopy(context: InstructionContext<'_, let dst = as_usize_or_fail!(context.interpreter, dst); let src = as_usize_or_fail!(context.interpreter, src); // Resize memory - resize_memory!(context.interpreter, max(dst, src), len); + resize_memory!( + context.interpreter, + context.host.gas_params(), + max(dst, src), + len + ); // Copy memory in place context.interpreter.memory.copy(dst, src, len); } diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 678dd7bf6a..1ad3bf86cc 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -5,6 +5,7 @@ use crate::{ }, CallInput, InstructionResult, }; +use context_interface::{cfg::GasParams, Host}; use core::ptr; use primitives::{B256, KECCAK_EMPTY, U256}; @@ -13,18 +14,20 @@ use crate::InstructionContext; /// Implements the KECCAK256 instruction. /// /// Computes Keccak-256 hash of memory data. -pub fn keccak256(context: InstructionContext<'_, H, WIRE>) { +pub fn keccak256( + context: InstructionContext<'_, H, WIRE>, +) { popn_top!([offset], top, context.interpreter); let len = as_usize_or_fail!(context.interpreter, top); gas!( context.interpreter, - context.interpreter.gas_params.keccak256_cost(len) + context.host.gas_params().keccak256_cost(len) ); let hash = if len == 0 { KECCAK_EMPTY } else { let from = as_usize_or_fail!(context.interpreter, offset); - resize_memory!(context.interpreter, from, len); + resize_memory!(context.interpreter, context.host.gas_params(), from, len); primitives::keccak256(context.interpreter.memory.slice_len(from, len).as_ref()) }; *top = hash.into(); @@ -73,11 +76,17 @@ pub fn codesize(context: InstructionContext<' /// Implements the CODECOPY instruction. /// /// Copies running contract's bytecode to memory. -pub fn codecopy(context: InstructionContext<'_, H, WIRE>) { +pub fn codecopy( + context: InstructionContext<'_, H, WIRE>, +) { popn!([memory_offset, code_offset, len], context.interpreter); let len = as_usize_or_fail!(context.interpreter, len); - let Some(memory_offset) = copy_cost_and_memory_resize(context.interpreter, memory_offset, len) - else { + let Some(memory_offset) = copy_cost_and_memory_resize( + context.interpreter, + context.host.gas_params(), + memory_offset, + len, + ) else { return; }; let code_offset = as_usize_saturated!(code_offset); @@ -148,11 +157,17 @@ pub fn callvalue(context: InstructionContext< /// Implements the CALLDATACOPY instruction. /// /// Copies input data to memory. -pub fn calldatacopy(context: InstructionContext<'_, H, WIRE>) { +pub fn calldatacopy( + context: InstructionContext<'_, H, WIRE>, +) { popn!([memory_offset, data_offset, len], context.interpreter); let len = as_usize_or_fail!(context.interpreter, len); - let Some(memory_offset) = copy_cost_and_memory_resize(context.interpreter, memory_offset, len) - else { + let Some(memory_offset) = copy_cost_and_memory_resize( + context.interpreter, + context.host.gas_params(), + memory_offset, + len, + ) else { return; }; @@ -185,7 +200,9 @@ pub fn returndatasize(context: InstructionCon } /// EIP-211: New opcodes: RETURNDATASIZE and RETURNDATACOPY -pub fn returndatacopy(context: InstructionContext<'_, H, WIRE>) { +pub fn returndatacopy( + context: InstructionContext<'_, H, WIRE>, +) { check!(context.interpreter, BYZANTIUM); popn!([memory_offset, offset, len], context.interpreter); @@ -199,8 +216,12 @@ pub fn returndatacopy(context: InstructionCon return; } - let Some(memory_offset) = copy_cost_and_memory_resize(context.interpreter, memory_offset, len) - else { + let Some(memory_offset) = copy_cost_and_memory_resize( + context.interpreter, + context.host.gas_params(), + memory_offset, + len, + ) else { return; }; @@ -228,16 +249,17 @@ pub fn gas(context: InstructionContext<'_, H, /// Handles memory expansion and gas calculation for data copy operations. pub fn copy_cost_and_memory_resize( interpreter: &mut Interpreter, + gas_params: &GasParams, memory_offset: U256, len: usize, ) -> Option { // Safe to cast usize to u64 - gas!(interpreter, interpreter.gas_params.copy_cost(len), None); + gas!(interpreter, gas_params.copy_cost(len), None); if len == 0 { return None; } let memory_offset = as_usize_or_fail_ret!(interpreter, memory_offset, None); - resize_memory!(interpreter, memory_offset, len, None); + resize_memory!(interpreter, gas_params, memory_offset, len, None); Some(memory_offset) } diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 2bfdab36a5..698773409f 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -9,6 +9,7 @@ mod runtime_flags; mod shared_memory; mod stack; +use context_interface::cfg::GasParams; // re-exports pub use ext_bytecode::ExtBytecode; pub use input::InputsImpl; @@ -19,8 +20,8 @@ pub use stack::{Stack, STACK_LIMIT}; // imports use crate::{ - gas::params::GasParams, host::DummyHost, instruction_context::InstructionContext, - interpreter_types::*, Gas, Host, InstructionResult, InstructionTable, InterpreterAction, + host::DummyHost, instruction_context::InstructionContext, interpreter_types::*, Gas, Host, + InstructionResult, InstructionTable, InterpreterAction, }; use bytecode::Bytecode; use primitives::{hardfork::SpecId, Bytes}; @@ -29,8 +30,6 @@ use primitives::{hardfork::SpecId, Bytes}; #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Interpreter { - /// Gas table for dynamic gas constants. - pub gas_params: GasParams, /// Bytecode being executed. pub bytecode: WIRE::Bytecode, /// Gas tracking for execution costs. @@ -58,7 +57,6 @@ impl Interpreter> { is_static: bool, spec_id: SpecId, gas_limit: u64, - gas_params: GasParams, ) -> Self { Self::new_inner( Stack::new(), @@ -68,7 +66,6 @@ impl Interpreter> { is_static, spec_id, gas_limit, - gas_params, ) } @@ -91,7 +88,6 @@ impl Interpreter> { false, SpecId::default(), u64::MAX, - GasParams::default(), ) } @@ -104,12 +100,10 @@ impl Interpreter> { is_static: bool, spec_id: SpecId, gas_limit: u64, - gas_params: GasParams, ) -> Self { Self { bytecode, gas: Gas::new(gas_limit), - gas_params, stack, return_data: Default::default(), memory, @@ -130,12 +124,10 @@ impl Interpreter> { is_static: bool, spec_id: SpecId, gas_limit: u64, - gas_params: GasParams, ) { let Self { bytecode: bytecode_ref, gas, - gas_params: gas_params_ref, stack, return_data, memory: memory_ref, @@ -154,7 +146,6 @@ impl Interpreter> { *memory_ref = memory; *input_ref = input; *runtime_flag = RuntimeFlags { spec_id, is_static }; - *gas_params_ref = gas_params; *extend = EXT::default(); } @@ -163,12 +154,6 @@ impl Interpreter> { self.bytecode = ExtBytecode::new(bytecode); self } - - /// Sets the specid for the interpreter. - pub fn set_spec_id(&mut self, spec_id: SpecId) { - self.gas_params = GasParams::new_spec(spec_id); - self.runtime_flag.spec_id = spec_id; - } } impl Default for Interpreter { @@ -198,14 +183,9 @@ impl Interpreter { /// Performs EVM memory resize. #[inline] #[must_use] - pub fn resize_memory(&mut self, offset: usize, len: usize) -> bool { - if let Err(result) = resize_memory( - &mut self.gas, - &mut self.memory, - &self.gas_params, - offset, - len, - ) { + pub fn resize_memory(&mut self, gas_params: &GasParams, offset: usize, len: usize) -> bool { + if let Err(result) = resize_memory(&mut self.gas, &mut self.memory, gas_params, offset, len) + { self.halt(result); return false; } @@ -333,7 +313,7 @@ impl Interpreter { /// This uses dummy Host. #[inline] pub fn step_dummy(&mut self, instruction_table: &InstructionTable) { - self.step(instruction_table, &mut DummyHost); + self.step(instruction_table, &mut DummyHost::default()); } /// Executes the interpreter until it returns or stops. @@ -448,7 +428,6 @@ mod tests { false, SpecId::default(), u64::MAX, - GasParams::default(), ); let serialized = serde_json::to_string_pretty(&interpreter).unwrap(); @@ -486,11 +465,10 @@ fn test_mstore_big_offset_memory_oog() { false, SpecId::default(), 1000, - GasParams::default(), ); let table = instruction_table::(); - let mut host = DummyHost; + let mut host = DummyHost::default(); let action = interpreter.run_plain(&table, &mut host); assert!(action.is_return()); @@ -525,11 +503,10 @@ fn test_mstore_big_offset_memory_limit_oog() { false, SpecId::default(), 100000, - GasParams::default(), ); let table = instruction_table::(); - let mut host = DummyHost; + let mut host = DummyHost::default(); let action = interpreter.run_plain(&table, &mut host); assert!(action.is_return()); diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index abaf4ca1df..f7a7598a8c 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -1,5 +1,6 @@ use super::MemoryTr; -use crate::{gas::params::GasParams, InstructionResult}; +use crate::InstructionResult; +use context_interface::cfg::GasParams; use core::{ cell::{Ref, RefCell, RefMut}, cmp::min, diff --git a/crates/op-revm/src/evm.rs b/crates/op-revm/src/evm.rs index a93a172756..64f28a3e35 100644 --- a/crates/op-revm/src/evm.rs +++ b/crates/op-revm/src/evm.rs @@ -1,7 +1,7 @@ //! Contains the `[OpEvm]` type and its implementation of the execution EVM traits. -use crate::precompiles::OpPrecompiles; +use crate::{precompiles::OpPrecompiles, OpSpecId}; use revm::{ - context::{ContextError, ContextSetters, Evm, FrameStack}, + context::{Cfg, ContextError, ContextSetters, Evm, FrameStack}, context_interface::ContextTr, handler::{ evm::FrameTr, @@ -26,17 +26,25 @@ pub struct OpEvm< pub Evm, ); -impl OpEvm, OpPrecompiles> { +impl + Clone>>, INSP> + OpEvm, OpPrecompiles> +{ /// Create a new Optimism EVM. pub fn new(ctx: CTX, inspector: INSP) -> Self { + let spec: OpSpecId = ctx.cfg().spec().into(); Self(Evm { ctx, inspector, - instruction: EthInstructions::new_mainnet(), - precompiles: OpPrecompiles::default(), + instruction: EthInstructions::new_mainnet_with_spec(spec.into()), + precompiles: OpPrecompiles::new_with_spec(spec), frame_stack: FrameStack::new_prealloc(8), }) } + + /// Consumes self and returns the inner context. + pub fn into_context(self) -> CTX { + self.0.ctx + } } impl OpEvm { diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index ef51d2eddc..ada5a49a0f 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -464,7 +464,7 @@ mod tests { }; use alloy_primitives::uint; use revm::{ - context::{BlockEnv, Context, TxEnv}, + context::{BlockEnv, CfgEnv, Context, TxEnv}, context_interface::result::InvalidTransaction, database::InMemoryDB, database_interface::EmptyDB, @@ -511,7 +511,7 @@ mod tests { .base(TxEnv::builder().gas_limit(100)) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::BEDROCK); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::BEDROCK)); let gas = call_last_frame_return(ctx, InstructionResult::Revert, Gas::new(90)); assert_eq!(gas.remaining(), 90); @@ -527,7 +527,7 @@ mod tests { .base(TxEnv::builder().gas_limit(100)) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let gas = call_last_frame_return(ctx, InstructionResult::Stop, Gas::new(90)); assert_eq!(gas.remaining(), 90); @@ -544,7 +544,7 @@ mod tests { .source_hash(B256::from([1u8; 32])) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let mut ret_gas = Gas::new(90); ret_gas.record_refund(20); @@ -569,7 +569,7 @@ mod tests { .source_hash(B256::from([1u8; 32])) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::BEDROCK); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::BEDROCK)); let gas = call_last_frame_return(ctx, InstructionResult::Stop, Gas::new(90)); assert_eq!(gas.remaining(), 0); assert_eq!(gas.spent(), 100); @@ -586,7 +586,7 @@ mod tests { .is_system_transaction() .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::BEDROCK); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::BEDROCK)); let gas = call_last_frame_return(ctx, InstructionResult::Stop, Gas::new(90)); assert_eq!(gas.remaining(), 100); assert_eq!(gas.spent(), 0); @@ -613,7 +613,7 @@ mod tests { l1_base_fee_scalar: U256::from(1_000), ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); ctx.modify_tx(|tx| { tx.deposit.source_hash = B256::from([1u8; 32]); tx.deposit.mint = Some(10); @@ -652,7 +652,7 @@ mod tests { l2_block: Some(U256::from(0)), ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)) .with_tx( OpTransaction::builder() .base(TxEnv::builder().gas_limit(100)) @@ -725,7 +725,7 @@ mod tests { number: BLOCK_NUM, ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); @@ -812,7 +812,7 @@ mod tests { number: BLOCK_NUM, ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::JOVIAN) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::JOVIAN)) // set the operator fee to a low value .with_tx( OpTransaction::builder() @@ -880,7 +880,7 @@ mod tests { number: BLOCK_NUM, ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let mut evm = ctx.build_op(); assert_ne!(evm.ctx().chain().l2_block, Some(BLOCK_NUM)); @@ -940,7 +940,7 @@ mod tests { number: BLOCK_NUM, ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ECOTONE); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ECOTONE)); let mut evm = ctx.build_op(); assert_ne!(evm.ctx().chain().l2_block, Some(BLOCK_NUM)); @@ -1013,7 +1013,7 @@ mod tests { number: BLOCK_NUM, ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); @@ -1063,7 +1063,7 @@ mod tests { l2_block: Some(U256::from(0)), ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)) .with_tx( OpTransaction::builder() .base(TxEnv::builder().gas_limit(100)) @@ -1106,7 +1106,7 @@ mod tests { l2_block: Some(U256::from(0)), ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)) .with_tx( OpTransaction::builder() .base(TxEnv::builder().gas_limit(10)) @@ -1148,7 +1148,7 @@ mod tests { l2_block: Some(U256::from(0)), ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::JOVIAN) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::JOVIAN)) .with_tx( OpTransaction::builder() .base(TxEnv::builder().gas_limit(10)) @@ -1190,7 +1190,7 @@ mod tests { l2_block: Some(U256::from(0)), ..Default::default() }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH) + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)) .modify_tx_chained(|tx| { tx.enveloped_tx = Some(bytes!("FACADE")); }); @@ -1221,7 +1221,7 @@ mod tests { tx.deposit.source_hash = B256::from([1u8; 32]); tx.deposit.is_system_transaction = true; }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let mut evm = ctx.build_op(); let handler = @@ -1234,7 +1234,11 @@ mod tests { )) ); - evm.ctx().modify_cfg(|cfg| cfg.spec = OpSpecId::BEDROCK); + // With BEDROCK spec. + let ctx = evm.into_context(); + let mut evm = ctx + .with_cfg(CfgEnv::new_with_spec(OpSpecId::BEDROCK)) + .build_op(); // Pre-regolith system transactions should be allowed. assert!(handler.validate_env(&mut evm).is_ok()); @@ -1247,7 +1251,7 @@ mod tests { .modify_tx_chained(|tx| { tx.deposit.source_hash = B256::from([1u8; 32]); }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let mut evm = ctx.build_op(); let handler = @@ -1263,7 +1267,7 @@ mod tests { .modify_tx_chained(|tx| { tx.deposit.source_hash = B256::from([1u8; 32]); }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let mut evm = ctx.build_op(); let handler = @@ -1280,7 +1284,7 @@ mod tests { // Set up as deposit transaction by having a deposit with source_hash tx.deposit.source_hash = B256::from([1u8; 32]); }) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::REGOLITH); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::REGOLITH)); let mut evm = ctx.build_op(); let mut handler = @@ -1363,7 +1367,7 @@ mod tests { }) .build_fill(), ) - .modify_cfg_chained(|cfg| cfg.spec = OpSpecId::ISTHMUS); + .with_cfg(CfgEnv::new_with_spec(OpSpecId::ISTHMUS)); let mut evm = ctx.build_op(); let handler = diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index 3c86904b47..325796f4da 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -11,11 +11,9 @@ use crate::{ OpSpecId, }; use revm::{ + context_interface::cfg::gas::{NON_ZERO_BYTE_MULTIPLIER_ISTANBUL, STANDARD_TOKEN_COST}, database_interface::Database, - interpreter::{ - gas::{get_tokens_in_calldata, NON_ZERO_BYTE_MULTIPLIER_ISTANBUL, STANDARD_TOKEN_COST}, - Gas, - }, + interpreter::{gas::get_tokens_in_calldata, Gas}, primitives::U256, }; diff --git a/crates/state/src/bal.rs b/crates/state/src/bal.rs index 3f713d87c4..bdaaa6953b 100644 --- a/crates/state/src/bal.rs +++ b/crates/state/src/bal.rs @@ -240,3 +240,5 @@ impl core::fmt::Display for BalError { } } } + +impl core::error::Error for BalError {} diff --git a/crates/statetest-types/src/test_unit.rs b/crates/statetest-types/src/test_unit.rs index c09f720fb1..ec11eb7acf 100644 --- a/crates/statetest-types/src/test_unit.rs +++ b/crates/statetest-types/src/test_unit.rs @@ -120,7 +120,7 @@ impl TestUnit { } // Set default prevrandao for merge - if cfg.spec.is_enabled_in(SpecId::MERGE) && block.prevrandao.is_none() { + if cfg.spec().is_enabled_in(SpecId::MERGE) && block.prevrandao.is_none() { block.prevrandao = Some(B256::default()); } @@ -184,8 +184,7 @@ mod tests { fn test_block_env_blob_fee_fraction_cancun() { let unit = create_test_unit_with_excess_blob_gas(0x240000); // 2,359,296 - let mut cfg = CfgEnv::default(); - cfg.spec = SpecId::CANCUN; + let mut cfg = CfgEnv::new_with_spec(SpecId::CANCUN); let block = unit.block_env(&mut cfg); @@ -208,8 +207,7 @@ mod tests { fn test_block_env_blob_fee_fraction_prague() { let unit = create_test_unit_with_excess_blob_gas(0x240000); // 2,359,296 - let mut cfg = CfgEnv::default(); - cfg.spec = SpecId::PRAGUE; + let mut cfg = CfgEnv::new_with_spec(SpecId::PRAGUE); let block = unit.block_env(&mut cfg); @@ -231,8 +229,7 @@ mod tests { fn test_block_env_blob_fee_fraction_osaka() { let unit = create_test_unit_with_excess_blob_gas(0x240000); // 2,359,296 - let mut cfg = CfgEnv::default(); - cfg.spec = SpecId::OSAKA; + let mut cfg = CfgEnv::new_with_spec(SpecId::OSAKA); let block = unit.block_env(&mut cfg); diff --git a/examples/erc20_gas/src/main.rs b/examples/erc20_gas/src/main.rs index 9518b3830d..8724cdc038 100644 --- a/examples/erc20_gas/src/main.rs +++ b/examples/erc20_gas/src/main.rs @@ -9,7 +9,7 @@ use alloy_sol_types::SolValue; use anyhow::Result; use exec::transact_erc20evm_commit; use revm::{ - context::TxEnv, + context::{CfgEnv, TxEnv}, database::{AlloyDB, BlockId, CacheDB}, database_interface::WrapDatabaseAsync, primitives::{address, hardfork::SpecId, keccak256, Address, StorageValue, TxKind, U256}, @@ -81,9 +81,7 @@ fn balance_of(address: Address, alloy_db: &mut AlloyCacheDB) -> Result Result<()> { let mut ctx = Context::mainnet() .with_db(cache_db) - .modify_cfg_chained(|cfg| { - cfg.spec = SpecId::CANCUN; - }) + .with_cfg(CfgEnv::new_with_spec(SpecId::CANCUN)) .with_tx( TxEnv::builder() .caller(from) From 281c6ad03f39f85bf5e79216fd9cce229ce9abeb Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 8 Jan 2026 11:45:58 +0100 Subject: [PATCH 108/127] feat: new gas params, tx initial gas and codedeposit (#3260) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: move GasParams to Cfg * propagate spec id * use cfg spec when evm is created * nits * nit * doc tests * use derive-where to skip fn * Move SetSpecTr and use it as main tr * feat: add codedeposit price in GasParams * remove SetSpecTr, introduce is_custom_gas_param flag * simplification * nits and tests fix * morf spec type * dont compare ptr * import fix * typo * ref alloy-eips * add core::error::Error impl to BalError 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 * send/sync on GasParams * relex generic for some Cfg functions * load_account_mut_skip_cold * WIP * move initial tx gas calc to GasParams * fixes --------- Co-authored-by: Claude Opus 4.5 --- crates/context/interface/src/cfg/gas.rs | 127 +------ .../context/interface/src/cfg/gas_params.rs | 341 +++++++++++++++++- crates/context/interface/src/context.rs | 7 + crates/context/interface/src/host.rs | 2 +- .../context/interface/src/journaled_state.rs | 9 +- crates/context/src/journal.rs | 11 + crates/handler/src/frame.rs | 26 +- crates/handler/src/validation.rs | 4 +- crates/interpreter/src/gas.rs | 4 +- crates/interpreter/src/gas/calc.rs | 156 -------- crates/interpreter/src/lib.rs | 3 +- crates/op-revm/src/l1block.rs | 4 +- examples/cheatcode_inspector/src/main.rs | 9 + 13 files changed, 399 insertions(+), 304 deletions(-) delete mode 100644 crates/interpreter/src/gas/calc.rs diff --git a/crates/context/interface/src/cfg/gas.rs b/crates/context/interface/src/cfg/gas.rs index 5b122b7657..fc3762f299 100644 --- a/crates/context/interface/src/cfg/gas.rs +++ b/crates/context/interface/src/cfg/gas.rs @@ -1,7 +1,7 @@ //! Gas constants and functions for gas calculation. -use crate::{transaction::AccessListItemTr as _, Transaction, TransactionType}; -use primitives::{eip7702, hardfork::SpecId, U256}; +use crate::{cfg::GasParams, transaction::AccessListItemTr as _, Transaction, TransactionType}; +use primitives::hardfork::SpecId; /// Gas cost for operations that consume zero gas. pub const ZERO: u64 = 0; @@ -107,57 +107,6 @@ pub const INITCODE_WORD_COST: u64 = 2; /// Gas stipend provided to the recipient of a CALL with value transfer. pub const CALL_STIPEND: u64 = 2300; -#[inline] -pub(crate) const fn log2floor(value: U256) -> u64 { - let mut l: u64 = 256; - let mut i = 3; - loop { - if value.as_limbs()[i] == 0u64 { - l -= 64; - } else { - l -= value.as_limbs()[i].leading_zeros() as u64; - if l == 0 { - return l; - } else { - return l - 1; - } - } - if i == 0 { - break; - } - i -= 1; - } - l -} - -/// Calculate the cost of buffer per word. -#[inline] -pub const fn cost_per_word(len: usize, multiple: u64) -> Option { - multiple.checked_mul(num_words(len) as u64) -} - -/// EIP-3860: Limit and meter initcode -/// -/// Apply extra gas cost of 2 for every 32-byte chunk of initcode. -/// -/// This cannot overflow as the initcode length is assumed to be checked. -#[inline] -pub const fn initcode_cost(len: usize) -> u64 { - let Some(cost) = cost_per_word(len, INITCODE_WORD_COST) else { - panic!("initcode cost overflow") - }; - cost -} - -/// Memory expansion cost calculation for a given number of words. -#[inline] -pub const fn memory_gas(num_words: usize, linear_cost: u64, quadratic_cost: u64) -> u64 { - let num_words = num_words as u64; - linear_cost - .saturating_mul(num_words) - .saturating_add(num_words.saturating_mul(num_words) / quadratic_cost) -} - /// Init and floor gas from transaction #[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -195,44 +144,13 @@ pub fn calculate_initial_tx_gas( access_list_storages: u64, authorization_list_num: u64, ) -> InitialAndFloorGas { - let mut gas = InitialAndFloorGas::default(); - - // Initdate stipend - let tokens_in_calldata = get_tokens_in_calldata(input, spec_id.is_enabled_in(SpecId::ISTANBUL)); - - gas.initial_gas += tokens_in_calldata * STANDARD_TOKEN_COST; - - // Get number of access list account and storages. - gas.initial_gas += access_list_accounts * ACCESS_LIST_ADDRESS; - gas.initial_gas += access_list_storages * ACCESS_LIST_STORAGE_KEY; - - // Base stipend - gas.initial_gas += if is_create { - if spec_id.is_enabled_in(SpecId::HOMESTEAD) { - // EIP-2: Homestead Hard-fork Changes - 53000 - } else { - 21000 - } - } else { - 21000 - }; - - // EIP-3860: Limit and meter initcode - // Init code stipend for bytecode analysis - if spec_id.is_enabled_in(SpecId::SHANGHAI) && is_create { - gas.initial_gas += initcode_cost(input.len()) - } - - // EIP-7702 - if spec_id.is_enabled_in(SpecId::PRAGUE) { - gas.initial_gas += authorization_list_num * eip7702::PER_EMPTY_ACCOUNT_COST; - - // Calculate gas floor for EIP-7623 - gas.floor_gas = calc_tx_floor_cost(tokens_in_calldata); - } - - gas + GasParams::new_spec(spec_id).initial_tx_gas( + input, + is_create, + access_list_accounts, + access_list_storages, + authorization_list_num, + ) } /// Initial gas that is deducted for transaction to be included. @@ -272,27 +190,14 @@ pub fn calculate_initial_tx_gas_for_tx(tx: impl Transaction, spec: SpecId) -> In /// Retrieve the total number of tokens in calldata. #[inline] -pub fn get_tokens_in_calldata(input: &[u8], is_istanbul: bool) -> u64 { - let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; - let non_zero_data_len = input.len() as u64 - zero_data_len; - let non_zero_data_multiplier = if is_istanbul { - // EIP-2028: Transaction data gas cost reduction - NON_ZERO_BYTE_MULTIPLIER_ISTANBUL - } else { - NON_ZERO_BYTE_MULTIPLIER - }; - zero_data_len + non_zero_data_len * non_zero_data_multiplier -} - -/// Calculate the transaction cost floor as specified in EIP-7623. -#[inline] -pub fn calc_tx_floor_cost(tokens_in_calldata: u64) -> u64 { - tokens_in_calldata * TOTAL_COST_FLOOR_PER_TOKEN + 21_000 +pub fn get_tokens_in_calldata_istanbul(input: &[u8]) -> u64 { + get_tokens_in_calldata(input, NON_ZERO_BYTE_MULTIPLIER_ISTANBUL) } -/// Returns number of words what would fit to provided number of bytes, -/// i.e. it rounds up the number bytes to number of words. +/// Retrieve the total number of tokens in calldata. #[inline] -pub const fn num_words(len: usize) -> usize { - len.div_ceil(32) +pub fn get_tokens_in_calldata(input: &[u8], non_zero_data_multiplier: u64) -> u64 { + let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; + let non_zero_data_len = input.len() as u64 - zero_data_len; + zero_data_len + non_zero_data_len * non_zero_data_multiplier } diff --git a/crates/context/interface/src/cfg/gas_params.rs b/crates/context/interface/src/cfg/gas_params.rs index 68e195eb49..7e59f6a027 100644 --- a/crates/context/interface/src/cfg/gas_params.rs +++ b/crates/context/interface/src/cfg/gas_params.rs @@ -1,15 +1,14 @@ //! Gas table for dynamic gas constants. use crate::{ - cfg::gas::{ - self, log2floor, num_words, ISTANBUL_SLOAD_GAS, SSTORE_RESET, SSTORE_SET, WARM_SSTORE_RESET, - }, + cfg::gas::{self, get_tokens_in_calldata, InitialAndFloorGas}, context::SStoreResult, }; use core::hash::{Hash, Hasher}; use primitives::{ + eip7702, hardfork::SpecId::{self}, - U256, + OnceLock, U256, }; use std::sync::Arc; @@ -45,6 +44,13 @@ impl core::fmt::Debug for GasParams { } } +/// Returns number of words what would fit to provided number of bytes, +/// i.e. it rounds up the number bytes to number of words. +#[inline] +pub const fn num_words(len: usize) -> usize { + len.div_ceil(32) +} + impl Eq for GasParams {} #[cfg(feature = "serde")] mod serde { @@ -85,7 +91,7 @@ mod serde { impl Default for GasParams { fn default() -> Self { - Self::new_spec(SpecId::default()) + Self::new_spec(SpecId::default()).clone() } } @@ -129,8 +135,66 @@ impl GasParams { } /// Creates a new `GasParams` for the given spec. - #[inline] + #[inline(never)] pub fn new_spec(spec: SpecId) -> Self { + use SpecId::*; + let gas_params = match spec { + FRONTIER | FRONTIER_THAWING => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // Transaction creation cost was added in homestead fork. + HOMESTEAD | DAO_FORK => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // New account cost for selfdestruct was added in tangerine fork. + TANGERINE => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // EXP cost was increased in spurious dragon fork. + SPURIOUS_DRAGON | BYZANTIUM | CONSTANTINOPLE | PETERSBURG => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // SSTORE gas calculation changed in istanbul fork. + ISTANBUL | MUIR_GLACIER => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // Warm/cold state access + BERLIN => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // Refund reduction in london fork. + LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // Transaction initcode cost was introduced in shanghai fork. + SHANGHAI | CANCUN => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // EIP-7702 was introduced in prague fork. + PRAGUE | OSAKA => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + // New fork. + SpecId::AMSTERDAM => { + static TABLE: OnceLock = OnceLock::new(); + TABLE.get_or_init(|| Self::new_spec_inner(spec)) + } + }; + gas_params.clone() + } + + /// Creates a new `GasParams` for the given spec. + #[inline] + fn new_spec_inner(spec: SpecId) -> Self { let mut table = [0; 256]; table[GasId::exp_byte_gas().as_usize()] = 10; @@ -150,9 +214,10 @@ impl GasParams { table[GasId::new_account_cost().as_usize()] = gas::NEWACCOUNT; table[GasId::warm_storage_read_cost().as_usize()] = 0; // Frontiers had fixed 5k cost. - table[GasId::sstore_static().as_usize()] = SSTORE_RESET; + table[GasId::sstore_static().as_usize()] = gas::SSTORE_RESET; // SSTORE SET - table[GasId::sstore_set_without_load_cost().as_usize()] = SSTORE_SET - SSTORE_RESET; + table[GasId::sstore_set_without_load_cost().as_usize()] = + gas::SSTORE_SET - gas::SSTORE_RESET; // SSTORE RESET Is covered in SSTORE_STATIC. table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = 0; // SSTORE CLEARING SLOT REFUND @@ -162,6 +227,15 @@ impl GasParams { table[GasId::cold_storage_additional_cost().as_usize()] = 0; table[GasId::cold_storage_cost().as_usize()] = 0; table[GasId::new_account_cost_for_selfdestruct().as_usize()] = 0; + table[GasId::code_deposit_cost().as_usize()] = gas::CODEDEPOSIT; + table[GasId::tx_token_non_zero_byte_multiplier().as_usize()] = + gas::NON_ZERO_BYTE_MULTIPLIER; + table[GasId::tx_token_cost().as_usize()] = gas::STANDARD_TOKEN_COST; + table[GasId::tx_base_stipend().as_usize()] = 21000; + + if spec.is_enabled_in(SpecId::HOMESTEAD) { + table[GasId::tx_create_cost().as_usize()] = gas::CREATE; + } if spec.is_enabled_in(SpecId::TANGERINE) { table[GasId::new_account_cost_for_selfdestruct().as_usize()] = gas::NEWACCOUNT; @@ -174,9 +248,11 @@ impl GasParams { if spec.is_enabled_in(SpecId::ISTANBUL) { table[GasId::sstore_static().as_usize()] = gas::ISTANBUL_SLOAD_GAS; table[GasId::sstore_set_without_load_cost().as_usize()] = - SSTORE_SET - ISTANBUL_SLOAD_GAS; + gas::SSTORE_SET - gas::ISTANBUL_SLOAD_GAS; table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = - SSTORE_RESET - ISTANBUL_SLOAD_GAS; + gas::SSTORE_RESET - gas::ISTANBUL_SLOAD_GAS; + table[GasId::tx_token_non_zero_byte_multiplier().as_usize()] = + gas::NON_ZERO_BYTE_MULTIPLIER_ISTANBUL; } if spec.is_enabled_in(SpecId::BERLIN) { @@ -189,9 +265,13 @@ impl GasParams { table[GasId::warm_storage_read_cost().as_usize()] = gas::WARM_STORAGE_READ_COST; table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = - WARM_SSTORE_RESET - gas::WARM_STORAGE_READ_COST; + gas::WARM_SSTORE_RESET - gas::WARM_STORAGE_READ_COST; table[GasId::sstore_set_without_load_cost().as_usize()] = - SSTORE_SET - gas::WARM_STORAGE_READ_COST; + gas::SSTORE_SET - gas::WARM_STORAGE_READ_COST; + + table[GasId::tx_access_list_address_cost().as_usize()] = gas::ACCESS_LIST_ADDRESS; + table[GasId::tx_access_list_storage_key_cost().as_usize()] = + gas::ACCESS_LIST_STORAGE_KEY; } if spec.is_enabled_in(SpecId::LONDON) { @@ -200,11 +280,23 @@ impl GasParams { // Replace SSTORE_CLEARS_SCHEDULE (as defined in EIP-2200) with // SSTORE_RESET_GAS + ACCESS_LIST_STORAGE_KEY_COST (4,800 gas as of EIP-2929 + EIP-2930) table[GasId::sstore_clearing_slot_refund().as_usize()] = - WARM_SSTORE_RESET + gas::ACCESS_LIST_STORAGE_KEY; + gas::WARM_SSTORE_RESET + gas::ACCESS_LIST_STORAGE_KEY; table[GasId::selfdestruct_refund().as_usize()] = 0; } + if spec.is_enabled_in(SpecId::SHANGHAI) { + table[GasId::tx_initcode_cost().as_usize()] = gas::INITCODE_WORD_COST; + } + + if spec.is_enabled_in(SpecId::PRAGUE) { + table[GasId::tx_eip7702_per_empty_account_cost().as_usize()] = + eip7702::PER_EMPTY_ACCOUNT_COST; + + table[GasId::tx_floor_cost_per_token().as_usize()] = gas::TOTAL_COST_FLOOR_PER_TOKEN; + table[GasId::tx_floor_cost_base_gas().as_usize()] = 21000; + } + Self::new(Arc::new(table)) } @@ -508,6 +600,146 @@ impl GasParams { self.get(GasId::copy_per_word()) .saturating_mul(word_num as u64) } + + /// Code deposit cost, calculated per byte as len * code_deposit_cost. + #[inline] + pub fn code_deposit_cost(&self, len: usize) -> u64 { + self.get(GasId::code_deposit_cost()) + .saturating_mul(len as u64) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the eip7702 per empty account cost. + #[inline] + pub fn tx_eip7702_per_empty_account_cost(&self) -> u64 { + self.get(GasId::tx_eip7702_per_empty_account_cost()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the token non zero byte multiplier. + #[inline] + pub fn tx_token_non_zero_byte_multiplier(&self) -> u64 { + self.get(GasId::tx_token_non_zero_byte_multiplier()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the token cost for input data. + #[inline] + pub fn tx_token_cost(&self) -> u64 { + self.get(GasId::tx_token_cost()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the floor gas per token. + pub fn tx_floor_cost_per_token(&self) -> u64 { + self.get(GasId::tx_floor_cost_per_token()) + } + + /// Used [GasParams::initial_tx_gas] to calculate the floor gas. + /// + /// Floor gas is introduced in EIP-7623. + #[inline] + pub fn tx_floor_cost(&self, tokens_in_calldata: u64) -> u64 { + self.tx_floor_cost_per_token() * tokens_in_calldata + self.tx_floor_cost_base_gas() + } + + /// Used in [GasParams::initial_tx_gas] to calculate the floor gas base gas. + pub fn tx_floor_cost_base_gas(&self) -> u64 { + self.get(GasId::tx_floor_cost_base_gas()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the access list address cost. + pub fn tx_access_list_address_cost(&self) -> u64 { + self.get(GasId::tx_access_list_address_cost()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the access list storage key cost. + pub fn tx_access_list_storage_key_cost(&self) -> u64 { + self.get(GasId::tx_access_list_storage_key_cost()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the base transaction stipend. + pub fn tx_base_stipend(&self) -> u64 { + self.get(GasId::tx_base_stipend()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the create cost. + /// + /// Similar to the [`Self::create_cost`] method but it got activated in different fork, + #[inline] + pub fn tx_create_cost(&self) -> u64 { + self.get(GasId::tx_create_cost()) + } + + /// Used in [GasParams::initial_tx_gas] to calculate the initcode cost per word of len. + #[inline] + pub fn tx_initcode_cost(&self, len: usize) -> u64 { + self.get(GasId::tx_initcode_cost()) + .saturating_mul(num_words(len) as u64) + } + + /// Initial gas that is deducted for transaction to be included. + /// Initial gas contains initial stipend gas, gas for access list and input data. + /// + /// # Returns + /// + /// - Intrinsic gas + /// - Number of tokens in calldata + pub fn initial_tx_gas( + &self, + input: &[u8], + is_create: bool, + access_list_accounts: u64, + access_list_storages: u64, + authorization_list_num: u64, + ) -> InitialAndFloorGas { + let mut gas = InitialAndFloorGas::default(); + + // Initdate stipend + let tokens_in_calldata = + get_tokens_in_calldata(input, self.tx_token_non_zero_byte_multiplier()); + + gas.initial_gas += tokens_in_calldata * self.tx_token_cost() + // before berlin tx_access_list_address_cost will be zero + + access_list_accounts * self.tx_access_list_address_cost() + // before berlin tx_access_list_storage_key_cost will be zero + + access_list_storages * self.tx_access_list_storage_key_cost() + + self.tx_base_stipend() + // EIP-7702: Authorization list + + authorization_list_num * self.tx_eip7702_per_empty_account_cost(); + + if is_create { + // EIP-2: Homestead Hard-fork Changes + gas.initial_gas += self.tx_create_cost(); + + // EIP-3860: Limit and meter initcode + gas.initial_gas += self.tx_initcode_cost(input.len()); + } + + // Calculate gas floor for EIP-7623 + gas.floor_gas = self.tx_floor_cost(tokens_in_calldata); + + gas + } +} + +#[inline] +pub(crate) const fn log2floor(value: U256) -> u64 { + let mut l: u64 = 256; + let mut i = 3; + loop { + if value.as_limbs()[i] == 0u64 { + l -= 64; + } else { + l -= value.as_limbs()[i].leading_zeros() as u64; + if l == 0 { + return l; + } else { + return l - 1; + } + } + if i == 0 { + break; + } + i -= 1; + } + l } /// Gas identifier that maps onto index in gas table. @@ -578,6 +810,23 @@ impl GasId { x if x == Self::new_account_cost_for_selfdestruct().as_u8() => { "new_account_cost_for_selfdestruct" } + x if x == Self::code_deposit_cost().as_u8() => "code_deposit_cost", + x if x == Self::tx_eip7702_per_empty_account_cost().as_u8() => { + "tx_eip7702_per_empty_account_cost" + } + x if x == Self::tx_token_non_zero_byte_multiplier().as_u8() => { + "tx_token_non_zero_byte_multiplier" + } + x if x == Self::tx_token_cost().as_u8() => "tx_token_cost", + x if x == Self::tx_floor_cost_per_token().as_u8() => "tx_floor_cost_per_token", + x if x == Self::tx_floor_cost_base_gas().as_u8() => "tx_floor_cost_base_gas", + x if x == Self::tx_access_list_address_cost().as_u8() => "tx_access_list_address_cost", + x if x == Self::tx_access_list_storage_key_cost().as_u8() => { + "tx_access_list_storage_key_cost" + } + x if x == Self::tx_base_stipend().as_u8() => "tx_base_stipend", + x if x == Self::tx_create_cost().as_u8() => "tx_create_cost", + x if x == Self::tx_initcode_cost().as_u8() => "tx_initcode_cost", _ => "unknown", } } @@ -624,6 +873,17 @@ impl GasId { "cold_storage_additional_cost" => Some(Self::cold_storage_additional_cost()), "cold_storage_cost" => Some(Self::cold_storage_cost()), "new_account_cost_for_selfdestruct" => Some(Self::new_account_cost_for_selfdestruct()), + "code_deposit_cost" => Some(Self::code_deposit_cost()), + "eip7702_per_empty_account_cost" => Some(Self::tx_eip7702_per_empty_account_cost()), + "tx_token_non_zero_byte_multiplier" => Some(Self::tx_token_non_zero_byte_multiplier()), + "tx_token_cost" => Some(Self::tx_token_cost()), + "tx_floor_cost_per_token" => Some(Self::tx_floor_cost_per_token()), + "tx_floor_cost_base_gas" => Some(Self::tx_floor_cost_base_gas()), + "tx_access_list_address_cost" => Some(Self::tx_access_list_address_cost()), + "tx_access_list_storage_key_cost" => Some(Self::tx_access_list_storage_key_cost()), + "tx_base_stipend" => Some(Self::tx_base_stipend()), + "tx_create_cost" => Some(Self::tx_create_cost()), + "tx_initcode_cost" => Some(Self::tx_initcode_cost()), _ => None, } } @@ -755,6 +1015,61 @@ impl GasId { pub const fn new_account_cost_for_selfdestruct() -> GasId { Self::new(25) } + + /// Code deposit cost. Calculated as len * code_deposit_cost. + pub const fn code_deposit_cost() -> GasId { + Self::new(26) + } + + /// EIP-7702 PER_EMPTY_ACCOUNT_COST gas + pub const fn tx_eip7702_per_empty_account_cost() -> GasId { + Self::new(27) + } + + /// Initial tx gas token non zero byte multiplier. + pub const fn tx_token_non_zero_byte_multiplier() -> GasId { + Self::new(28) + } + + /// Initial tx gas token cost. + pub const fn tx_token_cost() -> GasId { + Self::new(29) + } + + /// Initial tx gas floor cost per token. + pub const fn tx_floor_cost_per_token() -> GasId { + Self::new(30) + } + + /// Initial tx gas floor cost base gas. + pub const fn tx_floor_cost_base_gas() -> GasId { + Self::new(31) + } + + /// Initial tx gas access list address cost. + pub const fn tx_access_list_address_cost() -> GasId { + Self::new(32) + } + + /// Initial tx gas access list storage key cost. + pub const fn tx_access_list_storage_key_cost() -> GasId { + Self::new(33) + } + + /// Initial tx gas base stipend. + pub const fn tx_base_stipend() -> GasId { + Self::new(34) + } + + /// Initial tx gas create cost. + pub const fn tx_create_cost() -> GasId { + Self::new(35) + } + + /// Initial tx gas initcode cost per word. + pub const fn tx_initcode_cost() -> GasId { + Self::new(36) + } } #[cfg(test)] diff --git a/crates/context/interface/src/context.rs b/crates/context/interface/src/context.rs index 014dcf85e1..d544e1cff4 100644 --- a/crates/context/interface/src/context.rs +++ b/crates/context/interface/src/context.rs @@ -152,6 +152,13 @@ pub trait ContextTr: Host { let (_, tx, _, _, _, local) = self.all_mut(); (tx, local) } + + /// Get the configuration and journal mutably + #[inline] + fn cfg_journal_mut(&mut self) -> (&Self::Cfg, &mut Self::Journal) { + let (_, _, cfg, journal, _, _) = self.all_mut(); + (cfg, journal) + } } /// Inner Context error used for Interpreter to set error without returning it from instruction diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index e4efb22081..d3fb01ca58 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -213,7 +213,7 @@ impl DummyHost { /// Create a new dummy host with the given spec. pub fn new(spec: SpecId) -> Self { Self { - gas_params: GasParams::new_spec(spec), + gas_params: GasParams::new_spec(spec).clone(), } } } diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 7edc224ae8..33c085a705 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -189,9 +189,16 @@ pub trait JournalTr { &mut self, address: Address, ) -> Result>, ::Error> { - self.load_account_mut_optional_code(address, false) + self.load_account_mut_skip_cold_load(address, false) } + /// Loads the journaled account. + fn load_account_mut_skip_cold_load( + &mut self, + address: Address, + skip_cold_load: bool, + ) -> Result>, ::Error>; + /// Loads the journaled account. #[inline] fn load_account_with_code_mut( diff --git a/crates/context/src/journal.rs b/crates/context/src/journal.rs index 8360261e70..6814627d10 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -256,6 +256,17 @@ impl JournalTr for Journal { self.inner.load_account(&mut self.database, address) } + #[inline] + fn load_account_mut_skip_cold_load( + &mut self, + address: Address, + skip_cold_load: bool, + ) -> Result>, DB::Error> { + self.inner + .load_account_mut_optional(&mut self.database, address, skip_cold_load) + .map_err(JournalLoadError::unwrap_db_error) + } + #[inline] fn load_account_mut_optional_code( &mut self, diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 2b3ced2c1b..f5aea40738 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -4,7 +4,6 @@ use crate::{ }; use context::result::FromStringError; use context_interface::{ - cfg::gas::CODEDEPOSIT, context::ContextError, journaled_state::{account::JournaledAccountTr, JournalCheckpoint, JournalTr}, local::{FrameToken, OutFrame}, @@ -388,8 +387,6 @@ impl EthFrame { context: &mut CTX, next_action: InterpreterAction, ) -> Result, ERROR> { - let spec = context.cfg().spec().into(); - // Run interpreter let mut interpreter_result = match next_action { @@ -420,16 +417,13 @@ impl EthFrame { ))) } FrameData::Create(frame) => { - let max_code_size = context.cfg().max_code_size(); - let is_eip3541_disabled = context.cfg().is_eip3541_disabled(); + let (cfg, journal) = context.cfg_journal_mut(); return_create( - context.journal_mut(), + journal, + cfg, self.checkpoint, &mut interpreter_result, frame.created_address, - max_code_size, - is_eip3541_disabled, - spec, ); ItemOrResult::Result(FrameResult::Create(CreateOutcome::new( @@ -535,15 +529,17 @@ impl EthFrame { } /// Handles the result of a CREATE operation, including validation and state updates. -pub fn return_create( +pub fn return_create( journal: &mut JOURNAL, + cfg: CFG, checkpoint: JournalCheckpoint, interpreter_result: &mut InterpreterResult, address: Address, - max_code_size: usize, - is_eip3541_disabled: bool, - spec_id: SpecId, ) { + let max_code_size = cfg.max_code_size(); + let is_eip3541_disabled = cfg.is_eip3541_disabled(); + let spec_id = cfg.spec().into(); + // If return is not ok revert and return. if !interpreter_result.result.is_ok() { journal.checkpoint_revert(checkpoint); @@ -569,7 +565,9 @@ pub fn return_create( interpreter_result.result = InstructionResult::CreateContractSizeLimit; return; } - let gas_for_code = interpreter_result.output.len() as u64 * CODEDEPOSIT; + let gas_for_code = cfg + .gas_params() + .code_deposit_cost(interpreter_result.output.len()); if !interpreter_result.gas.record_cost(gas_for_code) { // Record code deposit gas cost and check if we are out of gas. // EIP-2 point 3: If contract creation does not have enough gas to pay for the diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index d038cd3f87..569ff23784 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -4,7 +4,7 @@ use context_interface::{ Block, Cfg, ContextTr, }; use core::cmp; -use interpreter::gas::{self, InitialAndFloorGas}; +use interpreter::{instructions::calculate_initial_tx_gas_for_tx, InitialAndFloorGas}; use primitives::{eip4844, hardfork::SpecId, B256}; /// Validates the execution environment including block and transaction parameters. @@ -230,7 +230,7 @@ pub fn validate_initial_tx_gas( spec: SpecId, is_eip7623_disabled: bool, ) -> Result { - let mut gas = gas::calculate_initial_tx_gas_for_tx(&tx, spec); + let mut gas = calculate_initial_tx_gas_for_tx(&tx, spec); if is_eip7623_disabled { gas.floor_gas = 0 diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index 68dbc24103..d862ab9499 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -1,8 +1,6 @@ //! EVM gas calculation utilities. -mod calc; - -pub use calc::*; +pub use context_interface::cfg::gas::*; /// Represents the state of gas during execution. #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs deleted file mode 100644 index ef4e79469b..0000000000 --- a/crates/interpreter/src/gas/calc.rs +++ /dev/null @@ -1,156 +0,0 @@ -use crate::num_words; -use context_interface::{ - cfg::gas::*, transaction::AccessListItemTr as _, Transaction, TransactionType, -}; -use primitives::{eip7702, hardfork::SpecId}; - -/// Calculate the cost of buffer per word. -#[inline] -pub const fn cost_per_word(len: usize, multiple: u64) -> Option { - multiple.checked_mul(num_words(len) as u64) -} - -/// EIP-3860: Limit and meter initcode -/// -/// Apply extra gas cost of 2 for every 32-byte chunk of initcode. -/// -/// This cannot overflow as the initcode length is assumed to be checked. -#[inline] -pub const fn initcode_cost(len: usize) -> u64 { - let Some(cost) = cost_per_word(len, INITCODE_WORD_COST) else { - panic!("initcode cost overflow") - }; - cost -} - -/// Init and floor gas from transaction -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct InitialAndFloorGas { - /// Initial gas for transaction. - pub initial_gas: u64, - /// If transaction is a Call and Prague is enabled - /// floor_gas is at least amount of gas that is going to be spent. - pub floor_gas: u64, -} - -impl InitialAndFloorGas { - /// Create a new InitialAndFloorGas instance. - #[inline] - pub const fn new(initial_gas: u64, floor_gas: u64) -> Self { - Self { - initial_gas, - floor_gas, - } - } -} - -/// Initial gas that is deducted for transaction to be included. -/// Initial gas contains initial stipend gas, gas for access list and input data. -/// -/// # Returns -/// -/// - Intrinsic gas -/// - Number of tokens in calldata -pub fn calculate_initial_tx_gas( - spec_id: SpecId, - input: &[u8], - is_create: bool, - access_list_accounts: u64, - access_list_storages: u64, - authorization_list_num: u64, -) -> InitialAndFloorGas { - let mut gas = InitialAndFloorGas::default(); - - // Initdate stipend - let tokens_in_calldata = get_tokens_in_calldata(input, spec_id.is_enabled_in(SpecId::ISTANBUL)); - - gas.initial_gas += tokens_in_calldata * STANDARD_TOKEN_COST; - - // Get number of access list account and storages. - gas.initial_gas += access_list_accounts * ACCESS_LIST_ADDRESS; - gas.initial_gas += access_list_storages * ACCESS_LIST_STORAGE_KEY; - - // Base stipend - gas.initial_gas += if is_create { - if spec_id.is_enabled_in(SpecId::HOMESTEAD) { - // EIP-2: Homestead Hard-fork Changes - 53000 - } else { - 21000 - } - } else { - 21000 - }; - - // EIP-3860: Limit and meter initcode - // Init code stipend for bytecode analysis - if spec_id.is_enabled_in(SpecId::SHANGHAI) && is_create { - gas.initial_gas += initcode_cost(input.len()) - } - - // EIP-7702 - if spec_id.is_enabled_in(SpecId::PRAGUE) { - gas.initial_gas += authorization_list_num * eip7702::PER_EMPTY_ACCOUNT_COST; - - // Calculate gas floor for EIP-7623 - gas.floor_gas = calc_tx_floor_cost(tokens_in_calldata); - } - - gas -} - -/// Initial gas that is deducted for transaction to be included. -/// Initial gas contains initial stipend gas, gas for access list and input data. -/// -/// # Returns -/// -/// - Intrinsic gas -/// - Number of tokens in calldata -pub fn calculate_initial_tx_gas_for_tx(tx: impl Transaction, spec: SpecId) -> InitialAndFloorGas { - let mut accounts = 0; - let mut storages = 0; - // legacy is only tx type that does not have access list. - if tx.tx_type() != TransactionType::Legacy { - (accounts, storages) = tx - .access_list() - .map(|al| { - al.fold((0, 0), |(mut num_accounts, mut num_storage_slots), item| { - num_accounts += 1; - num_storage_slots += item.storage_slots().count(); - - (num_accounts, num_storage_slots) - }) - }) - .unwrap_or_default(); - } - - calculate_initial_tx_gas( - spec, - tx.input(), - tx.kind().is_create(), - accounts as u64, - storages as u64, - tx.authorization_list_len() as u64, - ) -} - -/// Retrieve the total number of tokens in calldata. -#[inline] -pub fn get_tokens_in_calldata(input: &[u8], is_istanbul: bool) -> u64 { - let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; - let non_zero_data_len = input.len() as u64 - zero_data_len; - let non_zero_data_multiplier = if is_istanbul { - // EIP-2028: Transaction data gas cost reduction - NON_ZERO_BYTE_MULTIPLIER_ISTANBUL - } else { - NON_ZERO_BYTE_MULTIPLIER - }; - zero_data_len + non_zero_data_len * non_zero_data_multiplier -} - -/// Calculate the transaction cost floor as specified in EIP-7623. -#[inline] -pub fn calc_tx_floor_cost(tokens_in_calldata: u64) -> u64 { - tokens_in_calldata * TOTAL_COST_FLOOR_PER_TOKEN + 21_000 -} diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 675554b623..dc4f546424 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -27,10 +27,11 @@ pub mod interpreter_types; // Reexport primary types. pub use context_interface::{ + cfg::gas::InitialAndFloorGas, context::{SStoreResult, SelfDestructResult, StateLoad}, host, CreateScheme, Host, }; -pub use gas::{Gas, InitialAndFloorGas}; +pub use gas::Gas; pub use instruction_context::InstructionContext; pub use instruction_result::*; pub use instructions::{instruction_table, Instruction, InstructionTable}; diff --git a/crates/op-revm/src/l1block.rs b/crates/op-revm/src/l1block.rs index 325796f4da..eff2ab0a53 100644 --- a/crates/op-revm/src/l1block.rs +++ b/crates/op-revm/src/l1block.rs @@ -13,7 +13,7 @@ use crate::{ use revm::{ context_interface::cfg::gas::{NON_ZERO_BYTE_MULTIPLIER_ISTANBUL, STANDARD_TOKEN_COST}, database_interface::Database, - interpreter::{gas::get_tokens_in_calldata, Gas}, + interpreter::{gas::get_tokens_in_calldata_istanbul, Gas}, primitives::U256, }; @@ -234,7 +234,7 @@ impl L1BlockInfo { }; // tokens in calldata where non-zero bytes are priced 4 times higher than zero bytes (Same as in Istanbul). - let mut tokens_in_transaction_data = get_tokens_in_calldata(input, true); + let mut tokens_in_transaction_data = get_tokens_in_calldata_istanbul(input); // Prior to regolith, an extra 68 non zero bytes were included in the rollup data costs. if !spec_id.is_enabled_in(OpSpecId::REGOLITH) { diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index cbe0007aaa..71d5b67690 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -292,6 +292,15 @@ impl JournalTr for Backend { .sstore_skip_cold_load(address, key, value, skip_cold_load) } + fn load_account_mut_skip_cold_load( + &mut self, + address: Address, + skip_cold_load: bool, + ) -> Result>, Infallible> { + self.journaled_state + .load_account_mut_skip_cold_load(address, skip_cold_load) + } + fn load_account_info_skip_cold_load( &mut self, address: Address, From b336d9dce0af069cd063d5ded0b9c51935f4a969 Mon Sep 17 00:00:00 2001 From: Haythem Sellami <17862704+haythemsellami@users.noreply.github.com> Date: Thu, 8 Jan 2026 18:07:16 +0700 Subject: [PATCH 109/127] fix(database): make DatabaseCommit dyn-compatible (#3264) * fix(database): make DatabaseCommit dyn-compatible * fix performance & improve API * fix(database): make DatabaseCommit dyn-compatible by changing commit_iter to use &mut dyn Iterator --- crates/database/interface/src/lib.rs | 89 ++++++++++++++++++++++++++-- crates/database/src/states/state.rs | 2 +- 2 files changed, 86 insertions(+), 5 deletions(-) diff --git a/crates/database/interface/src/lib.rs b/crates/database/interface/src/lib.rs index 6a2427e609..140d0298ef 100644 --- a/crates/database/interface/src/lib.rs +++ b/crates/database/interface/src/lib.rs @@ -84,6 +84,11 @@ pub trait Database { } /// EVM database commit interface. +/// +/// # Dyn Compatibility +/// +/// This trait is dyn-compatible. The `commit_iter` method uses `&mut dyn Iterator` +/// which allows it to be called on trait objects while remaining in the vtable. #[auto_impl(&mut, Box)] pub trait DatabaseCommit { /// Commit changes to the database. @@ -94,12 +99,33 @@ pub trait DatabaseCommit { /// Implementors of [`DatabaseCommit`] should override this method when possible for efficiency. /// /// Callers should prefer using [`DatabaseCommit::commit`] when they already have a [`HashMap`]. - fn commit_iter(&mut self, changes: impl IntoIterator) { - let changes: HashMap = changes.into_iter().collect(); + /// + /// # Dyn Compatibility + /// + /// This method uses `&mut dyn Iterator` to remain object-safe and callable on trait objects. + /// For ergonomic usage with `impl IntoIterator`, use the inherent method + /// `commit_from_iter` on `dyn DatabaseCommit`. + fn commit_iter(&mut self, changes: &mut dyn Iterator) { + let changes: HashMap = changes.collect(); self.commit(changes); } } +/// Inherent implementation for `dyn DatabaseCommit` trait objects. +/// +/// This provides `commit_from_iter` as an ergonomic wrapper around the trait's +/// `commit_iter` method, accepting `impl IntoIterator` for convenience. +impl dyn DatabaseCommit { + /// Commit changes to the database with an iterator. + /// + /// This is an ergonomic wrapper that accepts `impl IntoIterator` and delegates + /// to the trait's [`commit_iter`](DatabaseCommit::commit_iter) method. + #[inline] + pub fn commit_from_iter(&mut self, changes: impl IntoIterator) { + self.commit_iter(&mut changes.into_iter()) + } +} + /// EVM database interface. /// /// Contains the same methods as [`Database`], but with `&self` receivers instead of `&mut self`. @@ -244,7 +270,7 @@ pub trait DatabaseCommitExt: Database + DatabaseCommit { // Unfortunately must collect here to short circuit on error .collect::, _>>()?; - self.commit_iter(transitions); + self.commit_iter(&mut transitions.into_iter()); Ok(()) } @@ -272,7 +298,62 @@ pub trait DatabaseCommitExt: Database + DatabaseCommit { }) .collect::, _>>()?; - self.commit_iter(transitions); + self.commit_iter(&mut transitions.into_iter()); Ok(balances) } } + +#[cfg(test)] +mod tests { + use super::*; + + /// Compile-time test that DatabaseCommit is dyn-compatible. + /// This mirrors Foundry's approach: `struct _ObjectSafe(dyn DatabaseExt);` + struct _DatabaseCommitObjectSafe(dyn DatabaseCommit); + + /// Test that dyn DatabaseCommit works correctly. + #[test] + fn test_dyn_database_commit() { + use std::collections::HashMap as StdHashMap; + + struct MockDb { + commits: Vec>, + } + + impl DatabaseCommit for MockDb { + fn commit(&mut self, changes: HashMap) { + let std_map: StdHashMap<_, _> = changes.into_iter().collect(); + self.commits.push(std_map); + } + } + + let mut db = MockDb { commits: vec![] }; + + // Test commit_iter on concrete types + let items: Vec<(Address, Account)> = vec![]; + db.commit_iter(&mut items.into_iter()); + assert_eq!(db.commits.len(), 1); + + // Test commit() on trait objects + { + let db_dyn: &mut dyn DatabaseCommit = &mut db; + db_dyn.commit(HashMap::default()); + } + assert_eq!(db.commits.len(), 2); + + // Test commit_iter on trait objects (now works directly!) + { + let db_dyn: &mut dyn DatabaseCommit = &mut db; + let items: Vec<(Address, Account)> = vec![]; + db_dyn.commit_iter(&mut items.into_iter()); + } + assert_eq!(db.commits.len(), 3); + + // Test ergonomic commit_from_iter on trait objects + { + let db_dyn: &mut dyn DatabaseCommit = &mut db; + db_dyn.commit_from_iter(vec![]); + } + assert_eq!(db.commits.len(), 4); + } +} diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 809b82d67d..a94289b0b2 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -392,7 +392,7 @@ impl DatabaseCommit for State { } } - fn commit_iter(&mut self, changes: impl IntoIterator) { + fn commit_iter(&mut self, changes: &mut dyn Iterator) { let transitions = self .cache .apply_evm_state_iter(changes, |address, account| { From e7c9d8b99680ce84b573808541592d1db01563d0 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 8 Jan 2026 12:13:44 +0100 Subject: [PATCH 110/127] fix(test): one gasid name is missing (#3290) --- crates/context/interface/src/cfg/gas_params.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/context/interface/src/cfg/gas_params.rs b/crates/context/interface/src/cfg/gas_params.rs index 7e59f6a027..9236d2d543 100644 --- a/crates/context/interface/src/cfg/gas_params.rs +++ b/crates/context/interface/src/cfg/gas_params.rs @@ -874,7 +874,7 @@ impl GasId { "cold_storage_cost" => Some(Self::cold_storage_cost()), "new_account_cost_for_selfdestruct" => Some(Self::new_account_cost_for_selfdestruct()), "code_deposit_cost" => Some(Self::code_deposit_cost()), - "eip7702_per_empty_account_cost" => Some(Self::tx_eip7702_per_empty_account_cost()), + "tx_eip7702_per_empty_account_cost" => Some(Self::tx_eip7702_per_empty_account_cost()), "tx_token_non_zero_byte_multiplier" => Some(Self::tx_token_non_zero_byte_multiplier()), "tx_token_cost" => Some(Self::tx_token_cost()), "tx_floor_cost_per_token" => Some(Self::tx_floor_cost_per_token()), @@ -1112,11 +1112,11 @@ mod tests { "Not all unique names are resolvable via from_str" ); - // We should have exactly 25 known GasIds (based on the indices 1-25 used) + // We should have exactly 36 known GasIds (based on the indices 1-36 used) assert_eq!( unique_names.len(), - 25, - "Expected 25 unique GasIds, found {}", + 36, + "Expected 36 unique GasIds, found {}", unique_names.len() ); } From 2367e60c734bb24279f6b4497e58c6c0361a34ae Mon Sep 17 00:00:00 2001 From: Doohyun Cho <158799614+doocho@users.noreply.github.com> Date: Thu, 8 Jan 2026 20:16:42 +0900 Subject: [PATCH 111/127] fix(database): return error instead of panic when block not found in AlloyDB (#3284) * fix(database): return error instead of panic when block not found in AlloyDB - Change DBTransportError struct to AlloyDBError enum - Add BlockNotFound variant for missing block errors - Handle None case in block_hash_async_ref gracefully This fixes potential panics when: - Using pruned nodes with deleted block data - Using light clients without full block data - Requesting future or non-existent block numbers Closes #3278 * Apply suggestion from @rakita --- crates/database/src/alloydb.rs | 44 +++++++++++++++++++++++++--------- crates/database/src/lib.rs | 2 +- 2 files changed, 34 insertions(+), 12 deletions(-) diff --git a/crates/database/src/alloydb.rs b/crates/database/src/alloydb.rs index 5a0234ba72..06a75edf37 100644 --- a/crates/database/src/alloydb.rs +++ b/crates/database/src/alloydb.rs @@ -12,23 +12,42 @@ use primitives::{Address, StorageKey, StorageValue, B256}; use state::{AccountInfo, Bytecode}; use std::fmt::Display; -/// Error type for transport-related database operations. +/// Error type for AlloyDB database operations. #[derive(Debug)] -pub struct DBTransportError(pub TransportError); +pub enum AlloyDBError { + /// Transport error from the underlying provider. + Transport(TransportError), + /// Block not found for the given block number. + /// + /// This can occur when: + /// - The node has pruned the block data + /// - Using a light client that doesn't have the block + BlockNotFound(u64), +} -impl DBErrorMarker for DBTransportError {} +impl DBErrorMarker for AlloyDBError {} -impl Display for DBTransportError { +impl Display for AlloyDBError { fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - write!(f, "Transport error: {}", self.0) + match self { + Self::Transport(err) => write!(f, "Transport error: {err}"), + Self::BlockNotFound(number) => write!(f, "Block not found: {number}"), + } } } -impl Error for DBTransportError {} +impl Error for AlloyDBError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + match self { + Self::Transport(err) => Some(err), + Self::BlockNotFound(_) => None, + } + } +} -impl From for DBTransportError { +impl From for AlloyDBError { fn from(e: TransportError) -> Self { - Self(e) + Self::Transport(e) } } @@ -61,7 +80,7 @@ impl> AlloyDB { } impl> DatabaseAsyncRef for AlloyDB { - type Error = DBTransportError; + type Error = AlloyDBError; async fn basic_async_ref(&self, address: Address) -> Result, Self::Error> { let nonce = self @@ -93,8 +112,11 @@ impl> DatabaseAsyncRef for AlloyDB { // SAFETY: We know number <= u64::MAX, so we can safely convert it to u64 .get_block_by_number(number.into()) .await?; - // SAFETY: If the number is given, the block is supposed to be finalized, so unwrapping is safe. - Ok(B256::new(*block.unwrap().header().hash())) + + match block { + Some(block) => Ok(B256::new(*block.header().hash())), + None => Err(AlloyDBError::BlockNotFound(number)), + } } async fn code_by_hash_async_ref(&self, _code_hash: B256) -> Result { diff --git a/crates/database/src/lib.rs b/crates/database/src/lib.rs index a1f6f5c543..ab1574a7c9 100644 --- a/crates/database/src/lib.rs +++ b/crates/database/src/lib.rs @@ -15,7 +15,7 @@ pub mod in_memory_db; pub mod states; #[cfg(feature = "alloydb")] -pub use alloydb::{AlloyDB, BlockId, DBTransportError}; +pub use alloydb::{AlloyDB, AlloyDBError, BlockId}; pub use in_memory_db::*; pub use states::{ From 40845b2c34d1a03f69b33d84dca8d15c16ade0fd Mon Sep 17 00:00:00 2001 From: Ryan Date: Thu, 8 Jan 2026 22:12:48 +0800 Subject: [PATCH 112/127] feat(inspector): make TestInspector public for testing EVM variants (#3282) * feat(inspector): make TestInspector public for testing EVM variants * fix ci --- crates/inspector/src/inspector_tests.rs | 178 +------------- crates/inspector/src/lib.rs | 3 + crates/inspector/src/test_inspector.rs | 293 ++++++++++++++++++++++++ 3 files changed, 298 insertions(+), 176 deletions(-) create mode 100644 crates/inspector/src/test_inspector.rs diff --git a/crates/inspector/src/inspector_tests.rs b/crates/inspector/src/inspector_tests.rs index 3fc183d6cf..8d9d13ae50 100644 --- a/crates/inspector/src/inspector_tests.rs +++ b/crates/inspector/src/inspector_tests.rs @@ -1,186 +1,12 @@ #[cfg(test)] mod tests { - use crate::{InspectEvm, InspectSystemCallEvm, Inspector}; + use crate::{InspectEvm, InspectSystemCallEvm, InspectorEvent, TestInspector}; use context::{Context, TxEnv}; use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; use handler::{MainBuilder, MainContext}; - use interpreter::{ - interpreter_types::{Jumps, MemoryTr, StackTr}, - CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterTypes, - }; - use primitives::{address, Address, Bytes, Log, TxKind, U256}; + use primitives::{address, Address, Bytes, TxKind, U256}; use state::{bytecode::opcode, AccountInfo, Bytecode}; - #[derive(Debug, Clone)] - struct InterpreterState { - pc: usize, - stack_len: usize, - memory_size: usize, - } - - #[derive(Debug, Clone)] - struct StepRecord { - before: InterpreterState, - after: Option, - opcode_name: String, - } - - #[derive(Debug, Clone)] - enum InspectorEvent { - Step(StepRecord), - Call { - inputs: CallInputs, - outcome: Option, - }, - Create { - inputs: CreateInputs, - outcome: Option, - }, - Log(Log), - Selfdestruct { - address: Address, - beneficiary: Address, - value: U256, - }, - } - - #[derive(Debug, Default)] - struct TestInspector { - events: Vec, - step_count: usize, - call_depth: usize, - } - - impl TestInspector { - fn new() -> Self { - Self { - events: Vec::new(), - step_count: 0, - call_depth: 0, - } - } - - fn capture_interpreter_state( - interp: &Interpreter, - ) -> InterpreterState - where - INTR::Bytecode: Jumps, - INTR::Stack: StackTr, - INTR::Memory: MemoryTr, - { - InterpreterState { - pc: interp.bytecode.pc(), - stack_len: interp.stack.len(), - memory_size: interp.memory.size(), - } - } - - fn get_events(&self) -> Vec { - self.events.clone() - } - - fn get_step_count(&self) -> usize { - self.step_count - } - } - - impl Inspector for TestInspector - where - INTR: InterpreterTypes, - INTR::Bytecode: Jumps, - INTR::Stack: StackTr, - INTR::Memory: MemoryTr, - { - fn step(&mut self, interp: &mut Interpreter, _context: &mut CTX) { - self.step_count += 1; - - let state = Self::capture_interpreter_state(interp); - let opcode = interp.bytecode.opcode(); - let opcode_name = if let Some(op) = state::bytecode::opcode::OpCode::new(opcode) { - format!("{op}") - } else { - format!("Unknown(0x{opcode:02x})") - }; - - self.events.push(InspectorEvent::Step(StepRecord { - before: state, - after: None, - opcode_name, - })); - } - - fn step_end(&mut self, interp: &mut Interpreter, _context: &mut CTX) { - let state = Self::capture_interpreter_state(interp); - - if let Some(InspectorEvent::Step(record)) = self.events.last_mut() { - record.after = Some(state); - } - } - - fn log(&mut self, _ctx: &mut CTX, log: Log) { - self.events.push(InspectorEvent::Log(log)); - } - - fn call(&mut self, _ctx: &mut CTX, inputs: &mut CallInputs) -> Option { - self.call_depth += 1; - self.events.push(InspectorEvent::Call { - inputs: inputs.clone(), - outcome: None, - }); - None - } - - fn call_end(&mut self, _ctx: &mut CTX, _inputs: &CallInputs, outcome: &mut CallOutcome) { - self.call_depth -= 1; - if let Some(InspectorEvent::Call { - outcome: ref mut out, - .. - }) = self - .events - .iter_mut() - .rev() - .find(|e| matches!(e, InspectorEvent::Call { outcome: None, .. })) - { - *out = Some(outcome.clone()); - } - } - - fn create(&mut self, _ctx: &mut CTX, inputs: &mut CreateInputs) -> Option { - self.events.push(InspectorEvent::Create { - inputs: inputs.clone(), - outcome: None, - }); - None - } - - fn create_end( - &mut self, - _ctx: &mut CTX, - _inputs: &CreateInputs, - outcome: &mut CreateOutcome, - ) { - if let Some(InspectorEvent::Create { - outcome: ref mut out, - .. - }) = self - .events - .iter_mut() - .rev() - .find(|e| matches!(e, InspectorEvent::Create { outcome: None, .. })) - { - *out = Some(outcome.clone()); - } - } - - fn selfdestruct(&mut self, contract: Address, beneficiary: Address, value: U256) { - self.events.push(InspectorEvent::Selfdestruct { - address: contract, - beneficiary, - value, - }); - } - } - #[test] fn test_push_opcodes_and_stack_operations() { // PUSH1 0x42, PUSH2 0x1234, ADD, PUSH1 0x00, MSTORE, STOP diff --git a/crates/inspector/src/lib.rs b/crates/inspector/src/lib.rs index 35338857bb..e8df6ccb5b 100644 --- a/crates/inspector/src/lib.rs +++ b/crates/inspector/src/lib.rs @@ -16,6 +16,8 @@ mod inspect; mod inspector; mod mainnet_inspect; mod noop; +/// Test inspector for testing EVM execution. +pub mod test_inspector; mod traits; #[cfg(test)] @@ -33,6 +35,7 @@ pub use handler::{inspect_instructions, InspectorHandler}; pub use inspect::{InspectCommitEvm, InspectEvm, InspectSystemCallEvm}; pub use inspector::*; pub use noop::NoOpInspector; +pub use test_inspector::{InspectorEvent, InterpreterState, StepRecord, TestInspector}; pub use traits::*; #[cfg(test)] diff --git a/crates/inspector/src/test_inspector.rs b/crates/inspector/src/test_inspector.rs new file mode 100644 index 0000000000..4aaf47108b --- /dev/null +++ b/crates/inspector/src/test_inspector.rs @@ -0,0 +1,293 @@ +//! Test inspector for testing EVM execution. + +extern crate alloc; + +use crate::Inspector; +use alloc::{format, string::String, vec::Vec}; +use interpreter::{ + interpreter_types::{Jumps, MemoryTr, StackTr}, + CallInputs, CallOutcome, CreateInputs, CreateOutcome, Interpreter, InterpreterTypes, +}; +use primitives::{Address, Log, U256}; + +/// Interpreter state at a specific point in execution. +#[derive(Debug, Clone)] +pub struct InterpreterState { + /// Program counter. + pub pc: usize, + /// Stack length. + pub stack_len: usize, + /// Memory size. + pub memory_size: usize, +} + +/// Step execution record. +#[derive(Debug, Clone)] +pub struct StepRecord { + /// State before instruction execution. + pub before: InterpreterState, + /// State after instruction execution. + pub after: Option, + /// Opcode name. + pub opcode_name: String, +} + +/// Events captured during EVM execution. +#[derive(Debug, Clone)] +pub enum InspectorEvent { + /// Execution step. + Step(StepRecord), + /// Call operation. + Call { + /// Call inputs. + inputs: CallInputs, + /// Call outcome. + outcome: Option, + }, + /// Create operation. + Create { + /// Create inputs. + inputs: CreateInputs, + /// Create outcome. + outcome: Option, + }, + /// Log emission. + Log(Log), + /// Selfdestruct operation. + Selfdestruct { + /// Contract address. + address: Address, + /// Beneficiary address. + beneficiary: Address, + /// Value transferred. + value: U256, + }, +} + +/// Test inspector that records execution events. +#[derive(Debug, Default)] +pub struct TestInspector { + /// Captured events. + pub events: Vec, + /// Total step count. + pub step_count: usize, + /// Current call depth. + pub call_depth: usize, +} + +impl TestInspector { + /// Create a new TestInspector. + pub fn new() -> Self { + Self::default() + } + + fn capture_interpreter_state( + interp: &Interpreter, + ) -> InterpreterState + where + INTR::Bytecode: Jumps, + INTR::Stack: StackTr, + INTR::Memory: MemoryTr, + { + InterpreterState { + pc: interp.bytecode.pc(), + stack_len: interp.stack.len(), + memory_size: interp.memory.size(), + } + } + + /// Get all captured events. + pub fn get_events(&self) -> Vec { + self.events.clone() + } + + /// Get the total step count. + pub fn get_step_count(&self) -> usize { + self.step_count + } +} + +impl Inspector for TestInspector +where + INTR: InterpreterTypes, + INTR::Bytecode: Jumps, + INTR::Stack: StackTr, + INTR::Memory: MemoryTr, +{ + fn step(&mut self, interp: &mut Interpreter, _context: &mut CTX) { + self.step_count += 1; + + let state = Self::capture_interpreter_state(interp); + let opcode = interp.bytecode.opcode(); + let opcode_name = if let Some(op) = state::bytecode::opcode::OpCode::new(opcode) { + format!("{op}") + } else { + format!("Unknown(0x{opcode:02x})") + }; + + self.events.push(InspectorEvent::Step(StepRecord { + before: state, + after: None, + opcode_name, + })); + } + + fn step_end(&mut self, interp: &mut Interpreter, _context: &mut CTX) { + let state = Self::capture_interpreter_state(interp); + + if let Some(InspectorEvent::Step(record)) = self.events.last_mut() { + record.after = Some(state); + } + } + + fn log(&mut self, _ctx: &mut CTX, log: Log) { + self.events.push(InspectorEvent::Log(log)); + } + + fn call(&mut self, _ctx: &mut CTX, inputs: &mut CallInputs) -> Option { + self.call_depth += 1; + self.events.push(InspectorEvent::Call { + inputs: inputs.clone(), + outcome: None, + }); + None + } + + fn call_end(&mut self, _ctx: &mut CTX, _inputs: &CallInputs, outcome: &mut CallOutcome) { + self.call_depth -= 1; + if let Some(InspectorEvent::Call { + outcome: ref mut out, + .. + }) = self + .events + .iter_mut() + .rev() + .find(|e| matches!(e, InspectorEvent::Call { outcome: None, .. })) + { + *out = Some(outcome.clone()); + } + } + + fn create(&mut self, _ctx: &mut CTX, inputs: &mut CreateInputs) -> Option { + self.events.push(InspectorEvent::Create { + inputs: inputs.clone(), + outcome: None, + }); + None + } + + fn create_end(&mut self, _ctx: &mut CTX, _inputs: &CreateInputs, outcome: &mut CreateOutcome) { + if let Some(InspectorEvent::Create { + outcome: ref mut out, + .. + }) = self + .events + .iter_mut() + .rev() + .find(|e| matches!(e, InspectorEvent::Create { outcome: None, .. })) + { + *out = Some(outcome.clone()); + } + } + + fn selfdestruct(&mut self, contract: Address, beneficiary: Address, value: U256) { + self.events.push(InspectorEvent::Selfdestruct { + address: contract, + beneficiary, + value, + }); + } +} + +/// Default tests for EVM implementations. +#[cfg(feature = "std")] +pub mod default_tests { + use super::*; + use alloc::{string::ToString, vec, vec::Vec}; + use primitives::Bytes; + use state::bytecode::opcode; + + /// Run default test suite on an EVM implementation. + /// The execute function should set up the EVM, run the bytecode, and return the TestInspector. + pub fn run_tests(mut execute: F) -> Result<(), Vec<(&'static str, String)>> + where + F: FnMut(Bytes) -> Result, + { + let mut failures = Vec::new(); + + // Test basic stack operations: PUSH, ADD, MSTORE + let stack_test = Bytes::from(vec![ + opcode::PUSH1, + 0x42, + opcode::PUSH1, + 0x10, + opcode::ADD, + opcode::PUSH1, + 0x00, + opcode::MSTORE, + opcode::STOP, + ]); + + match execute(stack_test) { + Ok(inspector) => { + if inspector.step_count < 5 { + failures.push(("stack_operations", "Not enough steps recorded".to_string())); + } + } + Err(e) => failures.push(("stack_operations", e)), + } + + // Test JUMP control flow + let jump_test = Bytes::from(vec![ + opcode::PUSH1, + 0x05, + opcode::JUMP, + opcode::INVALID, + opcode::INVALID, + opcode::JUMPDEST, + opcode::STOP, + ]); + + match execute(jump_test) { + Ok(inspector) => { + let has_jump = inspector + .events + .iter() + .any(|e| matches!(e, InspectorEvent::Step(s) if s.opcode_name == "JUMP")); + if !has_jump { + failures.push(("jump", "JUMP not recorded".to_string())); + } + } + Err(e) => failures.push(("jump", e)), + } + + // Test LOG0 + let log_test = Bytes::from(vec![ + opcode::PUSH1, + 0x20, + opcode::PUSH1, + 0x00, + opcode::LOG0, + opcode::STOP, + ]); + + match execute(log_test) { + Ok(inspector) => { + let has_log = inspector + .events + .iter() + .any(|e| matches!(e, InspectorEvent::Log(_))); + if !has_log { + failures.push(("log", "LOG0 not recorded".to_string())); + } + } + Err(e) => failures.push(("log", e)), + } + + if failures.is_empty() { + Ok(()) + } else { + Err(failures) + } + } +} From d06f63854a81bc0f8a35a3c944f6a518c8ddd8a8 Mon Sep 17 00:00:00 2001 From: Doohyun Cho <158799614+doocho@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:24:33 +0900 Subject: [PATCH 113/127] docs: fix typos and grammar in database crate (#3279) - state.rs: Fix 'After block is finishes' -> 'After block finishes' - state.rs: Fix 'Addition layer' -> 'Additional layer', 'fetched' -> 'fetch' - state.rs: Fix 'Takess' -> 'Takes' - bundle_state.rs: Fix incomplete sentence to match function docs - async_db.rs: Fix incorrect doc reference to actual method called --- crates/database/interface/src/async_db.rs | 2 +- crates/database/src/states/bundle_state.rs | 2 +- crates/database/src/states/state.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/database/interface/src/async_db.rs b/crates/database/interface/src/async_db.rs index 6e35dac440..2561e7c642 100644 --- a/crates/database/interface/src/async_db.rs +++ b/crates/database/interface/src/async_db.rs @@ -171,7 +171,7 @@ impl Database for WrapDatabaseAsync { /// Gets storage value of account by its id. /// - /// Default implementation is to call [`DatabaseRef::storage_ref`] method. + /// Wraps [`DatabaseAsync::storage_by_account_id_async`] in a blocking call. #[inline] fn storage_by_account_id( &mut self, diff --git a/crates/database/src/states/bundle_state.rs b/crates/database/src/states/bundle_state.rs index 8c28c7ff72..8982706132 100644 --- a/crates/database/src/states/bundle_state.rs +++ b/crates/database/src/states/bundle_state.rs @@ -397,7 +397,7 @@ impl BundleRetention { /// /// This is needed to decide if there were any changes to the account. /// -/// Reverts and created when TransitionState is applied to BundleState. +/// Changes are applied and reverts are created when TransitionState is applied to BundleState. /// /// And can be used to revert BundleState to the state before transition. #[derive(Default, Clone, Debug, PartialEq, Eq)] diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index a94289b0b2..10b7292677 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -50,13 +50,13 @@ pub struct State { /// /// Build reverts and state that gets applied to the state. pub transition_state: Option, - /// After block is finishes we merge those changes inside bundle + /// After block finishes we merge those changes inside bundle /// /// Bundle is used to update database and create changesets. /// /// Bundle state can be set on initialization if we want to use preloaded bundle. pub bundle_state: BundleState, - /// Addition layer that is going to be used to fetched values before fetching values + /// Additional layer that is going to be used to fetch values before fetching values /// from database /// /// Bundle is the main output of the state execution and this allows setting previous bundle @@ -192,7 +192,7 @@ impl State { } // TODO : Make cache aware of transitions dropping by having global transition counter. - /// Takess the [`BundleState`] changeset from the [`State`], replacing it + /// Takes the [`BundleState`] changeset from the [`State`], replacing it /// with an empty one. /// /// This will not apply any pending [`TransitionState`]. From 5f16e96f5e1d915e917efa7aeaacc925197111c1 Mon Sep 17 00:00:00 2001 From: Developer Uche <69772615+developeruche@users.noreply.github.com> Date: Fri, 9 Jan 2026 11:21:00 +0100 Subject: [PATCH 114/127] feat(cache-db): Added pritty_print for CacheDB (#3296) --- crates/database/src/in_memory_db.rs | 130 ++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/crates/database/src/in_memory_db.rs b/crates/database/src/in_memory_db.rs index e43f0dc2ca..16166853fe 100644 --- a/crates/database/src/in_memory_db.rs +++ b/crates/database/src/in_memory_db.rs @@ -190,6 +190,93 @@ impl CacheDB { account.storage = storage.into_iter().collect(); Ok(()) } + + /// Pretty print the cache DB for debugging purposes. + #[cfg(feature = "std")] + pub fn pretty_print(&self) -> String { + let mut output = String::new(); + output.push_str("CacheDB:\n"); + output.push_str(&format!( + " accounts: {} total\n", + self.cache.accounts.len() + )); + + // Sort accounts by address for deterministic output + let mut accounts: Vec<_> = self.cache.accounts.iter().collect(); + accounts.sort_by_key(|(addr, _)| *addr); + + for (address, db_account) in accounts { + output.push_str(&format!(" [{address}]:\n")); + output.push_str(&format!(" state: {:?}\n", db_account.account_state)); + + if let Some(info) = db_account.info() { + output.push_str(&format!(" balance: {}\n", info.balance)); + output.push_str(&format!(" nonce: {}\n", info.nonce)); + output.push_str(&format!(" code_hash: {}\n", info.code_hash)); + + if let Some(code) = info.code { + if !code.is_empty() { + output.push_str(&format!(" code: {} bytes\n", code.len())); + } + } + } else { + output.push_str(" account: None (not existing)\n"); + } + + if !db_account.storage.is_empty() { + output.push_str(&format!( + " storage: {} slots\n", + db_account.storage.len() + )); + let mut storage: Vec<_> = db_account.storage.iter().collect(); + storage.sort_by_key(|(k, _)| *k); + for (key, value) in storage { + output.push_str(&format!(" [{key:#x}]: {value:#x}\n")); + } + } + } + + if !self.cache.contracts.is_empty() { + output.push_str(&format!( + " contracts: {} total\n", + self.cache.contracts.len() + )); + let mut contracts: Vec<_> = self.cache.contracts.iter().collect(); + contracts.sort_by_key(|(h, _)| *h); + for (hash, bytecode) in contracts { + output.push_str(&format!(" [{hash}]: {} bytes\n", bytecode.len())); + } + } + + // Print logs in detail: index, address and number of topics. + if !self.cache.logs.is_empty() { + output.push_str(&format!(" logs: {} total\n", self.cache.logs.len())); + for (i, log) in self.cache.logs.iter().enumerate() { + // Print address and topics count. We avoid printing raw data to keep output compact. + output.push_str(&format!( + " [{i}]: address: {:?}, topics: {}\n", + log.address, + log.data.topics().len() + )); + } + } + + // Print block_hashes entries (sorted by block number) with their hash. + if !self.cache.block_hashes.is_empty() { + output.push_str(&format!( + " block_hashes: {} total\n", + self.cache.block_hashes.len() + )); + let mut block_hashes: Vec<_> = self.cache.block_hashes.iter().collect(); + block_hashes.sort_by_key(|(num, _)| *num); + for (num, hash) in block_hashes { + output.push_str(&format!(" [{num}]: {hash}\n")); + } + } + + output.push_str("}\n"); + output + } } impl DatabaseCommit for CacheDB { @@ -568,6 +655,49 @@ mod tests { assert_eq!(new_state.storage(account, key1), Ok(value1)); } + #[cfg(feature = "std")] + #[test] + fn test_pretty_print_cachedb() { + use primitives::{Bytes, Log, LogData, B256, U256}; + + let account = Address::with_last_byte(55); + let mut cachedb = CacheDB::new(EmptyDB::default()); + cachedb.insert_account_info( + account, + AccountInfo { + nonce: 7, + ..Default::default() + }, + ); + let key = StorageKey::from(1); + let value = StorageValue::from(2); + cachedb.insert_account_storage(account, key, value).unwrap(); + + // Add a log entry + let log = Log { + address: account, + data: LogData::new(Vec::new(), Bytes::from(vec![0x01u8])) + .expect("LogData should have <=4 topics"), + }; + cachedb.cache.logs.push(log); + + // Add a block hash entry + cachedb + .cache + .block_hashes + .insert(U256::from(123u64), B256::from([1u8; 32])); + + let s = cachedb.pretty_print(); + assert!(s.contains("CacheDB:")); + assert!(s.contains("accounts: 1 total")); + // storage line is expected to be present for the account + assert!(s.contains("storage: 1 slots")); + + // logs and block_hashes should be reported with counts + assert!(s.contains("logs: 1 total")); + assert!(s.contains("block_hashes: 1 total")); + } + #[cfg(feature = "serde")] #[test] fn test_serialize_deserialize_cachedb() { From a9738dd39fbc67d44c2fcac411c97d1f2b481936 Mon Sep 17 00:00:00 2001 From: Ryan Date: Fri, 9 Jan 2026 18:21:11 +0800 Subject: [PATCH 115/127] fix API comment (#3293) --- crates/context/src/local.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/context/src/local.rs b/crates/context/src/local.rs index 55b321ff88..1026721b73 100644 --- a/crates/context/src/local.rs +++ b/crates/context/src/local.rs @@ -42,7 +42,9 @@ impl LocalContextTr for LocalContext { } impl LocalContext { - /// Creates a new local context, initcodes are hashes and added to the mapping. + /// Creates a new local context with default values. + /// + /// Initializes a shared memory buffer with 4KB capacity and no precompile error message. pub fn new() -> Self { Self::default() } From 6afbaf97f1a53084a08f7496769ebad75a532b6a Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Fri, 9 Jan 2026 13:34:27 +0300 Subject: [PATCH 116/127] refactor(revme): consolidate find_all_json_tests into dir_utils (#3262) Eliminate code duplication by consolidating three separate implementations of find_all_json_tests into a single shared implementation in the dir_utils module. This reduces maintenance burden and ensures consistent behavior across blockchaintest and statetest commands. --- bins/revme/src/cmd/blockchaintest.rs | 18 +----------------- bins/revme/src/cmd/statetest.rs | 3 ++- bins/revme/src/cmd/statetest/runner.rs | 17 ----------------- bins/revme/src/dir_utils.rs | 24 +++++++++++++----------- 4 files changed, 16 insertions(+), 46 deletions(-) diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index 928043dd9c..fd8065874c 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -1,6 +1,7 @@ pub mod post_block; pub mod pre_block; +use crate::dir_utils::find_all_json_tests; use clap::Parser; use revm::statetest_types::blockchain::{ @@ -26,7 +27,6 @@ use std::{ time::Instant, }; use thiserror::Error; -use walkdir::{DirEntry, WalkDir}; /// Panics if the value cannot be serialized to JSON. fn print_json(value: &T) { @@ -86,22 +86,6 @@ impl Cmd { } } -/// Find all JSON test files in the given path -/// If path is a file, returns it in a vector -/// If path is a directory, recursively finds all .json files -pub fn find_all_json_tests(path: &Path) -> Vec { - if path.is_file() { - vec![path.to_path_buf()] - } else { - WalkDir::new(path) - .into_iter() - .filter_map(Result::ok) - .filter(|e| e.path().extension() == Some("json".as_ref())) - .map(DirEntry::into_path) - .collect() - } -} - /// Run all blockchain tests from the given files fn run_tests( test_files: Vec, diff --git a/bins/revme/src/cmd/statetest.rs b/bins/revme/src/cmd/statetest.rs index 3094316d53..5c583c0d18 100644 --- a/bins/revme/src/cmd/statetest.rs +++ b/bins/revme/src/cmd/statetest.rs @@ -4,8 +4,9 @@ pub mod utils; pub use runner::{TestError as Error, TestErrorKind}; +use crate::dir_utils::find_all_json_tests; use clap::Parser; -use runner::{find_all_json_tests, run, TestError}; +use runner::{run, TestError}; use std::path::PathBuf; /// `statetest` subcommand diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 52e2c8efcb..757bfac0d2 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -23,7 +23,6 @@ use std::{ time::{Duration, Instant}, }; use thiserror::Error; -use walkdir::{DirEntry, WalkDir}; /// Error that occurs during test execution #[derive(Debug, Error)] @@ -63,22 +62,6 @@ pub enum TestErrorKind { NoJsonFiles, } -/// Find all JSON test files in the given path -/// If path is a file, returns it in a vector -/// If path is a directory, recursively finds all .json files -pub fn find_all_json_tests(path: &Path) -> Vec { - if path.is_file() { - vec![path.to_path_buf()] - } else { - WalkDir::new(path) - .into_iter() - .filter_map(Result::ok) - .filter(|e| e.path().extension() == Some("json".as_ref())) - .map(DirEntry::into_path) - .collect() - } -} - /// Check if a test should be skipped based on its filename /// Some tests are known to be problematic or take too long fn skip_test(path: &Path) -> bool { diff --git a/bins/revme/src/dir_utils.rs b/bins/revme/src/dir_utils.rs index 09406cdd93..5cc2c40a49 100644 --- a/bins/revme/src/dir_utils.rs +++ b/bins/revme/src/dir_utils.rs @@ -1,16 +1,18 @@ use std::path::{Path, PathBuf}; use walkdir::{DirEntry, WalkDir}; +/// Find all JSON test files in the given path. +/// If path is a file, returns it in a vector. +/// If path is a directory, recursively finds all .json files. pub fn find_all_json_tests(path: &Path) -> Vec { - WalkDir::new(path) - .into_iter() - .filter_map(|e| e.ok()) - .filter(|e| { - e.path() - .extension() - .map(|ext| ext == "json") - .unwrap_or(false) - }) - .map(DirEntry::into_path) - .collect::>() + if path.is_file() { + vec![path.to_path_buf()] + } else { + WalkDir::new(path) + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.path().extension() == Some("json".as_ref())) + .map(DirEntry::into_path) + .collect() + } } From ea180b0e0d89f7593801a16f26e2e7f9fb5fa042 Mon Sep 17 00:00:00 2001 From: leopardracer <136604165+leopardracer@users.noreply.github.com> Date: Fri, 9 Jan 2026 15:06:09 +0200 Subject: [PATCH 117/127] chore: fix typos, grammar errors, and improve documentation consistency (#3294) * Update README.md * Fix typo in MIGRATION_GUIDE.md Corrected a typo in the description of `PrecompileError`. * Update inspector.md * Update revme.md * Update contact.md * Update documentation comment for isthmus function * Update awesome.md * Update architecture.md * Update README.md * Update README.md --- MIGRATION_GUIDE.md | 4 ++-- README.md | 8 ++++---- book/src/architecture.md | 6 +++--- book/src/awesome.md | 2 +- book/src/contact.md | 5 ++--- book/src/inspector.md | 4 ++-- book/src/revme.md | 4 ++-- crates/README.md | 2 +- crates/op-revm/src/precompiles.rs | 2 +- examples/my_evm/README.md | 2 +- 10 files changed, 19 insertions(+), 20 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 2f9751276e..33e408e82c 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -22,7 +22,7 @@ No breaking changes * difference is that `log_full` has `Interpreter` input while `log` does not and `log` will be called in places where Interpreter is not found. * `PrecompileError` now contains `Other` as `Cow<'static, str>` - * It allows allows setting both `&'static str` that is without perf penalty and `String` if needed. + * It allows setting both `&'static str` that is without perf penalty and `String` if needed. # v98 tag @@ -158,4 +158,4 @@ No breaking changes # v67 tag (revm v21.0.0) -> v68 tag ( revm v22.0.0) * No code breaking changes -* alloy-primitives bumped to v1.0.0 and we had a major bump because of it. \ No newline at end of file +* alloy-primitives bumped to v1.0.0 and we had a major bump because of it. diff --git a/README.md b/README.md index 82bbb64d5c..237cd5aef8 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Revm offers two primary applications: firstly, it functions as an executor where ### How to use: -Here is a straightforward example of using the Execution API: It allows us to create an Ethereum Virtual Machine (EVM) and execute transactions. Additionally, it can be utilized to generate traces with the inspector or more complex example of foundry cheatcodes. +Here is a straightforward example of using the Execution API: It allows us to create an Ethereum Virtual Machine (EVM) and execute transactions. Additionally, it can be utilized to generate traces with the inspector or more complex examples of foundry cheatcodes. ```rust,ignore let mut evm = Context::mainnet().with_block(block).build_mainnet(); @@ -49,7 +49,7 @@ The full list of projects that use Revm is available in the [awesome-revm](https The [book](https://bluealloy.github.io/revm/) and [`Architecture and API`](https://bluealloy.github.io/revm/architecture.html) page is the best starting resource. -Some quick links can be found here. Some point to code documentation or the book. code docs are there to explain usage of a particular part of the code where the book is to get more of an overview of the architecture or how components/projects fit together. +Some quick links can be found here. Some point to code documentation or the book. Code docs are there to explain usage of a particular part of the code where the book is to get more of an overview of the architecture or how components/projects fit together. * [How to build and use revm](https://bluealloy.github.io/revm/dev.html) * [Architecture overview](https://bluealloy.github.io/revm/architecture.html) @@ -69,8 +69,8 @@ The Minimum Supported Rust Version (MSRV) may be updated at any time, so we can ### Community: For questions please open a github issue or join the public [telegram group](https://t.me/+Ig4WDWOzikA3MzA0) -### Licence -Revm is licensed under MIT Licence. +### License +Revm is licensed under MIT License. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, shall be licensed as above, without any additional terms or conditions. diff --git a/book/src/architecture.md b/book/src/architecture.md index 9832b1f3cf..52cb073856 100644 --- a/book/src/architecture.md +++ b/book/src/architecture.md @@ -22,7 +22,7 @@ The API is designed around four key execution patterns: - **Execution with commit**: Run transactions and automatically persist state changes - **Execution with inspection**: Run transactions with detailed tracing and observation -[`Evm`](https://docs.rs/revm-context/1.0.0/revm_context/evm/struct.Evm.html) the main structure for executing mainnet ethereum transaction is built with a [`Context`](https://docs.rs/revm-context/latest/revm_context/context/struct.Context.html) and a builder, code for it looks like this: +[`Evm`](https://docs.rs/revm-context/1.0.0/revm_context/evm/struct.Evm.html) is the main structure for executing mainnet ethereum transactions. It is built with a [`Context`](https://docs.rs/revm-context/latest/revm_context/context/struct.Context.html) and a builder, code for it looks like this: ```rust,ignore let mut evm = Context::mainnet().with_block(block).build_mainnet(); @@ -42,10 +42,10 @@ And [`Context`](https://docs.rs/revm-context/latest/revm_context/context/struct. REVM provides four ways to execute transactions through traits (API): -* `transact(tx)` and `replay()` are function of [`ExecuteEvm`](https://docs.rs/revm-handler/latest/revm_handler/api/trait.ExecuteEvm.html) trait that allow execution transactions. They return the status of execution with reason, changed state and in case of failed execution an error. +* `transact(tx)` and `replay()` are functions of [`ExecuteEvm`](https://docs.rs/revm-handler/latest/revm_handler/api/trait.ExecuteEvm.html) trait that allow execution transactions. They return the status of execution with reason, changed state and in case of failed execution an error. * `transact_commit(tx)` and `replay_commit()` are part of [`ExecuteCommitEvm`](https://docs.rs/revm-handler/latest/revm_handler/api/trait.ExecuteCommitEvm.html) that internally commits the state diff to the database and returns status of execution. Database is required to support `DatabaseCommit` trait. * `inspect()`, `inspect_replay(tx)` and a few others are part of [`InspectEvm`](https://docs.rs/revm-inspector/latest/revm_inspector/trait.InspectEvm.html) trait that allow execution with inspection. This is how tracers are called. -* `inspect_commit()`,`inspect_replay_commit(tx)` are part of the [`InspectCommitEvm`](https://docs.rs/revm-inspector/latest/revm_inspector/trait.InspectCommitEvm.html) trait that extends `InspectEvm` to allow committing state diff after tracing. +* `inspect_commit()`, `inspect_replay_commit(tx)` are part of the [`InspectCommitEvm`](https://docs.rs/revm-inspector/latest/revm_inspector/trait.InspectCommitEvm.html) trait that extends `InspectEvm` to allow committing state diff after tracing. For inspection API to be enabled, [`Evm`](https://docs.rs/revm-context/1.0.0/revm_context/evm/struct.Evm.html) needs to be created with inspector. diff --git a/book/src/awesome.md b/book/src/awesome.md index 51f759a196..e90d609778 100644 --- a/book/src/awesome.md +++ b/book/src/awesome.md @@ -19,7 +19,7 @@ A curated list of excellent Revm-related resources. Feel free to contribute to t - [**Trin**](https://github.com/ethereum/trin) is a Rust implementation of a Portal Network client. #### EVM Variants -- [**Optimism**](https://github.com/bluealloy/revm/tree/main/crates/op-revm) is a ethereum L2 network. +- [**Optimism**](https://github.com/bluealloy/revm/tree/main/crates/op-revm) is an ethereum L2 network. - [**Base**](https://www.base.org/) is an Ethereum Layer 2 (L2) chain that offers a safe, low-cost, developer-friendly way to build on-chain - [**Scroll**](https://github.com/scroll-tech/revm) is its own Layer 2 network built on Ethereum (more specifically, a “zero-knowledge rollup”). diff --git a/book/src/contact.md b/book/src/contact.md index bced995c04..ed2072dd7f 100644 --- a/book/src/contact.md +++ b/book/src/contact.md @@ -5,13 +5,12 @@ The git repository can be found at [https://github.com/bluealloy/revm/](https:// For questions please open a github issue or join the public [telegram group](https://t.me/+Ig4WDWOzikA3MzA0) -### Licence +### License -Licensed under MIT Licence. +Licensed under MIT License. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in these crates by you, shall be licensed as above, without any additional terms or conditions. ### Security If there is a security question or finding please contact me directly via email at `dragan0rakita@gmail.com` or on keybase `@draganrakita` - diff --git a/book/src/inspector.md b/book/src/inspector.md index a3005bad00..dac32f92eb 100644 --- a/book/src/inspector.md +++ b/book/src/inspector.md @@ -28,7 +28,7 @@ pub trait Inspector { // Event tracing fn log(&mut self, context: &mut CTX, log: Log) {} - fn log_full(&mut self, interp: &mut Interpreter, context &mut CTX, log: Log) { + fn log_full(&mut self, interp: &mut Interpreter, context: &mut CTX, log: Log) { self.log(context, log) } fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) {} @@ -138,4 +138,4 @@ REVM provides several ready-to-use inspectors: - **Development tools**: Contract interaction tracing - **Testing frameworks**: Execution verification and state checking -The Inspector trait makes REVM very observable EVM implementations available, enabling sophisticated tooling and analysis capabilities. \ No newline at end of file +The Inspector trait makes REVM one of the most observable EVM implementations available, enabling sophisticated tooling and analysis capabilities. diff --git a/book/src/revme.md b/book/src/revme.md index bc0818d58b..d82bf2bf33 100644 --- a/book/src/revme.md +++ b/book/src/revme.md @@ -1,6 +1,6 @@ # Revme -Is a binary that allows running statetest and eof validation. +Revme is a binary that allows running statetest and eof validation. ```bash, ignore $: revme --help @@ -27,7 +27,7 @@ Test suites for the latest hardforks can be found in [EEST releases](https://git Revm can run statetest type of tests with `revme` using the following command: `cargo run --release -p revme -- statetest folder_path` -For running EEST tests, we can use the `./scripts/run-tests.sh.` +For running EEST tests, we can use the `./scripts/run-tests.sh`. For legacy tests, we need to first download the repo `git clone https://github.com/ethereum/legacytests` and then run it with `cargo run --release -p revme -- statetest legacytests/Cancun/GeneralStateTests` All statetest that can be run by revme can be found in the `GeneralStateTests` folder. diff --git a/crates/README.md b/crates/README.md index 8bb52201fc..88773fdb42 100644 --- a/crates/README.md +++ b/crates/README.md @@ -1,5 +1,5 @@ Crates version and their description: -* ![revm](https://img.shields.io/crates/v/revm?height=50?label=revm) main crate, it reexports all other crates. +* ![revm](https://img.shields.io/crates/v/revm?height=50?label=revm) main crate. It reexports all other crates. * ![revm-primitives](https://img.shields.io/crates/v/revm-primitives?label=revm-primitives) contains constants and primitives types that revm uses (alloy-primitives) * ![revm-interpreter](https://img.shields.io/crates/v/revm-interpreter?label=revm-interpreter) biggest crate in the project, it contains all instructions * ![revm-precompile](https://img.shields.io/crates/v/revm-precompile?label=revm-precompile) Precompiles defined by ethereum diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index d234980164..14df489c57 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -75,7 +75,7 @@ pub fn granite() -> &'static Precompiles { }) } -/// Returns precompiles for isthumus spec. +/// Returns precompiles for isthmus spec. pub fn isthmus() -> &'static Precompiles { static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { diff --git a/examples/my_evm/README.md b/examples/my_evm/README.md index 7b0a852968..58363aab6e 100644 --- a/examples/my_evm/README.md +++ b/examples/my_evm/README.md @@ -68,7 +68,7 @@ let _res = my_evm.inspect_commit_replay(); ``` ### [`revm::SystemCallEvm`] -Allows executing system transaction, only input needed is system contract add address and input +Allows executing a system transaction. Only input needed is system contract address and input. Validation and pre-execution and most of post execution phases of ordinary transact flow will be skipped. System calls are needed for inserting of fetching data on pre or post block state. From a31fa98efe2208af326cf70f59d374165e0df363 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 9 Jan 2026 14:06:26 +0100 Subject: [PATCH 118/127] chore: apply improvements from ai-bot labeled PRs (#3297) * chore: apply improvements from ai-bot labeled PRs This commit consolidates improvements from 8 community PRs with the ai-bot label: - fix: correct debug log for blob gas fields in blockchaintest (#3291) Split blob_excess_gas_and_price into separate debug outputs for clarity - perf(state): remove redundant clones in account_info.rs (#3287) Eliminate unnecessary clone operations in test code - docs: fix duplicate word in MIGRATION_GUIDE.md (#3209) Remove duplicate "allows" in PrecompileError documentation - fix: return G2NotInSubgroup for G2 subgroup check failure (#3179) Correct error type from G1NotInSubgroup to G2NotInSubgroup in BLS12-381 - refactor: reuse bound tx and remove redundant context.tx() calls (#3176) Optimize validation by reusing transaction binding - docs: fix incorrect reth references in blockchain.rs comments (#3169) Update comments to use correct terminology instead of "reth" - perf: use lazy defaults for env vars in burntpix benchmark (#3071) Replace unwrap_or with unwrap_or_else to avoid unnecessary allocations All changes have been tested with cargo check and cargo test. * fmt --- bins/revme/src/cmd/bench/burntpix.rs | 7 +++++-- bins/revme/src/cmd/blockchaintest.rs | 7 +++---- crates/handler/src/validation.rs | 4 ++-- crates/precompile/src/bls12_381/arkworks.rs | 2 +- crates/state/src/account_info.rs | 4 ++-- crates/statetest-types/src/blockchain.rs | 4 ++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index cc19f7937c..1537dcb12c 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -102,9 +102,12 @@ pub fn svg(filename: String, svg_data: &[u8]) -> Result<(), Box> { const DEFAULT_SEED: &str = "0"; const DEFAULT_ITERATIONS: &str = "0x4E20"; // 20_000 iterations fn try_init_env_vars() -> Result<(u32, U256), Box> { - let seed_from_env = std::env::var("SEED").unwrap_or(DEFAULT_SEED.to_string()); + // Use lazy default to avoid unnecessary allocation when env is set + let seed_from_env = std::env::var("SEED").unwrap_or_else(|_| DEFAULT_SEED.to_string()); let seed: u32 = try_from_hex_to_u32(&seed_from_env)?; - let iterations_from_env = std::env::var("ITERATIONS").unwrap_or(DEFAULT_ITERATIONS.to_string()); + // Use lazy default to avoid unnecessary allocation when env is set + let iterations_from_env = + std::env::var("ITERATIONS").unwrap_or_else(|_| DEFAULT_ITERATIONS.to_string()); let iterations = U256::from_str(&iterations_from_env)?; Ok((seed, iterations)) } diff --git a/bins/revme/src/cmd/blockchaintest.rs b/bins/revme/src/cmd/blockchaintest.rs index fd8065874c..44503babb6 100644 --- a/bins/revme/src/cmd/blockchaintest.rs +++ b/bins/revme/src/cmd/blockchaintest.rs @@ -485,10 +485,9 @@ fn print_error_with_state( eprintln!(" Difficulty: {}", debug_info.block_env.difficulty); eprintln!(" Prevrandao: {:?}", debug_info.block_env.prevrandao); eprintln!(" Beneficiary: {:?}", debug_info.block_env.beneficiary); - eprintln!( - " Blob excess gas: {:?}", - debug_info.block_env.blob_excess_gas_and_price - ); + let blob = debug_info.block_env.blob_excess_gas_and_price; + eprintln!(" Blob excess gas: {:?}", blob.map(|a| a.excess_blob_gas)); + eprintln!(" Blob gas price: {:?}", blob.map(|a| a.blob_gasprice)); // Print withdrawals if let Some(withdrawals) = &debug_info.withdrawals { diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index 569ff23784..282990866f 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -122,8 +122,8 @@ pub fn validate_tx_env( spec_id: SpecId, ) -> Result<(), InvalidTransaction> { // Check if the transaction's chain id is correct - let tx_type = context.tx().tx_type(); let tx = context.tx(); + let tx_type = tx.tx_type(); let base_fee = if context.cfg().is_base_fee_check_disabled() { None @@ -216,7 +216,7 @@ pub fn validate_tx_env( // EIP-3860: Limit and meter initcode. Still valid with EIP-7907 and increase of initcode size. if spec_id.is_enabled_in(SpecId::SHANGHAI) && tx.kind().is_create() - && context.tx().input().len() > context.cfg().max_initcode_size() + && tx.input().len() > context.cfg().max_initcode_size() { return Err(InvalidTransaction::CreateInitCodeSizeLimit); } diff --git a/crates/precompile/src/bls12_381/arkworks.rs b/crates/precompile/src/bls12_381/arkworks.rs index 7995a705fb..0722eebca4 100644 --- a/crates/precompile/src/bls12_381/arkworks.rs +++ b/crates/precompile/src/bls12_381/arkworks.rs @@ -179,7 +179,7 @@ fn read_g2( ) -> Result { let point = read_g2_no_subgroup_check(a_x_0, a_x_1, a_y_0, a_y_1)?; if !point.is_in_correct_subgroup_assuming_on_curve() { - return Err(PrecompileError::Bls12381G1NotInSubgroup); + return Err(PrecompileError::Bls12381G2NotInSubgroup); } Ok(point) } diff --git a/crates/state/src/account_info.rs b/crates/state/src/account_info.rs index 74d42f26af..c91fac8ff5 100644 --- a/crates/state/src/account_info.rs +++ b/crates/state/src/account_info.rs @@ -314,7 +314,7 @@ mod tests { fn test_account_info_trait_consistency() { let bytecode = Bytecode::default(); let account1 = AccountInfo { - code: Some(bytecode.clone()), + code: Some(bytecode), ..AccountInfo::default() }; @@ -342,7 +342,7 @@ mod tests { "Set contains account2 (since equal)" ); - let mut accounts = [account2.clone(), account1.clone()]; + let mut accounts = [account2, account1]; accounts.sort(); assert_eq!(accounts[0], accounts[1], "Sorted vec treats them as equal"); } diff --git a/crates/statetest-types/src/blockchain.rs b/crates/statetest-types/src/blockchain.rs index 494d014540..d76dfaa259 100644 --- a/crates/statetest-types/src/blockchain.rs +++ b/crates/statetest-types/src/blockchain.rs @@ -352,7 +352,7 @@ impl BlockHeader { impl Transaction { /// Convert Transaction to TxEnv - /// Note: The 'to' and 'sender' fields need to be provided separately in the reth model + /// Note: The 'to' and 'sender' fields need to be provided separately in TxEnv pub fn to_tx_env(&self) -> Result { // Determine transaction type let tx_type = self.transaction_type.map(|t| t.to::()).unwrap_or(0); @@ -472,7 +472,7 @@ mod test { let result: Result = serde_json::from_str(SAMPLE); // Note: The test may fail because the sample JSON has a different structure - // than what reth expects (e.g., network is a string instead of ForkSpec enum) + // than the expected format (e.g., network is a string instead of ForkSpec enum) // This is expected as the formats differ slightly if let Err(e) = result { println!("Expected deserialization error due to format differences: {e}"); From 1e87f705ef2c6b2dfcc1c0f1b7017636697ffcd0 Mon Sep 17 00:00:00 2001 From: Tomass <155266802+zeroprooff@users.noreply.github.com> Date: Wed, 14 Jan 2026 11:27:26 +0200 Subject: [PATCH 119/127] perf: remove redundant clones in gas params defaults (#3300) --- crates/context/interface/src/cfg/gas_params.rs | 2 +- crates/context/interface/src/host.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/context/interface/src/cfg/gas_params.rs b/crates/context/interface/src/cfg/gas_params.rs index 9236d2d543..ca7c52a451 100644 --- a/crates/context/interface/src/cfg/gas_params.rs +++ b/crates/context/interface/src/cfg/gas_params.rs @@ -91,7 +91,7 @@ mod serde { impl Default for GasParams { fn default() -> Self { - Self::new_spec(SpecId::default()).clone() + Self::new_spec(SpecId::default()) } } diff --git a/crates/context/interface/src/host.rs b/crates/context/interface/src/host.rs index d3fb01ca58..e4efb22081 100644 --- a/crates/context/interface/src/host.rs +++ b/crates/context/interface/src/host.rs @@ -213,7 +213,7 @@ impl DummyHost { /// Create a new dummy host with the given spec. pub fn new(spec: SpecId) -> Self { Self { - gas_params: GasParams::new_spec(spec).clone(), + gas_params: GasParams::new_spec(spec), } } } From 2af80536cefc824f2738f7acd0c32a835e7f6324 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 14 Jan 2026 19:19:07 +0100 Subject: [PATCH 120/127] feat: add `new_oog` helpers to InterpreterResult, CallOutcome, CreateOutcome, and FrameResult (#3309) Add convenience constructors for creating out-of-gas results: - `InterpreterResult::new_oog(gas_limit)` - `CallOutcome::new_oog(gas_limit, memory_offset)` - `CreateOutcome::new_oog(gas_limit)` - `FrameResult::new_call_oog(gas_limit, memory_offset)` - `FrameResult::new_create_oog(gas_limit)` --- crates/handler/src/frame_data.rs | 12 ++++++++++++ crates/interpreter/src/interpreter.rs | 9 +++++++++ .../src/interpreter_action/call_outcome.rs | 10 ++++++++++ .../src/interpreter_action/create_outcome.rs | 13 +++++++++++++ 4 files changed, 44 insertions(+) diff --git a/crates/handler/src/frame_data.rs b/crates/handler/src/frame_data.rs index fab41ca813..de085e174e 100644 --- a/crates/handler/src/frame_data.rs +++ b/crates/handler/src/frame_data.rs @@ -42,6 +42,18 @@ pub enum FrameResult { } impl FrameResult { + /// Creates a new call frame result for an out-of-gas error. + #[inline] + pub fn new_call_oog(gas_limit: u64, memory_offset: core::ops::Range) -> Self { + Self::Call(CallOutcome::new_oog(gas_limit, memory_offset)) + } + + /// Creates a new create frame result for an out-of-gas error. + #[inline] + pub fn new_create_oog(gas_limit: u64) -> Self { + Self::Create(CreateOutcome::new_oog(gas_limit)) + } + /// Casts frame result to interpreter result. #[inline] pub fn into_interpreter_result(self) -> InterpreterResult { diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 698773409f..4f648ad036 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -370,6 +370,15 @@ impl InterpreterResult { } } + /// Returns a new `InterpreterResult` for an out-of-gas error with the given gas limit. + pub fn new_oog(gas_limit: u64) -> Self { + Self { + result: InstructionResult::OutOfGas, + output: Bytes::default(), + gas: Gas::new_spent(gas_limit), + } + } + /// Returns whether the instruction result is a success. #[inline] pub const fn is_ok(&self) -> bool { diff --git a/crates/interpreter/src/interpreter_action/call_outcome.rs b/crates/interpreter/src/interpreter_action/call_outcome.rs index 6ce0fadfd3..d8e851c302 100644 --- a/crates/interpreter/src/interpreter_action/call_outcome.rs +++ b/crates/interpreter/src/interpreter_action/call_outcome.rs @@ -45,6 +45,16 @@ impl CallOutcome { } } + /// Constructs a new [`CallOutcome`] for an out-of-gas error. + /// + /// # Arguments + /// + /// * `gas_limit` - The gas limit that was exceeded. + /// * `memory_offset` - The range in memory indicating where the output data is stored. + pub fn new_oog(gas_limit: u64, memory_offset: Range) -> Self { + Self::new(InterpreterResult::new_oog(gas_limit), memory_offset) + } + /// Returns a reference to the instruction result. /// /// Provides access to the result of the executed instruction. diff --git a/crates/interpreter/src/interpreter_action/create_outcome.rs b/crates/interpreter/src/interpreter_action/create_outcome.rs index 11d7204e66..d10e517cda 100644 --- a/crates/interpreter/src/interpreter_action/create_outcome.rs +++ b/crates/interpreter/src/interpreter_action/create_outcome.rs @@ -30,6 +30,19 @@ impl CreateOutcome { Self { result, address } } + /// Constructs a new [`CreateOutcome`] for an out-of-gas error. + /// + /// # Arguments + /// + /// * `gas_limit` - The gas limit that was exceeded. + /// + /// # Returns + /// + /// A new [`CreateOutcome`] instance with no address. + pub fn new_oog(gas_limit: u64) -> Self { + Self::new(InterpreterResult::new_oog(gas_limit), None) + } + /// Retrieves a reference to the [`InstructionResult`] from the [`InterpreterResult`]. /// /// This method provides access to the [`InstructionResult`] which represents the From 5eedd20ef9a4e2ec8922c54603b7d597af20f946 Mon Sep 17 00:00:00 2001 From: iPLAY888 <133153661+letmehateu@users.noreply.github.com> Date: Wed, 14 Jan 2026 22:15:32 +0300 Subject: [PATCH 121/127] refactor(precompile): extract common pairing_check_bytes logic in bls12_381 (#3301) * Create pairing_common.rs * Update bls12_381.rs * Update arkworks.rs * Update blst.rs * fmt --- crates/precompile/src/bls12_381.rs | 1 + crates/precompile/src/bls12_381/arkworks.rs | 39 +----------- crates/precompile/src/bls12_381/blst.rs | 39 +----------- .../src/bls12_381/pairing_common.rs | 61 +++++++++++++++++++ 4 files changed, 64 insertions(+), 76 deletions(-) create mode 100644 crates/precompile/src/bls12_381/pairing_common.rs diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs index 0c6ff83b9e..5b7474f9ee 100644 --- a/crates/precompile/src/bls12_381.rs +++ b/crates/precompile/src/bls12_381.rs @@ -38,6 +38,7 @@ pub mod g2_msm; pub mod map_fp2_to_g2; pub mod map_fp_to_g1; pub mod pairing; +mod pairing_common; mod utils; /// Returns the BLS12-381 precompiles with their addresses. diff --git a/crates/precompile/src/bls12_381/arkworks.rs b/crates/precompile/src/bls12_381/arkworks.rs index 0722eebca4..b6353f7263 100644 --- a/crates/precompile/src/bls12_381/arkworks.rs +++ b/crates/precompile/src/bls12_381/arkworks.rs @@ -350,44 +350,7 @@ pub(crate) fn pairing_check(pairs: &[(G1Affine, G2Affine)]) -> bool { /// pairing_check_bytes performs a pairing check on a list of G1 and G2 point pairs taking byte inputs. #[inline] pub(crate) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { - if pairs.is_empty() { - return Ok(true); - } - - let mut parsed_pairs = Vec::with_capacity(pairs.len()); - for ((g1_x, g1_y), (g2_x_0, g2_x_1, g2_y_0, g2_y_1)) in pairs { - // Check if G1 point is zero (point at infinity) - let g1_is_zero = g1_x.iter().all(|&b| b == 0) && g1_y.iter().all(|&b| b == 0); - - // Check if G2 point is zero (point at infinity) - let g2_is_zero = g2_x_0.iter().all(|&b| b == 0) - && g2_x_1.iter().all(|&b| b == 0) - && g2_y_0.iter().all(|&b| b == 0) - && g2_y_1.iter().all(|&b| b == 0); - - // Skip this pair if either point is at infinity as it's a no-op - if g1_is_zero || g2_is_zero { - // Still need to validate the non-zero point if one exists - if !g1_is_zero { - let _ = read_g1(g1_x, g1_y)?; - } - if !g2_is_zero { - let _ = read_g2(g2_x_0, g2_x_1, g2_y_0, g2_y_1)?; - } - continue; - } - - let g1_point = read_g1(g1_x, g1_y)?; - let g2_point = read_g2(g2_x_0, g2_x_1, g2_y_0, g2_y_1)?; - parsed_pairs.push((g1_point, g2_point)); - } - - // If all pairs were filtered out, return true (identity element) - if parsed_pairs.is_empty() { - return Ok(true); - } - - Ok(pairing_check(&parsed_pairs)) + super::pairing_common::pairing_check_bytes_generic(pairs, read_g1, read_g2, pairing_check) } // Byte-oriented versions of the functions for external API compatibility diff --git a/crates/precompile/src/bls12_381/blst.rs b/crates/precompile/src/bls12_381/blst.rs index 6200382a25..008ea5af7a 100644 --- a/crates/precompile/src/bls12_381/blst.rs +++ b/crates/precompile/src/bls12_381/blst.rs @@ -755,42 +755,5 @@ pub(crate) fn p2_msm_bytes( /// pairing_check_bytes performs a pairing check on a list of G1 and G2 point pairs taking byte inputs. #[inline] pub(crate) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { - if pairs.is_empty() { - return Ok(true); - } - - let mut parsed_pairs = Vec::with_capacity(pairs.len()); - for ((g1_x, g1_y), (g2_x_0, g2_x_1, g2_y_0, g2_y_1)) in pairs { - // Check if G1 point is zero (point at infinity) - let g1_is_zero = g1_x.iter().all(|&b| b == 0) && g1_y.iter().all(|&b| b == 0); - - // Check if G2 point is zero (point at infinity) - let g2_is_zero = g2_x_0.iter().all(|&b| b == 0) - && g2_x_1.iter().all(|&b| b == 0) - && g2_y_0.iter().all(|&b| b == 0) - && g2_y_1.iter().all(|&b| b == 0); - - // Skip this pair if either point is at infinity as it's a no-op - if g1_is_zero || g2_is_zero { - // Still need to validate the non-zero point if one exists - if !g1_is_zero { - let _ = read_g1(g1_x, g1_y)?; - } - if !g2_is_zero { - let _ = read_g2(g2_x_0, g2_x_1, g2_y_0, g2_y_1)?; - } - continue; - } - - let g1_point = read_g1(g1_x, g1_y)?; - let g2_point = read_g2(g2_x_0, g2_x_1, g2_y_0, g2_y_1)?; - parsed_pairs.push((g1_point, g2_point)); - } - - // If all pairs were filtered out, return true (identity element) - if parsed_pairs.is_empty() { - return Ok(true); - } - - Ok(pairing_check(&parsed_pairs)) + super::pairing_common::pairing_check_bytes_generic(pairs, read_g1, read_g2, pairing_check) } diff --git a/crates/precompile/src/bls12_381/pairing_common.rs b/crates/precompile/src/bls12_381/pairing_common.rs new file mode 100644 index 0000000000..845dd1a2b8 --- /dev/null +++ b/crates/precompile/src/bls12_381/pairing_common.rs @@ -0,0 +1,61 @@ +//! Common pairing validation logic shared between arkworks and blst backends. +//! +//! This module intentionally holds only the byte-level validation/filtering logic that is +//! identical across backends. Backend-specific parsing and pairing computation are injected +//! as function parameters. + +use crate::PrecompileError; +use std::vec::Vec; + +/// Shared implementation of `pairing_check_bytes`. +#[inline] +pub(super) fn pairing_check_bytes_generic( + pairs: &[super::PairingPair], + read_g1: ReadG1, + read_g2: ReadG2, + pairing_check: PairingCheck, +) -> Result +where + ReadG1: Fn(&[u8; 48], &[u8; 48]) -> Result, + ReadG2: Fn(&[u8; 48], &[u8; 48], &[u8; 48], &[u8; 48]) -> Result, + PairingCheck: FnOnce(&[(G1, G2)]) -> bool, +{ + if pairs.is_empty() { + return Ok(true); + } + + let mut parsed_pairs = Vec::with_capacity(pairs.len()); + for ((g1_x, g1_y), (g2_x_0, g2_x_1, g2_y_0, g2_y_1)) in pairs { + // Check if G1 point is zero (point at infinity) + let g1_is_zero = g1_x.iter().all(|&b| b == 0) && g1_y.iter().all(|&b| b == 0); + + // Check if G2 point is zero (point at infinity) + let g2_is_zero = g2_x_0.iter().all(|&b| b == 0) + && g2_x_1.iter().all(|&b| b == 0) + && g2_y_0.iter().all(|&b| b == 0) + && g2_y_1.iter().all(|&b| b == 0); + + // Skip this pair if either point is at infinity as it's a no-op + if g1_is_zero || g2_is_zero { + // Still need to validate the non-zero point if one exists + if !g1_is_zero { + let _ = read_g1(g1_x, g1_y)?; + } + if !g2_is_zero { + let _ = read_g2(g2_x_0, g2_x_1, g2_y_0, g2_y_1)?; + } + continue; + } + + let g1_point = read_g1(g1_x, g1_y)?; + let g2_point = read_g2(g2_x_0, g2_x_1, g2_y_0, g2_y_1)?; + parsed_pairs.push((g1_point, g2_point)); + } + + // If all pairs were filtered out, return true (identity element) + if parsed_pairs.is_empty() { + return Ok(true); + } + + Ok(pairing_check(&parsed_pairs)) +} From a1490dbc4cb28784c8d9f4f5f982410c0e820f0e Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 14 Jan 2026 20:52:58 +0100 Subject: [PATCH 122/127] refactor(gas_params): add dedicated GasIds for sstore_refund (#3310) Add `sstore_set_refund` and `sstore_reset_refund` GasIds so that `sstore_refund` no longer depends on `sstore_set_without_load_cost` and `sstore_reset_without_cold_load_cost` which are used in `sstore_dynamic_gas`. This allows the two functions to have independent gas parameters while maintaining the same values. --- .../context/interface/src/cfg/gas_params.rs | 50 +++++++++++++++++-- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/crates/context/interface/src/cfg/gas_params.rs b/crates/context/interface/src/cfg/gas_params.rs index ca7c52a451..a646fc97d5 100644 --- a/crates/context/interface/src/cfg/gas_params.rs +++ b/crates/context/interface/src/cfg/gas_params.rs @@ -220,6 +220,12 @@ impl GasParams { gas::SSTORE_SET - gas::SSTORE_RESET; // SSTORE RESET Is covered in SSTORE_STATIC. table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = 0; + // SSTORE SET REFUND (same as sstore_set_without_load_cost but used only in sstore_refund) + table[GasId::sstore_set_refund().as_usize()] = + table[GasId::sstore_set_without_load_cost().as_usize()]; + // SSTORE RESET REFUND (same as sstore_reset_without_cold_load_cost but used only in sstore_refund) + table[GasId::sstore_reset_refund().as_usize()] = + table[GasId::sstore_reset_without_cold_load_cost().as_usize()]; // SSTORE CLEARING SLOT REFUND table[GasId::sstore_clearing_slot_refund().as_usize()] = 15000; table[GasId::selfdestruct_refund().as_usize()] = 24000; @@ -251,6 +257,10 @@ impl GasParams { gas::SSTORE_SET - gas::ISTANBUL_SLOAD_GAS; table[GasId::sstore_reset_without_cold_load_cost().as_usize()] = gas::SSTORE_RESET - gas::ISTANBUL_SLOAD_GAS; + table[GasId::sstore_set_refund().as_usize()] = + table[GasId::sstore_set_without_load_cost().as_usize()]; + table[GasId::sstore_reset_refund().as_usize()] = + table[GasId::sstore_reset_without_cold_load_cost().as_usize()]; table[GasId::tx_token_non_zero_byte_multiplier().as_usize()] = gas::NON_ZERO_BYTE_MULTIPLIER_ISTANBUL; } @@ -268,6 +278,10 @@ impl GasParams { gas::WARM_SSTORE_RESET - gas::WARM_STORAGE_READ_COST; table[GasId::sstore_set_without_load_cost().as_usize()] = gas::SSTORE_SET - gas::WARM_STORAGE_READ_COST; + table[GasId::sstore_set_refund().as_usize()] = + table[GasId::sstore_set_without_load_cost().as_usize()]; + table[GasId::sstore_reset_refund().as_usize()] = + table[GasId::sstore_reset_without_cold_load_cost().as_usize()]; table[GasId::tx_access_list_address_cost().as_usize()] = gas::ACCESS_LIST_ADDRESS; table[GasId::tx_access_list_storage_key_cost().as_usize()] = @@ -389,6 +403,18 @@ impl GasParams { self.get(GasId::sstore_clearing_slot_refund()) } + /// SSTORE set refund. Used in sstore_refund for SSTORE_SET_GAS - SLOAD_GAS. + #[inline] + pub fn sstore_set_refund(&self) -> u64 { + self.get(GasId::sstore_set_refund()) + } + + /// SSTORE reset refund. Used in sstore_refund for SSTORE_RESET_GAS - SLOAD_GAS. + #[inline] + pub fn sstore_reset_refund(&self) -> u64 { + self.get(GasId::sstore_reset_refund()) + } + /// Dynamic gas cost for SSTORE opcode. /// /// Dynamic gas cost is gas that needs input from SSTORE operation to be calculated. @@ -469,11 +495,11 @@ impl GasParams { // If original value is 0 if vals.is_original_zero() { // add SSTORE_SET_GAS - SLOAD_GAS to refund counter. - refund += self.sstore_set_without_load_cost() as i64; + refund += self.sstore_set_refund() as i64; // Otherwise } else { // add SSTORE_RESET_GAS - SLOAD_GAS gas to refund counter. - refund += self.sstore_reset_without_cold_load_cost() as i64; + refund += self.sstore_reset_refund() as i64; } } refund @@ -827,6 +853,8 @@ impl GasId { x if x == Self::tx_base_stipend().as_u8() => "tx_base_stipend", x if x == Self::tx_create_cost().as_u8() => "tx_create_cost", x if x == Self::tx_initcode_cost().as_u8() => "tx_initcode_cost", + x if x == Self::sstore_set_refund().as_u8() => "sstore_set_refund", + x if x == Self::sstore_reset_refund().as_u8() => "sstore_reset_refund", _ => "unknown", } } @@ -884,6 +912,8 @@ impl GasId { "tx_base_stipend" => Some(Self::tx_base_stipend()), "tx_create_cost" => Some(Self::tx_create_cost()), "tx_initcode_cost" => Some(Self::tx_initcode_cost()), + "sstore_set_refund" => Some(Self::sstore_set_refund()), + "sstore_reset_refund" => Some(Self::sstore_reset_refund()), _ => None, } } @@ -1070,6 +1100,16 @@ impl GasId { pub const fn tx_initcode_cost() -> GasId { Self::new(36) } + + /// SSTORE set refund. Used in sstore_refund for SSTORE_SET_GAS - SLOAD_GAS refund calculation. + pub const fn sstore_set_refund() -> GasId { + Self::new(37) + } + + /// SSTORE reset refund. Used in sstore_refund for SSTORE_RESET_GAS - SLOAD_GAS refund calculation. + pub const fn sstore_reset_refund() -> GasId { + Self::new(38) + } } #[cfg(test)] @@ -1112,11 +1152,11 @@ mod tests { "Not all unique names are resolvable via from_str" ); - // We should have exactly 36 known GasIds (based on the indices 1-36 used) + // We should have exactly 38 known GasIds (based on the indices 1-38 used) assert_eq!( unique_names.len(), - 36, - "Expected 36 unique GasIds, found {}", + 38, + "Expected 38 unique GasIds, found {}", unique_names.len() ); } From 3d345be02998aaff78b1495b8921a0e47bd5bf3a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 15 Jan 2026 10:46:20 +0100 Subject: [PATCH 123/127] chore: bump alloy and do cargo update (#3311) --- Cargo.lock | 1229 ++++++++++++++++++++++++---------------------------- Cargo.toml | 30 +- 2 files changed, 572 insertions(+), 687 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9820c7f05a..62bf536f1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,21 +2,6 @@ # It is not intended for manual editing. version = 4 -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - -[[package]] -name = "adler2" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" - [[package]] name = "ahash" version = "0.8.12" @@ -31,9 +16,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -46,9 +31,9 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "alloy-chains" -version = "0.2.9" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8ff73a143281cb77c32006b04af9c047a6b8fe5860e85a88ad325328965355" +checksum = "25db5bcdd086f0b1b9610140a12c59b757397be90bd130d8d836fc8da0815a34" dependencies = [ "alloy-primitives", "num_enum", @@ -57,9 +42,9 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e318e25fb719e747a7e8db1654170fc185024f3ed5b10f86c08d448a912f6e2" +checksum = "12870ab65b131f609257436935047eec3cfabee8809732f6bf5a69fe2a18cf2e" dependencies = [ "alloy-eips", "alloy-primitives", @@ -84,9 +69,9 @@ dependencies = [ [[package]] name = "alloy-consensus-any" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "364380a845193a317bcb7a5398fc86cdb66c47ebe010771dde05f6869bf9e64a" +checksum = "47c66b14d2187de0c4efe4ef678aaa57a6a34cccdbea3a0773627fac9bd128f4" dependencies = [ "alloy-consensus", "alloy-eips", @@ -149,9 +134,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c4d7c5839d9f3a467900c625416b24328450c65702eb3d8caff8813e4d1d33" +checksum = "f076d25ddfcd2f1cbcc234e072baf97567d1df0e3fccdc1f8af8cc8b18dc6299" dependencies = [ "alloy-eip2124", "alloy-eip2930", @@ -172,9 +157,9 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bfca3dbbcb7498f0f60e67aff2ad6aff57032e22eb2fd03189854be11a22c03" +checksum = "84e3cf01219c966f95a460c95f1d4c30e12f6c18150c21a30b768af2a2a29142" dependencies = [ "alloy-primitives", "alloy-sol-type-parser", @@ -184,9 +169,9 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f72cf87cda808e593381fb9f005ffa4d2475552b7a6c5ac33d087bf77d82abd0" +checksum = "250dbd8496f04eabe997e6e4c5186a0630b8bc3dbe7552e1fd917d491ef811e9" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -199,9 +184,9 @@ dependencies = [ [[package]] name = "alloy-network" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12aeb37b6f2e61b93b1c3d34d01ee720207c76fe447e2a2c217e433ac75b17f5" +checksum = "fd45cdac957d1fa1d0c18f54f262350eb72f1adc38dd1f8b15f33f0747c6a60c" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -225,9 +210,9 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd29ace62872083e30929cd9b282d82723196d196db589f3ceda67edcc05552" +checksum = "fba5c43e055effb5bd33dbc74b1ab7fe0f367d8801a25af9e7c716b3ef5e440b" dependencies = [ "alloy-consensus", "alloy-eips", @@ -238,9 +223,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c850e6ccbd34b8a463a1e934ffc8fc00e1efc5e5489f2ad82d7797949f3bd4e" +checksum = "f6a0fb18dd5fb43ec5f0f6a20be1ce0287c79825827de5744afaa6c957737c33" dependencies = [ "alloy-rlp", "arbitrary", @@ -248,10 +233,10 @@ dependencies = [ "cfg-if", "const-hex", "derive_more", - "foldhash 0.2.0", - "getrandom 0.3.3", + "foldhash", + "getrandom 0.3.4", "hashbrown 0.16.1", - "indexmap 2.11.0", + "indexmap 2.13.0", "itoa", "k256", "keccak-asm", @@ -269,9 +254,9 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b710636d7126e08003b8217e24c09f0cca0b46d62f650a841736891b1ed1fc1" +checksum = "9e87a90cacc27dffd91fa6440145934a782227d31b9876444c5924d3607084ea" dependencies = [ "alloy-chains", "alloy-consensus", @@ -325,14 +310,14 @@ checksum = "64b728d511962dda67c1bc7ea7c03736ec275ed2cf4c35d9585298ac9ccf3b73" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "alloy-rpc-client" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0882e72d2c1c0c79dcf4ab60a67472d3f009a949f774d4c17d0bdb669cfde05" +checksum = "57a65bb9060e43e9738bbd7c30d742ed962d609f2123a665bbdab7e6e0f13fd3" dependencies = [ "alloy-json-rpc", "alloy-primitives", @@ -353,9 +338,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-any" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a63fb40ed24e4c92505f488f9dd256e2afaed17faa1b7a221086ebba74f4122" +checksum = "8faa6f22068857f58579271b15e042f4725ad35cdce2ed4778ba32ffd3102b92" dependencies = [ "alloy-consensus-any", "alloy-rpc-types-eth", @@ -364,9 +349,9 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eae0c7c40da20684548cbc8577b6b7447f7bf4ddbac363df95e3da220e41e72" +checksum = "1ec734cce11f7fe889950b36b51589397528b26beb6f890834a2131ee9f174d7" dependencies = [ "alloy-consensus", "alloy-consensus-any", @@ -385,9 +370,9 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0df1987ed0ff2d0159d76b52e7ddfc4e4fbddacc54d2fbee765e0d14d7c01b5" +checksum = "27f076bfd74fccc63d50546e1765359736357a953de2eb778b7b6191571735e6" dependencies = [ "alloy-primitives", "serde", @@ -396,9 +381,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff69deedee7232d7ce5330259025b868c5e6a52fa8dffda2c861fb3a5889b24" +checksum = "d80748c209a68421ab6f737828ce6ede7543569a5cad099c1ec16fc1baa05620" dependencies = [ "alloy-primitives", "async-trait", @@ -411,9 +396,9 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72cfe0be3ec5a8c1a46b2e5a7047ed41121d360d97f4405bb7c1c784880c86cb" +checksum = "17eb1eb39351b4bf20bb0710d8d3a91eb7918d3f3de2f3835f556842e33865cb" dependencies = [ "alloy-consensus", "alloy-network", @@ -427,41 +412,41 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2218e3aeb3ee665d117fdf188db0d5acfdc3f7b7502c827421cb78f26a2aec0" +checksum = "09eb18ce0df92b4277291bbaa0ed70545d78b02948df756bbd3d6214bf39a218" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "alloy-sol-macro-expander" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b231cb8cc48e66dd1c6e11a1402f3ac86c3667cbc13a6969a0ac030ba7bb8c88" +checksum = "95d9fa2daf21f59aa546d549943f10b5cce1ae59986774019fbedae834ffe01b" dependencies = [ "alloy-sol-macro-input", "const-hex", "heck", - "indexmap 2.11.0", + "indexmap 2.13.0", "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49a522d79929c1bf0152b07567a38f7eaed3ab149e53e7528afa78ff11994668" +checksum = "9396007fe69c26ee118a19f4dee1f5d1d6be186ea75b3881adf16d87f8444686" dependencies = [ "const-hex", "dunce", @@ -469,15 +454,15 @@ dependencies = [ "macro-string", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", "syn-solidity", ] [[package]] name = "alloy-sol-type-parser" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475c459859c8d9428af6ff3736614655a57efda8cc435a3b8b4796fa5ac1dd0" +checksum = "af67a0b0dcebe14244fc92002cd8d96ecbf65db4639d479f5fcd5805755a4c27" dependencies = [ "serde", "winnow", @@ -485,9 +470,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35287d9d821d5f26011bcd8d9101340898f761c9933cf50fca689bb7ed62fdeb" +checksum = "09aeea64f09a7483bdcd4193634c7e5cf9fd7775ee767585270cd8ce2d69dc95" dependencies = [ "alloy-json-abi", "alloy-primitives", @@ -497,9 +482,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be98b07210d24acf5b793c99b759e9a696e4a2e67593aec0487ae3b3e1a2478c" +checksum = "4a0c1a0288cdff6ee2b2c2c98ab42889d221ca8a9ee4120ede59b5449e0dcb20" dependencies = [ "alloy-json-rpc", "auto_impl", @@ -520,9 +505,9 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4198a1ee82e562cab85e7f3d5921aab725d9bd154b6ad5017f82df1695877c97" +checksum = "36dfa207caf6b528b9466c714626f5b2dfd5e8d4595a74631d5670672dac102b" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -535,9 +520,9 @@ dependencies = [ [[package]] name = "alloy-trie" -version = "0.9.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3412d52bb97c6c6cc27ccc28d4e6e8cf605469101193b50b0bd5813b1f990b5" +checksum = "428aa0f0e0658ff091f8f667c406e034b431cb10abd39de4f507520968acc499" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -551,22 +536,16 @@ dependencies = [ [[package]] name = "alloy-tx-macros" -version = "1.1.3" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "333544408503f42d7d3792bfc0f7218b643d968a03d2c0ed383ae558fb4a76d0" +checksum = "bb0d567f4830dea921868c7680004ae0c7f221b05e6477db6c077c7953698f56" dependencies = [ - "darling 0.21.3", + "darling", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -584,9 +563,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "43d5b281e737544384e969a5ccad3f1cdd24b48086a0fc1b2a5262a26b8f4f4a" dependencies = [ "anstyle", "anstyle-parse", @@ -599,9 +578,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "5192cca8006f1fd4f7237516f40fa183bb07f8fbdfedaa0036de5ea9b0b45e78" [[package]] name = "anstyle-parse" @@ -614,29 +593,29 @@ dependencies = [ [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anyhow" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" [[package]] name = "approx" @@ -786,7 +765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62945a2f7e6de02a31fe400aa489f0e0f5b2502e69f95f853adb82a96c7a6b60" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -824,7 +803,7 @@ dependencies = [ "num-traits", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -913,7 +892,7 @@ checksum = "213888f660fddcca0d257e88e54ac05bca01885f258ccdf695bafd77031bb69d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -980,7 +959,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -991,7 +970,7 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1018,7 +997,7 @@ checksum = "ffdcb70bdbc4d478427380519163274ac86e52916e10f0a8889adf0f96d3fee7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1027,21 +1006,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" -[[package]] -name = "backtrace" -version = "0.3.75" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" -dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", -] - [[package]] name = "base16ct" version = "0.2.0" @@ -1056,18 +1020,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" - -[[package]] -name = "bincode" -version = "1.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" -dependencies = [ - "serde", -] +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bit-set" @@ -1086,15 +1041,15 @@ checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] name = "bitcoin-io" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b47c4ab7a93edb0c7198c5535ed9b52b63095f4e9b45279c6736cec4b856baf" +checksum = "2dee39a0ee5b4095224a0cfc6bf4cc1baf0f9624b96b367e53b66d974e51d953" [[package]] name = "bitcoin_hashes" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb18c03d0db0247e147a21a6faafd5a7eb851c743db062de72018b6b7e8e4d16" +checksum = "26ec84b80c482df901772e931a9a681e26a1b9ee2302edeff23cb30328745c8b" dependencies = [ "bitcoin-io", "hex-conservative", @@ -1102,11 +1057,11 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.9.3" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d" +checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -1133,9 +1088,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fd49896f12ac9b6dcd7a5998466b9b58263a695a3dd1ecc1aaca2e12a90b080" +checksum = "dcdb4c7013139a150f9fc55d123186dbfaba0d912817466282c73ac49e71fb45" dependencies = [ "cc", "glob", @@ -1163,14 +1118,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" [[package]] name = "byte-slice-cast" @@ -1186,18 +1141,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" dependencies = [ "serde", ] [[package]] name = "c-kzg" -version = "2.1.4" +version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "137a2a2878ed823ef1bd73e5441e245602aae5360022113b8ad259ca4b5b8727" +checksum = "e00bf4b112b07b505472dbefd19e37e53307e2bfed5a79e0cc161d58ccd0e687" dependencies = [ "blst", "cc", @@ -1216,18 +1171,19 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.2.34" +version = "1.2.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc" +checksum = "cd4932aefd12402b36c60956a4fe0035421f544799057659ff86f923657aada3" dependencies = [ + "find-msvc-tools", "shlex", ] [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -1237,11 +1193,10 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2" dependencies = [ - "android-tzdata", "iana-time-zone", "num-traits", "serde", @@ -1277,9 +1232,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.46" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" +checksum = "c6e6ff9dcd79cff5cd969a17a545d79e84ab086e444102a591e288a8aa3ce394" dependencies = [ "clap_builder", "clap_derive", @@ -1287,9 +1242,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.46" +version = "4.5.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" +checksum = "fa42cf4d2b7a41bc8f663a7cab4031ebafa1bf3875705bfaf8466dc60ab52c00" dependencies = [ "anstream", "anstyle", @@ -1299,56 +1254,58 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.45" +version = "4.5.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" +checksum = "2a0b5487afeab2deb2ff4e03a807ad1a03ac532ff5a2cee5d86884440c7f7671" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "c3e64b0cc0439b12df2fa678eae89a1c56a529fd067a9115f7827f1fffd22b32" [[package]] name = "codspeed" -version = "3.0.5" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35584c5fcba8059780748866387fb97c5a203bcfc563fc3d0790af406727a117" +checksum = "5f0d98d97fd75ca4489a1a0997820a6521531085e7c8a98941bd0e1264d567dd" dependencies = [ "anyhow", - "bincode", + "cc", "colored", + "getrandom 0.2.17", "glob", "libc", "nix", "serde", "serde_json", "statrs", - "uuid", ] [[package]] name = "codspeed-criterion-compat" -version = "3.0.5" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78f6c1c6bed5fd84d319e8b0889da051daa361c79b7709c9394dfe1a882bba67" +checksum = "d16fe2db207123f7b3a3b5cfff0c22f99469f7534145f3573f57f4c8a5653c2c" dependencies = [ + "clap", "codspeed", "codspeed-criterion-compat-walltime", "colored", + "regex", ] [[package]] name = "codspeed-criterion-compat-walltime" -version = "3.0.5" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c989289ce6b1cbde72ed560496cb8fbf5aa14d5ef5666f168e7f87751038352e" +checksum = "b035c7f9846b143aeabb3833f5b584023eb97b43ecbff3d997db74c4372df2bd" dependencies = [ "anes", "cast", @@ -1389,28 +1346,27 @@ dependencies = [ [[package]] name = "console" -version = "0.16.0" +version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e09ced7ebbccb63b4c65413d821f2e00ce54c5ca4514ddc6b3c892fdbcbc69d" +checksum = "03e45a4a8926227e4197636ba97a9fc9b00477e9f4bd711395687c5f0734bec4" dependencies = [ "encode_unicode", "libc", "once_cell", "unicode-width", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "const-hex" -version = "1.15.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dccd746bf9b1038c0507b7cec21eb2b11222db96a2902c96e8c185d6d20fb9c4" +checksum = "3bb320cac8a0750d7f25280aa97b09c26edfe161164238ecbbb31092b079e735" dependencies = [ "cfg-if", "cpufeatures", - "hex", "proptest", - "serde", + "serde_core", ] [[package]] @@ -1421,9 +1377,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" [[package]] name = "const_format" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126f97965c8ad46d6d9163268ff28432e8f6a1196a55578867832e3049df63dd" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ "const_format_proc_macros", ] @@ -1439,6 +1395,15 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "convert_case" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] + [[package]] name = "core-foundation" version = "0.9.4" @@ -1466,9 +1431,9 @@ dependencies = [ [[package]] name = "crc" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675" +checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d" dependencies = [ "crc-catalog", ] @@ -1544,57 +1509,33 @@ dependencies = [ [[package]] name = "csv" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] -[[package]] -name = "darling" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" -dependencies = [ - "darling_core 0.20.11", - "darling_macro 0.20.11", -] - [[package]] name = "darling" version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "darling_core 0.21.3", - "darling_macro 0.21.3", -] - -[[package]] -name = "darling_core" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" -dependencies = [ - "fnv", - "ident_case", - "proc-macro2", - "quote", - "strsim", - "syn 2.0.106", + "darling_core", + "darling_macro", ] [[package]] @@ -1609,18 +1550,7 @@ dependencies = [ "quote", "serde", "strsim", - "syn 2.0.106", -] - -[[package]] -name = "darling_macro" -version = "0.20.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" -dependencies = [ - "darling_core 0.20.11", - "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1629,9 +1559,9 @@ version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "darling_core 0.21.3", + "darling_core", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1660,12 +1590,12 @@ dependencies = [ [[package]] name = "deranged" -version = "0.4.0" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", - "serde", + "serde_core", ] [[package]] @@ -1687,7 +1617,7 @@ checksum = "ef941ded77d15ca19b40374869ac6000af1c9f2a4c0f3d4c70926287e6364a8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1698,27 +1628,29 @@ checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "derive_more" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" dependencies = [ "derive_more-impl", ] [[package]] name = "derive_more-impl" -version = "2.0.1" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ + "convert_case", "proc-macro2", "quote", - "syn 2.0.106", + "rustc_version 0.4.1", + "syn 2.0.114", "unicode-xid", ] @@ -1751,7 +1683,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1790,7 +1722,7 @@ dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1830,22 +1762,22 @@ checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" [[package]] name = "enum-ordinalize" -version = "4.3.0" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5" +checksum = "4a1091a7bb1f8f2c4b28f1fe2cef4980ca2d410a3d727d67ecc3178c9b0800f0" dependencies = [ "enum-ordinalize-derive", ] [[package]] name = "enum-ordinalize-derive" -version = "4.3.1" +version = "4.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" +checksum = "8ca9601fb2d62598ee17836250842873a413586e5d7ed88b356e38ddbb0ec631" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -1856,12 +1788,12 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -1997,6 +1929,12 @@ dependencies = [ "subtle", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f449e6c6c08c865631d4890cfacf252b3d396c9bcc83adb6623cdb02a8336c41" + [[package]] name = "fixed-hash" version = "0.8.0" @@ -2015,12 +1953,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -2113,7 +2045,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2160,9 +2092,9 @@ checksum = "42012b0f064e01aa58b545fe3727f90f7dd4020f4a3ea735b50344965f5a57e9" [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -2171,33 +2103,27 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", "r-efi", - "wasi 0.14.2+wasi-0.2.4", + "wasip2", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -2206,9 +2132,9 @@ checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" [[package]] name = "gmp-mpfr-sys" -version = "1.6.7" +version = "1.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a636fb6a653382a379ee1e5593dacdc628667994167024c143214cafd40c1a86" +checksum = "60f8970a75c006bb2f8ae79c6768a116dd215fa8346a87aed99bf9d82ca43394" dependencies = [ "libc", "windows-sys 0.60.2", @@ -2227,12 +2153,13 @@ dependencies = [ [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "cfg-if", "crunchy", + "zerocopy", ] [[package]] @@ -2260,8 +2187,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ "allocator-api2", - "equivalent", - "foldhash 0.1.5", ] [[package]] @@ -2270,7 +2195,9 @@ version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ - "foldhash 0.2.0", + "allocator-api2", + "equivalent", + "foldhash", "serde", "serde_core", ] @@ -2292,15 +2219,12 @@ name = "hex" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" -dependencies = [ - "serde", -] [[package]] name = "hex-conservative" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5313b072ce3c597065a808dbf612c4c8e8590bdbf8b579508bf7a762c5eae6cd" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" dependencies = [ "arrayvec", ] @@ -2316,12 +2240,11 @@ dependencies = [ [[package]] name = "http" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -2356,9 +2279,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" dependencies = [ "atomic-waker", "bytes", @@ -2393,9 +2316,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" dependencies = [ "base64", "bytes", @@ -2417,9 +2340,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -2441,9 +2364,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" dependencies = [ "displaydoc", "potential_utf", @@ -2454,9 +2377,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" dependencies = [ "displaydoc", "litemap", @@ -2467,11 +2390,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -2482,42 +2404,38 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", "yoke", "zerofrom", @@ -2569,7 +2487,7 @@ checksum = "a0eb5a3343abf848c0984fe4604b2b105da9539376e24fc0a3b0007411ae4fd9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -2585,21 +2503,22 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "arbitrary", "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "serde", + "serde_core", ] [[package]] name = "indicatif" -version = "0.18.0" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70a646d946d06bedbbc4cac4c218acf4bbf2d87757a784857025f4d447e4e1cd" +checksum = "9375e112e4b463ec1b1c6c011953545c65a30164fbab5b581df32b3abf0dcb88" dependencies = [ "console", "portable-atomic", @@ -2608,17 +2527,6 @@ dependencies = [ "web-time", ] -[[package]] -name = "io-uring" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b" -dependencies = [ - "bitflags", - "cfg-if", - "libc", -] - [[package]] name = "ipnet" version = "2.11.0" @@ -2627,9 +2535,9 @@ checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "iri-string" -version = "0.7.8" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" dependencies = [ "memchr", "serde", @@ -2637,20 +2545,20 @@ dependencies = [ [[package]] name = "is-terminal" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" +checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -2681,15 +2589,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" [[package]] name = "js-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8" dependencies = [ "once_cell", "wasm-bindgen", @@ -2739,9 +2647,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.175" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libm" @@ -2751,39 +2659,38 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.27" +version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] name = "lru" -version = "0.13.0" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227748d55f2f0ab4735d87fd623798cb6b664512fe979705f829c9f81c934465" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -2794,33 +2701,24 @@ checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "memchr" -version = "2.7.5" +version = "2.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "miniz_oxide" -version = "0.8.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" -dependencies = [ - "adler2", -] +checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "mio" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -2842,9 +2740,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.29.0" +version = "0.30.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" +checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" dependencies = [ "bitflags", "cfg-if", @@ -2944,9 +2842,9 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a973b4e44ce6cad84ce69d797acf9a044532e4184c4f267913d1b546a0727b7a" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ "num_enum_derive", "rustversion", @@ -2954,21 +2852,21 @@ dependencies = [ [[package]] name = "num_enum_derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e878c846a8abae00dd069496dbe8751b16ac1c3d6bd2a7283a938e8228f90d" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "nybbles" -version = "0.4.3" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63cb50036b1ad148038105af40aaa70ff24d8a14fbc44ae5c914e1348533d12e" +checksum = "7b5676b5c379cf5b03da1df2b3061c4a4e2aa691086a56ac923e08c143f53f59" dependencies = [ "alloy-rlp", "cfg-if", @@ -2978,15 +2876,6 @@ dependencies = [ "smallvec", ] -[[package]] -name = "object" -version = "0.36.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" -dependencies = [ - "memchr", -] - [[package]] name = "once_cell" version = "1.21.3" @@ -2995,9 +2884,9 @@ checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "oorandom" @@ -3021,9 +2910,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ "bitflags", "cfg-if", @@ -3042,7 +2931,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3053,9 +2942,9 @@ checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.111" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321" dependencies = [ "cc", "libc", @@ -3100,14 +2989,14 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -3115,15 +3004,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link", ] [[package]] @@ -3140,12 +3029,11 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.1" +version = "2.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "2c9eb05c21a464ea704b53158d358a31e6425db2f63a1a7312268b05fe2b75f7" dependencies = [ "memchr", - "thiserror", "ucd-trie", ] @@ -3180,7 +3068,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3209,7 +3097,7 @@ checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3279,15 +3167,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "f89776e4d69bb58bc6993e99ffa1d11f228b839984854c7daeb5d37f87cbe950" [[package]] name = "potential_utf" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" dependencies = [ "zerovec", ] @@ -3329,9 +3217,9 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983" dependencies = [ "toml_edit", ] @@ -3355,28 +3243,27 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" dependencies = [ "unicode-ident", ] [[package]] name = "proptest" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fcdab19deb5195a31cf7726a210015ff1496ba1464fd42cb4f537b8b01b471f" +checksum = "bee689443a2bd0a16ab0348b52ee43e3b2d1b1f931c8aa5c9f8de4c86fbe8c40" dependencies = [ "bit-set", "bit-vec", "bitflags", - "lazy_static", "num-traits", "rand 0.9.2", "rand_chacha 0.9.0", @@ -3395,7 +3282,7 @@ checksum = "095a99f75c69734802359b682be8daaf8980296731f6470434ea2c652af1dd30" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -3406,9 +3293,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.40" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" dependencies = [ "proc-macro2", ] @@ -3444,7 +3331,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", "serde", ] @@ -3465,7 +3352,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -3474,16 +3361,16 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "serde", ] @@ -3493,14 +3380,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "513962919efc330f829edb2535844d1b912b0fbe2ca165d613e4e8788bb05a5a" dependencies = [ - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] name = "rapidhash" -version = "4.1.1" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8e65c75143ce5d47c55b510297eeb1182f3c739b6043c537670e9fc18612dae" +checksum = "5d8b5b858a440a0bc02625b62dd95131b9201aa9f69f411195dd4a7cfb1de3d7" dependencies = [ "rand 0.9.2", "rustversion", @@ -3528,38 +3415,38 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ "bitflags", ] [[package]] name = "ref-cast" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", "memchr", @@ -3569,9 +3456,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", "memchr", @@ -3580,9 +3467,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" [[package]] name = "relative-path" @@ -3592,9 +3479,9 @@ checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64", "bytes", @@ -3923,20 +3810,21 @@ dependencies = [ "regex", "relative-path", "rustc_version 0.4.1", - "syn 2.0.106", + "syn 2.0.114", "unicode-ident", ] [[package]] name = "ruint" -version = "1.16.0" +version = "1.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecb38f82477f20c5c3d62ef52d7c4e536e38ea9b73fb570a20c5cae0e14bcf6" +checksum = "c141e807189ad38a07276942c6623032d3753c8859c146104ac2e4d68865945a" dependencies = [ "alloy-rlp", "arbitrary", "ark-ff 0.3.0", "ark-ff 0.4.2", + "ark-ff 0.5.0", "bytes", "fastrlp 0.3.1", "fastrlp 0.4.0", @@ -3950,7 +3838,7 @@ dependencies = [ "rand 0.9.2", "rlp", "ruint-macro", - "serde", + "serde_core", "valuable", "zeroize", ] @@ -3961,12 +3849,6 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" version = "2.1.1" @@ -3997,27 +3879,27 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "semver 1.0.26", + "semver 1.0.27", ] [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "rustls-pki-types" -version = "1.12.0" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "21e6f2ab2928ca4291b86736a8bd920a277a399bba1589409d72154ff87c1282" dependencies = [ "zeroize", ] @@ -4030,9 +3912,9 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "rusty-fork" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f" +checksum = "cc6bf79ff24e648f6da1f8d1f011e9cac26491b619e6b9280f2b47f1774e6ee2" dependencies = [ "fnv", "quick-error", @@ -4042,9 +3924,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" [[package]] name = "same-file" @@ -4057,11 +3939,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -4078,9 +3960,9 @@ dependencies = [ [[package]] name = "schemars" -version = "1.0.4" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "54e910108742c57a770f492731f99be216a52fadd361b06c8fb59d74ccc267d2" dependencies = [ "dyn-clone", "ref-cast", @@ -4165,9 +4047,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.14.0" +version = "2.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" dependencies = [ "core-foundation-sys", "libc", @@ -4184,9 +4066,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" [[package]] name = "semver-parser" @@ -4224,20 +4106,21 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.13.0", "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -4254,19 +4137,18 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.14.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7" dependencies = [ "base64", "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.11.0", + "indexmap 2.13.0", "schemars 0.9.0", - "schemars 1.0.4", - "serde", - "serde_derive", + "schemars 1.2.0", + "serde_core", "serde_json", "serde_with_macros", "time", @@ -4274,14 +4156,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.14.0" +version = "3.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c" dependencies = [ - "darling 0.20.11", + "darling", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4374,12 +4256,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -4400,9 +4282,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -4444,7 +4326,7 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4479,9 +4361,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" dependencies = [ "proc-macro2", "quote", @@ -4490,14 +4372,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "1.5.0" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60ceeb7c95a4536de0c0e1649bd98d1a72a4bb9590b1f3e45a8a0bfdb7c188c0" +checksum = "5f92d01b5de07eaf324f7fca61cc6bd3d82bbc1de5b6c963e6fe79e86f36580d" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4517,7 +4399,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4528,35 +4410,35 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tempfile" -version = "3.21.0" +version = "3.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "655da9c7eb6305c55742045d5a8d2037996d61d8de95806335c7c86ce0f82e9c" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4570,30 +4452,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.41" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +checksum = "f9e442fc33d7fdb45aa9bfeb312c095964abdf596f7567261062b2a7107aaabd" dependencies = [ "deranged", "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.4" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" +checksum = "8b36ee98fd31ec7426d599183e8fe26932a8dc1fb76ddb6214d05493377d34ca" [[package]] name = "time-macros" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +checksum = "71e552d1249bf61ac2a52db88179fd0673def1e1ad8243a00d9ec9ed71fee3dd" dependencies = [ "num-conv", "time-core", @@ -4610,9 +4492,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" dependencies = [ "displaydoc", "zerovec", @@ -4630,31 +4512,28 @@ dependencies = [ [[package]] name = "tokio" -version = "1.47.1" +version = "1.49.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" +checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" dependencies = [ - "backtrace", "bytes", - "io-uring", "libc", "mio", "pin-project-lite", - "slab", "socket2", "tokio-macros", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -4669,9 +4548,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" dependencies = [ "futures-core", "pin-project-lite", @@ -4681,9 +4560,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -4694,26 +4573,39 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.7.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +dependencies = [ + "serde_core", +] [[package]] name = "toml_edit" -version = "0.22.27" +version = "0.23.10+spec-1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" +checksum = "84c8b9f757e028cee9fa244aea147aab2a9ec09d5325a9b01e0a49730c2b5269" dependencies = [ - "indexmap 2.11.0", + "indexmap 2.13.0", "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_parser" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +dependencies = [ "winnow", ] [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", @@ -4726,9 +4618,9 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ "bitflags", "bytes", @@ -4756,9 +4648,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -4767,20 +4659,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -4813,9 +4705,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" [[package]] name = "ucd-trie" @@ -4843,15 +4735,21 @@ checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" [[package]] name = "unicode-ident" -version = "1.0.18" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -4861,15 +4759,15 @@ checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "unit-prefix" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "323402cff2dd658f39ca17c789b502021b3f18707c91cdf22e3838e1b4023817" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -4889,17 +4787,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" -[[package]] -name = "uuid" -version = "1.18.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be" -dependencies = [ - "getrandom 0.3.3", - "js-sys", - "wasm-bindgen", -] - [[package]] name = "valuable" version = "0.1.1" @@ -4953,45 +4840,32 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" +name = "wasip2" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ - "wit-bindgen-rt", + "wit-bindgen", ] [[package]] name = "wasm-bindgen" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd" dependencies = [ "cfg-if", "once_cell", "rustversion", "wasm-bindgen-macro", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.100" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" -dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.50" +version = "0.4.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c" dependencies = [ "cfg-if", "js-sys", @@ -5002,9 +4876,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -5012,31 +4886,31 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.114", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.100" +version = "0.2.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4" dependencies = [ "unicode-ident", ] [[package]] name = "wasmtimer" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8d49b5d6c64e8558d9b1b065014426f35c18de636895d24893dbbd329743446" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" dependencies = [ "futures", "js-sys", @@ -5048,9 +4922,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.77" +version = "0.3.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac" dependencies = [ "js-sys", "wasm-bindgen", @@ -5068,18 +4942,18 @@ dependencies = [ [[package]] name = "winapi-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "windows-core" -version = "0.61.2" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", @@ -5090,46 +4964,46 @@ dependencies = [ [[package]] name = "windows-implement" -version = "0.60.0" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "windows-link" -version = "0.1.3" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ "windows-link", ] [[package]] name = "windows-strings" -version = "0.4.2" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ "windows-link", ] @@ -5149,7 +5023,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", ] [[package]] @@ -5170,19 +5053,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ "windows-link", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] [[package]] @@ -5193,9 +5076,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -5205,9 +5088,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -5217,9 +5100,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -5229,9 +5112,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -5241,9 +5124,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -5253,9 +5136,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -5265,9 +5148,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -5277,33 +5160,30 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] name = "winnow" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" dependencies = [ "memchr", ] [[package]] -name = "wit-bindgen-rt" -version = "0.39.0" +name = "wit-bindgen" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" [[package]] name = "wyz" @@ -5316,11 +5196,10 @@ dependencies = [ [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" dependencies = [ - "serde", "stable_deref_trait", "yoke-derive", "zerofrom", @@ -5328,34 +5207,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.26" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +checksum = "668f5168d10b9ee831de31933dc111a459c97ec93225beb307aed970d1372dfd" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.26" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +checksum = "2c7962b26b0a8685668b671ee4b54d007a67d4eaf05fda79ac0ecf41e32270f1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] @@ -5375,35 +5254,35 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" dependencies = [ "zeroize_derive", ] [[package]] name = "zeroize_derive" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" dependencies = [ "displaydoc", "yoke", @@ -5412,9 +5291,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" dependencies = [ "yoke", "zerofrom", @@ -5423,11 +5302,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.114", ] + +[[package]] +name = "zmij" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd8f3f50b848df28f887acb68e41201b5aea6bc8a8dacc00fb40635ff9a72fea" diff --git a/Cargo.toml b/Cargo.toml index e2f10307c8..cb4950f246 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,20 +58,20 @@ op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.1.0", de ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy -alloy-eip2930 = { version = "0.2.1", default-features = false } -alloy-eip7702 = { version = "0.6.1", default-features = false } +alloy-eip2930 = { version = "0.2.3", default-features = false } +alloy-eip7702 = { version = "0.6.3", default-features = false } alloy-eip7928 = { version = "0.3.0", default-features = false } -alloy-primitives = { version = "1.5.0", default-features = false } +alloy-primitives = { version = "1.5.2", default-features = false } # alloy in examples, revme or feature flagged. alloy-rlp = { version = "0.3.12", default-features = false } -alloy-sol-types = { version = "1.5.0", default-features = false } -alloy-consensus = { version = "1.1.3", default-features = false } -alloy-eips = { version = "1.1.3", default-features = false } -alloy-provider = { version = "1.1.3", default-features = false } -alloy-signer = { version = "1.1.3", default-features = false } -alloy-signer-local = { version = "1.1.3", default-features = false } -alloy-transport = { version = "1.1.3", default-features = false } +alloy-sol-types = { version = "1.5.2", default-features = false } +alloy-consensus = { version = "1.4.2", default-features = false } +alloy-eips = { version = "1.4.2", default-features = false } +alloy-provider = { version = "1.4.2", default-features = false } +alloy-signer = { version = "1.4.2", default-features = false } +alloy-signer-local = { version = "1.4.2", default-features = false } +alloy-transport = { version = "1.4.2", default-features = false } # precompiles ark-bls12-381 = { version = "0.5", default-features = false } @@ -97,8 +97,8 @@ paste = "1.0" phf = { version = "0.13", default-features = false } # revme -clap = { version = "4", features = ["derive"] } -criterion = { package = "codspeed-criterion-compat", version = "3.0" } +clap = { version = "4.5", features = ["derive"] } +criterion = { package = "codspeed-criterion-compat", version = "4.2" } # serde serde = { version = "1.0", default-features = false, features = [ @@ -109,15 +109,15 @@ serde_json = { version = "1.0", default-features = false } # misc auto_impl = "1.3.0" -bitflags = { version = "2.9.3", default-features = false } +bitflags = { version = "2.10", default-features = false } cfg-if = { version = "1.0", default-features = false } -derive-where = { version = "1.6.0", default-features = false } +derive-where = { version = "1.6", default-features = false } rand = "0.9" tokio = "1.47" either = { version = "1.15.0", default-features = false } # dev-dependencies -anyhow = "1.0.99" +anyhow = "1.0" eyre = "0.6.12" hash-db = "0.15" indicatif = "0.18" From aea81d0c3072e95258b3981d93fff03e3a4f4000 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 Jan 2026 11:27:23 +0100 Subject: [PATCH 124/127] chore: release (#3175) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 30 +++++++++++++------------- Cargo.toml | 28 ++++++++++++------------ bins/revme/CHANGELOG.md | 30 ++++++++++++++++++++++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 17 +++++++++++++++ crates/bytecode/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 29 +++++++++++++++++++++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 24 +++++++++++++++++++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 29 +++++++++++++++++++++++++ crates/database/Cargo.toml | 2 +- crates/database/interface/CHANGELOG.md | 23 ++++++++++++++++++++ crates/database/interface/Cargo.toml | 2 +- crates/handler/CHANGELOG.md | 29 +++++++++++++++++++++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 16 ++++++++++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 24 +++++++++++++++++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 17 +++++++++++++++ crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 18 ++++++++++++++++ crates/precompile/Cargo.toml | 2 +- crates/primitives/CHANGELOG.md | 14 ++++++++++++ crates/primitives/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 14 ++++++++++++ crates/revm/Cargo.toml | 2 +- crates/state/CHANGELOG.md | 16 ++++++++++++++ crates/state/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 20 +++++++++++++++++ crates/statetest-types/Cargo.toml | 2 +- 32 files changed, 364 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62bf536f1b..3fe1d77510 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2896,7 +2896,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "14.1.0" +version = "14.2.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3515,7 +3515,7 @@ dependencies = [ [[package]] name = "revm" -version = "33.1.0" +version = "33.2.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3535,7 +3535,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.1.1" +version = "7.2.0" dependencies = [ "bitvec", "paste", @@ -3547,7 +3547,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "12.1.0" +version = "13.0.0" dependencies = [ "bitvec", "cfg-if", @@ -3563,7 +3563,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "13.1.0" +version = "14.0.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3577,7 +3577,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "9.0.6" +version = "10.0.0" dependencies = [ "alloy-eips", "alloy-provider", @@ -3593,7 +3593,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "8.0.5" +version = "9.0.0" dependencies = [ "auto_impl", "either", @@ -3620,7 +3620,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "14.1.0" +version = "15.0.0" dependencies = [ "alloy-provider", "alloy-signer", @@ -3641,7 +3641,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "14.1.0" +version = "14.2.0" dependencies = [ "auto_impl", "either", @@ -3658,7 +3658,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "31.1.0" +version = "32.0.0" dependencies = [ "revm-bytecode", "revm-context-interface", @@ -3670,7 +3670,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "31.0.0" +version = "31.1.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3698,7 +3698,7 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "21.0.2" +version = "21.1.0" dependencies = [ "alloy-primitives", "num_enum", @@ -3708,7 +3708,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "8.1.1" +version = "9.0.0" dependencies = [ "alloy-eip7928", "bitflags", @@ -3720,7 +3720,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "13.1.0" +version = "14.0.0" dependencies = [ "alloy-eip7928", "k256", @@ -3737,7 +3737,7 @@ dependencies = [ [[package]] name = "revme" -version = "10.0.2" +version = "11.0.0" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index cb4950f246..fbfa622e2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "33.1.0", default-features = false } -primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.0.2", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.1.1", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "9.0.6", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "8.0.5", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "8.1.1", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "31.1.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.1.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "31.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "13.1.0", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "12.1.0", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "13.1.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "14.1.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.1.0", default-features = false } +revm = { path = "crates/revm", version = "33.2.0", default-features = false } +primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.1.0", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.2.0", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "10.0.0", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "9.0.0", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "9.0.0", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "32.0.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.2.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "31.1.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "14.0.0", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "13.0.0", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "14.0.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "15.0.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.2.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index eb15baf5c0..92ae68ad14 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -7,6 +7,36 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [11.0.0](https://github.com/bluealloy/revm/compare/revme-v10.0.2...revme-v11.0.0) - 2026-01-15 + +### Added + +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- Propagate `map-foldhash` Feature Through Dependency Chain ([#3252](https://github.com/bluealloy/revm/pull/3252)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- DatabaseCommitExt + increment_balances ([#3195](https://github.com/bluealloy/revm/pull/3195)) +- sort accounts by address in blockchaintest output ([#3182](https://github.com/bluealloy/revm/pull/3182)) + +### Fixed + +- incorrect bytecode value in blockchain test error output ([#3288](https://github.com/bluealloy/revm/pull/3288)) +- use expected_exception instead of error field for unexpected_success status ([#3244](https://github.com/bluealloy/revm/pull/3244)) +- deduplicate post-state validation error handling ([#3228](https://github.com/bluealloy/revm/pull/3228)) +- *(revme)* incorrect debug log message in btest ([#3233](https://github.com/bluealloy/revm/pull/3233)) +- *(statetest)* use spec-aware blob base fee update fraction ([#3210](https://github.com/bluealloy/revm/pull/3210)) + +### Other + +- apply improvements from ai-bot labeled PRs ([#3297](https://github.com/bluealloy/revm/pull/3297)) +- *(revme)* consolidate find_all_json_tests into dir_utils ([#3262](https://github.com/bluealloy/revm/pull/3262)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- *(revme)* use unwrap_or_default for non-UTF8 path safety ([#3259](https://github.com/bluealloy/revm/pull/3259)) +- sort storage keys and test files in blockchaintest output ([#3186](https://github.com/bluealloy/revm/pull/3186)) +- *(revme)* extract JSON printing helper in blockchaintest ([#3257](https://github.com/bluealloy/revm/pull/3257)) +- remove redundant clone calls ([#3258](https://github.com/bluealloy/revm/pull/3258)) +- re-export statetest-types from revm crate behind test-types feature ([#3247](https://github.com/bluealloy/revm/pull/3247)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [10.0.2](https://github.com/bluealloy/revm/compare/revme-v10.0.0...revme-v10.0.2) - 2025-11-14 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index c9eea11062..93dc009532 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revme" description = "Rust Ethereum Virtual Machine Executable" -version = "10.0.2" +version = "11.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index 4dc5acdcca..e4afba6e5d 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.2.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.1.1...revm-bytecode-v7.2.0) - 2026-01-15 + +### Added + +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) + +### Fixed + +- *(bytecode)* remove duplicate implementation in bytes_ref method ([#3276](https://github.com/bluealloy/revm/pull/3276)) +- the MLOAD opcode can resize memory ([#3266](https://github.com/bluealloy/revm/pull/3266)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- the KECCAK256 opcode can resize memory ([#3269](https://github.com/bluealloy/revm/pull/3269)) + ## [7.1.1](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.1.0...revm-bytecode-v7.1.1) - 2025-11-07 ### Other diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index 5312108ef8..7f0ea33c69 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "7.1.1" +version = "7.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index e1ee788814..c279c0b142 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [13.0.0](https://github.com/bluealloy/revm/compare/revm-context-v12.1.0...revm-context-v13.0.0) - 2026-01-15 + +### Added + +- new gas params, tx initial gas and codedeposit ([#3260](https://github.com/bluealloy/revm/pull/3260)) +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- Propagate `map-foldhash` Feature Through Dependency Chain ([#3252](https://github.com/bluealloy/revm/pull/3252)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- Gas params ([#3132](https://github.com/bluealloy/revm/pull/3132)) +- JournaledAccount sload/sstore ([#3201](https://github.com/bluealloy/revm/pull/3201)) +- Restrict Database::Error. JournaledAccountTr ([#3199](https://github.com/bluealloy/revm/pull/3199)) + +### Fixed + +- fix API comment ([#3293](https://github.com/bluealloy/revm/pull/3293)) +- *(test)* one gasid name is missing ([#3290](https://github.com/bluealloy/revm/pull/3290)) +- set transaction_id on new account ([#3204](https://github.com/bluealloy/revm/pull/3204)) + +### Other + +- *(gas_params)* add dedicated GasIds for sstore_refund ([#3310](https://github.com/bluealloy/revm/pull/3310)) +- remove redundant clones in gas params defaults ([#3300](https://github.com/bluealloy/revm/pull/3300)) +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- add Display trait for ExecutionResult and related types ([#3267](https://github.com/bluealloy/revm/pull/3267)) +- add Display for HaltReason and OutOfGasError ([#3265](https://github.com/bluealloy/revm/pull/3265)) +- *(cleanup)* remove unused duplicate ContextSetters trait in context crate ([#3225](https://github.com/bluealloy/revm/pull/3225)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [12.1.0](https://github.com/bluealloy/revm/compare/revm-context-v12.0.0...revm-context-v12.1.0) - 2025-11-14 ### Added diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 6ffe809ff9..9cd5625df3 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "12.1.0" +version = "13.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index 380b0490df..d059eeeded 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v13.1.0...revm-context-interface-v14.0.0) - 2026-01-15 + +### Added + +- new gas params, tx initial gas and codedeposit ([#3260](https://github.com/bluealloy/revm/pull/3260)) +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- Gas params ([#3132](https://github.com/bluealloy/revm/pull/3132)) +- JournaledAccount sload/sstore ([#3201](https://github.com/bluealloy/revm/pull/3201)) +- Restrict Database::Error. JournaledAccountTr ([#3199](https://github.com/bluealloy/revm/pull/3199)) + +### Fixed + +- *(test)* one gasid name is missing ([#3290](https://github.com/bluealloy/revm/pull/3290)) + +### Other + +- *(gas_params)* add dedicated GasIds for sstore_refund ([#3310](https://github.com/bluealloy/revm/pull/3310)) +- remove redundant clones in gas params defaults ([#3300](https://github.com/bluealloy/revm/pull/3300)) +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- add Display trait for ExecutionResult and related types ([#3267](https://github.com/bluealloy/revm/pull/3267)) +- add Display for HaltReason and OutOfGasError ([#3265](https://github.com/bluealloy/revm/pull/3265)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [13.1.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v13.0.0...revm-context-interface-v13.1.0) - 2025-11-14 ### Added diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 258df96e20..2a71aba3c4 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context-interface" description = "Revm context interface crates" -version = "13.1.0" +version = "14.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index bfa738a90b..c54c25d78a 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [10.0.0](https://github.com/bluealloy/revm/compare/revm-database-v9.0.6...revm-database-v10.0.0) - 2026-01-15 + +### Added + +- *(cache-db)* Added pritty_print for CacheDB ([#3296](https://github.com/bluealloy/revm/pull/3296)) +- Propagate `map-foldhash` Feature Through Dependency Chain ([#3252](https://github.com/bluealloy/revm/pull/3252)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- DatabaseCommitExt::drain_balances ([#3205](https://github.com/bluealloy/revm/pull/3205)) +- DatabaseCommitExt + increment_balances ([#3195](https://github.com/bluealloy/revm/pull/3195)) +- DatabaseCommit::commit_iter ([#3197](https://github.com/bluealloy/revm/pull/3197)) +- Restrict Database::Error. JournaledAccountTr ([#3199](https://github.com/bluealloy/revm/pull/3199)) + +### Fixed + +- *(database)* return error instead of panic when block not found in AlloyDB ([#3284](https://github.com/bluealloy/revm/pull/3284)) +- *(database)* make DatabaseCommit dyn-compatible ([#3264](https://github.com/bluealloy/revm/pull/3264)) +- *(database)* prevent deadlock in ([#3251](https://github.com/bluealloy/revm/pull/3251)) +- *(database)* verify handle belongs to current runtime before block_in_place ([#3212](https://github.com/bluealloy/revm/pull/3212)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- fix typos and grammar in database crate ([#3279](https://github.com/bluealloy/revm/pull/3279)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- avoid collect in CacheState commit ([#3242](https://github.com/bluealloy/revm/pull/3242)) +- *(database)* use fixed hashmaps in cache db ([#3231](https://github.com/bluealloy/revm/pull/3231)) +- *(database)* avoid triple cache lookup ([#3232](https://github.com/bluealloy/revm/pull/3232)) +- optimize vector initialization with size hints in state and precompile modules ([#3191](https://github.com/bluealloy/revm/pull/3191)) + ## [9.0.6](https://github.com/bluealloy/revm/compare/revm-database-v9.0.5...revm-database-v9.0.6) - 2025-11-14 ### Fixed diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 11ff562fa8..f7a0df71f8 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "9.0.6" +version = "10.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/interface/CHANGELOG.md b/crates/database/interface/CHANGELOG.md index 7568716ac2..ff79d15a5d 100644 --- a/crates/database/interface/CHANGELOG.md +++ b/crates/database/interface/CHANGELOG.md @@ -7,6 +7,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.0](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.5...revm-database-interface-v9.0.0) - 2026-01-15 + +### Added + +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- DatabaseCommitExt::drain_balances ([#3205](https://github.com/bluealloy/revm/pull/3205)) +- DatabaseCommitExt + increment_balances ([#3195](https://github.com/bluealloy/revm/pull/3195)) +- DatabaseCommit::commit_iter ([#3197](https://github.com/bluealloy/revm/pull/3197)) +- Restrict Database::Error. JournaledAccountTr ([#3199](https://github.com/bluealloy/revm/pull/3199)) + +### Fixed + +- *(database)* make DatabaseCommit dyn-compatible ([#3264](https://github.com/bluealloy/revm/pull/3264)) +- *(database)* prevent deadlock in ([#3251](https://github.com/bluealloy/revm/pull/3251)) +- *(database)* verify handle belongs to current runtime before block_in_place ([#3212](https://github.com/bluealloy/revm/pull/3212)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- fix typos and grammar in database crate ([#3279](https://github.com/bluealloy/revm/pull/3279)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [8.0.5](https://github.com/bluealloy/revm/compare/revm-database-interface-v8.0.4...revm-database-interface-v8.0.5) - 2025-11-07 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index d668da62f5..133e05c119 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database-interface" description = "Revm Database interface" -version = "8.0.5" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 792f6dabd2..d17188fdc6 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -7,6 +7,35 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [15.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v14.1.0...revm-handler-v15.0.0) - 2026-01-15 + +### Added + +- add `new_oog` helpers to InterpreterResult, CallOutcome, CreateOutcome, and FrameResult ([#3309](https://github.com/bluealloy/revm/pull/3309)) +- new gas params, tx initial gas and codedeposit ([#3260](https://github.com/bluealloy/revm/pull/3260)) +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- Gas params ([#3132](https://github.com/bluealloy/revm/pull/3132)) +- *(create)* Implement Cache for CreateInputs::created_address ([#3218](https://github.com/bluealloy/revm/pull/3218)) +- JournaledAccount sload/sstore ([#3201](https://github.com/bluealloy/revm/pull/3201)) +- Restrict Database::Error. JournaledAccountTr ([#3199](https://github.com/bluealloy/revm/pull/3199)) + +### Fixed + +- *(create)* Fix CreateInputs::created_address Cache invalidation ([#3222](https://github.com/bluealloy/revm/pull/3222)) + +### Other + +- apply improvements from ai-bot labeled PRs ([#3297](https://github.com/bluealloy/revm/pull/3297)) +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- description of `Handler::validate_against_state_and_deduct_caller` should match responsibilities ([#3256](https://github.com/bluealloy/revm/pull/3256)) +- *(handler)* eliminate code duplication in transaction validation ([#3243](https://github.com/bluealloy/revm/pull/3243)) +- *(handler)* validate_initial_tx_gas takes &mut Evm ([#3235](https://github.com/bluealloy/revm/pull/3235)) +- *(clippy)* remove unused imports ([#3227](https://github.com/bluealloy/revm/pull/3227)) +- optimize vector initialization using size hints ([#3200](https://github.com/bluealloy/revm/pull/3200)) +- apply_auth_list helper fn ([#3187](https://github.com/bluealloy/revm/pull/3187)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [14.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v14.0.0...revm-handler-v14.1.0) - 2025-11-14 ### Other diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 3631a310fa..99396c4ab1 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "14.1.0" +version = "15.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 355f7530f5..472298e530 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.2.0](https://github.com/bluealloy/revm/compare/revm-inspector-v14.1.0...revm-inspector-v14.2.0) - 2026-01-15 + +### Added + +- *(inspector)* make TestInspector public for testing EVM variants ([#3282](https://github.com/bluealloy/revm/pull/3282)) +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- Gas params ([#3132](https://github.com/bluealloy/revm/pull/3132)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- replace HashMap with fixed-size array for opcode counts in CountInspector ([#3203](https://github.com/bluealloy/revm/pull/3203)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [14.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v14.0.0...revm-inspector-v14.1.0) - 2025-11-14 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index c0834aa95b..cac3cb711e 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "14.1.0" +version = "14.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index f9bcf99999..2bedd96a79 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [32.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v31.1.0...revm-interpreter-v32.0.0) - 2026-01-15 + +### Added + +- add `new_oog` helpers to InterpreterResult, CallOutcome, CreateOutcome, and FrameResult ([#3309](https://github.com/bluealloy/revm/pull/3309)) +- new gas params, tx initial gas and codedeposit ([#3260](https://github.com/bluealloy/revm/pull/3260)) +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- Gas params ([#3132](https://github.com/bluealloy/revm/pull/3132)) +- *(create)* Implement Cache for CreateInputs::created_address ([#3218](https://github.com/bluealloy/revm/pull/3218)) + +### Fixed + +- *(create)* Fix CreateInputs::created_address Cache invalidation ([#3222](https://github.com/bluealloy/revm/pull/3222)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- add optimization for push and pop ([#3263](https://github.com/bluealloy/revm/pull/3263)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- avoid loading bytecode in extcodehash ([#3261](https://github.com/bluealloy/revm/pull/3261)) +- *(clippy)* remove unused imports ([#3227](https://github.com/bluealloy/revm/pull/3227)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [31.1.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v31.0.0...revm-interpreter-v31.1.0) - 2025-11-14 ### Fixed diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index 83de6d17ea..7ddfc962e4 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-interpreter" description = "Revm Interpreter that executes bytecode." -version = "31.1.0" +version = "32.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index e06472495d..e9061aa4c2 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.2.0](https://github.com/bluealloy/revm/compare/op-revm-v14.1.0...op-revm-v14.2.0) - 2026-01-15 + +### Added + +- new gas params, tx initial gas and codedeposit ([#3260](https://github.com/bluealloy/revm/pull/3260)) +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- early return if the l1 fee scalar is zero ([#3213](https://github.com/bluealloy/revm/pull/3213)) +- Restrict Database::Error. JournaledAccountTr ([#3199](https://github.com/bluealloy/revm/pull/3199)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- Remove redundant tx fetch in Optimism handler gas accounting ([#3220](https://github.com/bluealloy/revm/pull/3220)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [14.1.0](https://github.com/bluealloy/revm/compare/op-revm-v14.0.0...op-revm-v14.1.0) - 2025-11-14 ### Fixed diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 767d0f7cf2..5564f315da 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "14.1.0" +version = "14.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index 0b8341c99a..aed7974a63 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,6 +7,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [31.1.0](https://github.com/bluealloy/revm/compare/revm-precompile-v31.0.0...revm-precompile-v31.1.0) - 2026-01-15 + +### Added + +- rm gmp use-system-libs ([#3253](https://github.com/bluealloy/revm/pull/3253)) +- dynamically link gmp ([#3250](https://github.com/bluealloy/revm/pull/3250)) + +### Other + +- *(precompile)* extract common pairing_check_bytes logic in bls12_381 ([#3301](https://github.com/bluealloy/revm/pull/3301)) +- apply improvements from ai-bot labeled PRs ([#3297](https://github.com/bluealloy/revm/pull/3297)) +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- optimize vector initialization using size hints ([#3200](https://github.com/bluealloy/revm/pull/3200)) +- optimize precompile `extend()` ([#3192](https://github.com/bluealloy/revm/pull/3192)) +- optimize vector initialization with size hints in state and precompile modules ([#3191](https://github.com/bluealloy/revm/pull/3191)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [31.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v29.0.1...revm-precompile-v31.0.0) - 2025-11-10 ### Added diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index d1ebbe473b..2739839687 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "31.0.0" +version = "31.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index 2a39fc1765..731965263e 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [21.1.0](https://github.com/bluealloy/revm/compare/revm-primitives-v21.0.2...revm-primitives-v21.1.0) - 2026-01-15 + +### Added + +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) +- JournaledAccount sload/sstore ([#3201](https://github.com/bluealloy/revm/pull/3201)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- *(database)* use fixed hashmaps in cache db ([#3231](https://github.com/bluealloy/revm/pull/3231)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [21.0.2](https://github.com/bluealloy/revm/compare/revm-primitives-v21.0.1...revm-primitives-v21.0.2) - 2025-11-07 ### Other diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index d77c9d4022..3b85300433 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-primitives" description = "Revm primitives types" -version = "21.0.2" +version = "21.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 4b51b21947..bbf217a6ab 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [33.2.0](https://github.com/bluealloy/revm/compare/revm-v33.1.0...revm-v33.2.0) - 2026-01-15 + +### Added + +- Propagate `map-foldhash` Feature Through Dependency Chain ([#3252](https://github.com/bluealloy/revm/pull/3252)) +- dynamically link gmp ([#3250](https://github.com/bluealloy/revm/pull/3250)) + +### Other + +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- re-export statetest-types from revm crate behind test-types feature ([#3247](https://github.com/bluealloy/revm/pull/3247)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [33.1.0](https://github.com/bluealloy/revm/compare/revm-v33.0.0...revm-v33.1.0) - 2025-11-14 ### Fixed diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 4b590aeeb1..a43df25ed4 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "33.1.0" +version = "33.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index 63e4abe9c5..2f454ba55f 100644 --- a/crates/state/CHANGELOG.md +++ b/crates/state/CHANGELOG.md @@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.0](https://github.com/bluealloy/revm/compare/revm-state-v8.1.1...revm-state-v9.0.0) - 2026-01-15 + +### Added + +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- Propagate `map-foldhash` Feature Through Dependency Chain ([#3252](https://github.com/bluealloy/revm/pull/3252)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) + +### Other + +- apply improvements from ai-bot labeled PRs ([#3297](https://github.com/bluealloy/revm/pull/3297)) +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- deduplicate local/global flags setup ([#3190](https://github.com/bluealloy/revm/pull/3190)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [8.1.1](https://github.com/bluealloy/revm/compare/revm-state-v8.1.0...revm-state-v8.1.1) - 2025-11-07 ### Other diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 48f0efe1c4..84597df29b 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "8.1.1" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index 32bf941789..f41f6f6401 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [14.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v13.1.0...revm-statetest-types-v14.0.0) - 2026-01-15 + +### Added + +- move GasParams to Cfg ([#3229](https://github.com/bluealloy/revm/pull/3229)) +- Propagate `map-foldhash` Feature Through Dependency Chain ([#3252](https://github.com/bluealloy/revm/pull/3252)) +- BAL EIP-7928 ([#3070](https://github.com/bluealloy/revm/pull/3070)) + +### Fixed + +- *(statetest)* use spec-aware blob base fee update fraction ([#3210](https://github.com/bluealloy/revm/pull/3210)) + +### Other + +- apply improvements from ai-bot labeled PRs ([#3297](https://github.com/bluealloy/revm/pull/3297)) +- fix typos, grammar errors, and improve documentation consistency ([#3294](https://github.com/bluealloy/revm/pull/3294)) +- happy new year, 2026 licence ([#3272](https://github.com/bluealloy/revm/pull/3272)) +- re-export statetest-types from revm crate behind test-types feature ([#3247](https://github.com/bluealloy/revm/pull/3247)) +- *(fmt)* merge all imports ([#3184](https://github.com/bluealloy/revm/pull/3184)) + ## [13.1.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v13.0.0...revm-statetest-types-v13.1.0) - 2025-11-14 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index df8dc9a686..b50e6cf270 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-statetest-types" description = "Statetest types for revme" -version = "13.1.0" +version = "14.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true From 41f31014a9d37c654581260c272d34cd30b4c11a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 15 Jan 2026 12:08:11 +0100 Subject: [PATCH 125/127] bump: revm v34.0.0 (#3313) --- Cargo.lock | 12 ++++++------ Cargo.toml | 12 ++++++------ MIGRATION_GUIDE.md | 31 +++++++++++++++++++++++++++++++ crates/bytecode/CHANGELOG.md | 2 +- crates/bytecode/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 2 +- crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 2 +- crates/precompile/Cargo.toml | 2 +- crates/primitives/CHANGELOG.md | 6 ------ crates/primitives/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 2 +- crates/revm/Cargo.toml | 2 +- 15 files changed, 54 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3fe1d77510..b5b14c0432 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2896,7 +2896,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "14.2.0" +version = "15.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3515,7 +3515,7 @@ dependencies = [ [[package]] name = "revm" -version = "33.2.0" +version = "34.0.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3535,7 +3535,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "7.2.0" +version = "8.0.0" dependencies = [ "bitvec", "paste", @@ -3641,7 +3641,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "14.2.0" +version = "15.0.0" dependencies = [ "auto_impl", "either", @@ -3670,7 +3670,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "31.1.0" +version = "32.0.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3698,7 +3698,7 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "21.1.0" +version = "22.0.0" dependencies = [ "alloy-primitives", "num_enum", diff --git a/Cargo.toml b/Cargo.toml index fbfa622e2d..97327f2975 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "33.2.0", default-features = false } -primitives = { path = "crates/primitives", package = "revm-primitives", version = "21.1.0", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "7.2.0", default-features = false } +revm = { path = "crates/revm", version = "34.0.0", default-features = false } +primitives = { path = "crates/primitives", package = "revm-primitives", version = "22.0.0", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "8.0.0", default-features = false } database = { path = "crates/database", package = "revm-database", version = "10.0.0", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "9.0.0", default-features = false } state = { path = "crates/state", package = "revm-state", version = "9.0.0", default-features = false } interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "32.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "14.2.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "31.1.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "15.0.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "32.0.0", default-features = false } statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "14.0.0", default-features = false } context = { path = "crates/context", package = "revm-context", version = "13.0.0", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "14.0.0", default-features = false } handler = { path = "crates/handler", package = "revm-handler", version = "15.0.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "14.2.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "15.0.0", default-features = false } ee-tests = { path = "crates/ee-tests", package = "revm-ee-tests", version = "0.1.0", default-features = false } # alloy diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 33e408e82c..7acf8d44f6 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,35 @@ +# v103 tag (revm v34.0.0) + +* BAL (EIP-7928) support added to Database implementations. +* `GasParams` is new struct where you can set dynamic opcode gas params. Initialized and can be found in cfg. + * Gas calculation functions moved from `revm-interpreter` to be part of gas params. + * Gas constants moved from `revm_interpreter`::gas to `revm_context_interface::cfg::gas` +* `CreateInputs` struct fields made private with accessor pattern. + * Use `CreateInputs::created_address()` getter (now cached). +* `Host::selfdestruct` signature changed to support OOG on cold load for target account. +* Inspector `log` function renamed: + * `Inspector::log` renamed to `log` and `log_full`. + * `log_full` default impl calls `log`. + * `log_full` has `Interpreter` input while `log` does not. + * `log` is called in places where Interpreter is not found. +* `PrecompileError::Other` now contains `Cow<'static, str>` instead of `&'static str`. + * Allows setting both `&'static str` (no perf penalty) and `String` if needed. +* `JournaledAccount` struct added for tracking account changes. + * `JournalTr` functions that fetch account now return a ref. + * New function `load_account_mut` returns `JournaledAccount`. +* `JournalTr::load_account_code` deprecated, renamed to `JournalTr::load_account_with_code`. +* `JournalTr::warm_account_and_storage` and `JournalTr::warm_account` removed. + * Access list is now separate from the main Journal EvmState. + * Use `JournalTr::warm_access_list` to import access list. +* Declarative macros `tri!`, `gas_or_fail!`, `otry!` removed from `revm-interpreter`. +* `MemoryGas` API signature changes. +* Removed deprecated methods including `into_plain_state`, `regenerate_hash`. +* `State.bal_state` field added (breaks struct literal constructors). +* `DatabaseCommitExt::drain_balances` and `increment_balances` added. +* First precompile error now bubbles up with detailed error messages. + * New `PrecompileError` variants added. + # 102 tag ( revm v33.1.0) No breaking changes diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index e4afba6e5d..ccac682b66 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [7.2.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.1.1...revm-bytecode-v7.2.0) - 2026-01-15 +## [8.0.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v7.1.1...revm-bytecode-v8.0.0) - 2026-01-15 ### Added diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index 7f0ea33c69..6f2e1d7955 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "7.2.0" +version = "8.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 472298e530..eb3996e0d9 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [14.2.0](https://github.com/bluealloy/revm/compare/revm-inspector-v14.1.0...revm-inspector-v14.2.0) - 2026-01-15 +## [15.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v14.1.0...revm-inspector-v15.0.0) - 2026-01-15 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index cac3cb711e..190babcd3e 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "14.2.0" +version = "15.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/op-revm/CHANGELOG.md b/crates/op-revm/CHANGELOG.md index e9061aa4c2..e7731b8828 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [14.2.0](https://github.com/bluealloy/revm/compare/op-revm-v14.1.0...op-revm-v14.2.0) - 2026-01-15 +## [15.0.0](https://github.com/bluealloy/revm/compare/op-revm-v14.1.0...op-revm-v15.0.0) - 2026-01-15 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 5564f315da..59e1c7d093 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "op-revm" description = "Optimism variant of Revm" -version = "14.2.0" +version = "15.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index aed7974a63..e1f96e977c 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [31.1.0](https://github.com/bluealloy/revm/compare/revm-precompile-v31.0.0...revm-precompile-v31.1.0) - 2026-01-15 +## [32.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v31.0.0...revm-precompile-v32.0.0) - 2026-01-15 ### Added diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 2739839687..cdafcfa1e8 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-precompile" description = "Revm Precompiles - Ethereum compatible precompiled contracts" -version = "31.1.0" +version = "32.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index 731965263e..6af04291b6 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -270,12 +270,6 @@ Stable version - Bump new logo ([#1735](https://github.com/bluealloy/revm/pull/1735)) - bump kzg-rs version ([#1734](https://github.com/bluealloy/revm/pull/1734)) -## [9.0.1](https://github.com/bluealloy/revm/compare/revm-primitives-v9.0.0...revm-primitives-v9.0.1) - 2024-08-30 - -### Other -- Bump new logo ([#1735](https://github.com/bluealloy/revm/pull/1735)) -- bump kzg-rs version ([#1734](https://github.com/bluealloy/revm/pull/1734)) - ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-primitives-v8.0.0...revm-primitives-v9.0.0) - 2024-08-29 ### Added diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 3b85300433..edc9a2e688 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-primitives" description = "Revm primitives types" -version = "21.1.0" +version = "22.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index bbf217a6ab..d12f8ffbca 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] -## [33.2.0](https://github.com/bluealloy/revm/compare/revm-v33.1.0...revm-v33.2.0) - 2026-01-15 +## [34.0.0](https://github.com/bluealloy/revm/compare/revm-v33.1.0...revm-v34.0.0) - 2026-01-15 ### Added diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index a43df25ed4..085aa1a004 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm" description = "Revm - Rust Ethereum Virtual Machine" -version = "33.2.0" +version = "34.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true From 50405a27f57f80a96ab9d91e93180bca22217a3a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 15 Jan 2026 12:16:25 +0100 Subject: [PATCH 126/127] chore(script): move statetest before revm publish (#3314) --- scripts/publish.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/publish.sh b/scripts/publish.sh index d0ac3c4a24..3443a5b235 100755 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -14,7 +14,7 @@ cargo publish --package revm-database cargo publish --package revm-context cargo publish --package revm-handler cargo publish --package revm-inspector -cargo publish --package revm cargo publish --package revm-statetest-types +cargo publish --package revm cargo publish --package revme cargo publish --package op-revm From d3d99f3525fe954961cc45b2a6fa0836b50475b5 Mon Sep 17 00:00:00 2001 From: frisitano Date: Thu, 26 Feb 2026 22:01:38 +0400 Subject: [PATCH 127/127] lint --- crates/context/src/cfg.rs | 28 ++- crates/ee-tests/src/op_revm_tests.rs | 266 +++++++++++---------------- 2 files changed, 123 insertions(+), 171 deletions(-) diff --git a/crates/context/src/cfg.rs b/crates/context/src/cfg.rs index d86cf7054c..682d7e9437 100644 --- a/crates/context/src/cfg.rs +++ b/crates/context/src/cfg.rs @@ -346,13 +346,10 @@ impl CfgEnv { self.enable_eip7702 = true; use context_interface::cfg::gas_params::GasId; use primitives::eip7702; - self.gas_params.override_gas( - [( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - )] - .into_iter(), - ); + self.gas_params.override_gas([( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + )]); self } @@ -361,16 +358,13 @@ impl CfgEnv { pub fn enable_eip_7623(mut self) -> CfgEnv { self.enable_eip7623 = true; use context_interface::cfg::{gas, gas_params::GasId}; - self.gas_params.override_gas( - [ - ( - GasId::tx_floor_cost_per_token(), - gas::TOTAL_COST_FLOOR_PER_TOKEN, - ), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + self.gas_params.override_gas([ + ( + GasId::tx_floor_cost_per_token(), + gas::TOTAL_COST_FLOOR_PER_TOKEN, + ), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); self } diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index 59e5fd6995..51530783f1 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -183,17 +183,14 @@ fn bn254_pair_test_tx( let input = Bytes::from([1; GRANITE_MAX_INPUT_SIZE + 2]); let mut gas_params = GasParams::new_spec(spec.into()); if spec >= OpSpecId::ISTHMUS { - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); } let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); @@ -329,17 +326,14 @@ fn g1_msm_test_tx( const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::G1_MSM_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let gs1_msm_gas = bls12_381_utils::msm_required_gas( @@ -371,17 +365,14 @@ fn test_halted_tx_call_bls12_381_g1_msm_input_wrong_size() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::G1_MSM_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let gs1_msm_gas = bls12_381_utils::msm_required_gas( @@ -430,17 +421,14 @@ fn test_halted_tx_call_bls12_381_g1_msm_out_of_gas() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::G1_MSM_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let gs1_msm_gas = bls12_381_utils::msm_required_gas( @@ -586,17 +574,14 @@ fn g2_msm_test_tx( const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::G2_MSM_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let gs2_msm_gas = bls12_381_utils::msm_required_gas( @@ -628,17 +613,14 @@ fn test_halted_tx_call_bls12_381_g2_msm_input_wrong_size() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::G2_MSM_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let gs2_msm_gas = bls12_381_utils::msm_required_gas( @@ -687,17 +669,14 @@ fn test_halted_tx_call_bls12_381_g2_msm_out_of_gas() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::G2_MSM_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let gs2_msm_gas = bls12_381_utils::msm_required_gas( @@ -769,17 +748,14 @@ fn bl12_381_pairing_test_tx( const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PAIRING_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); @@ -809,17 +785,14 @@ fn test_halted_tx_call_bls12_381_pairing_input_wrong_size() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PAIRING_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let pairing_gas: u64 = @@ -865,17 +838,14 @@ fn test_halted_tx_call_bls12_381_pairing_out_of_gas() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PAIRING_INPUT_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); let pairing_gas: u64 = @@ -943,17 +913,14 @@ fn test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PADDED_FP_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); @@ -997,17 +964,14 @@ fn test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PADDED_FP_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); @@ -1051,17 +1015,14 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PADDED_FP2_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0); @@ -1143,17 +1104,14 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size() { const SPEC_ID: OpSpecId = OpSpecId::ISTHMUS; let input = Bytes::from([1; bls12_381_const::PADDED_FP2_LENGTH]); let mut gas_params = GasParams::new_spec(SPEC_ID.into()); - gas_params.override_gas( - [ - ( - GasId::tx_eip7702_per_empty_account_cost(), - eip7702::PER_EMPTY_ACCOUNT_COST, - ), - (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), - (GasId::tx_floor_cost_base_gas(), 21000), - ] - .into_iter(), - ); + gas_params.override_gas([ + ( + GasId::tx_eip7702_per_empty_account_cost(), + eip7702::PER_EMPTY_ACCOUNT_COST, + ), + (GasId::tx_floor_cost_per_token(), TOTAL_COST_FLOOR_PER_TOKEN), + (GasId::tx_floor_cost_base_gas(), 21000), + ]); let InitialAndFloorGas { initial_gas, .. } = gas_params.initial_tx_gas(&input[..], false, 0, 0, 0);