From a46aa4abed552a5f4b26383591be1067315ae6ca Mon Sep 17 00:00:00 2001 From: MozirDmitriy Date: Wed, 23 Jul 2025 18:49:10 +0300 Subject: [PATCH 01/78] fix: swapped comments for db and db_mut methods in JournalTr trait (#2774) --- crates/context/interface/src/journaled_state.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 1cf9900624..e8ff56adc0 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -20,10 +20,10 @@ pub trait JournalTr { /// Dont forget to set spec_id. fn new(database: Self::Database) -> Self; - /// Returns the database. + /// Returns a mutable reference to the database. fn db_mut(&mut self) -> &mut Self::Database; - /// Returns the mutable database. + /// Returns an immutable reference to the database. fn db(&self) -> &Self::Database; /// Returns the storage value from Journal state. From e6a25a3f9e30672418a23f30fa1cf3c8070f5a11 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Wed, 23 Jul 2025 17:10:17 +0100 Subject: [PATCH 02/78] chore: Add dyn Crypto trait to PrecompileFn (#2772) * add trait to PrecompilesStruct and refactor * impl sha * add execute method and execute using Crypto trait * refactor tests * fmt * reduce diff * fix * fmt * add box * benchmarks * fmt * add ripemd --- crates/handler/src/precompile_provider.rs | 3 +- crates/op-revm/src/precompiles.rs | 49 ++++++---- crates/precompile/bench/blake2.rs | 36 ++++++-- crates/precompile/bench/ecrecover.rs | 9 +- crates/precompile/bench/eip1962.rs | 21 ++++- crates/precompile/bench/eip2537.rs | 14 +-- crates/precompile/bench/eip4844.rs | 2 +- crates/precompile/src/blake2.rs | 4 +- crates/precompile/src/bls12_381/g1_add.rs | 2 +- crates/precompile/src/bls12_381/g1_msm.rs | 4 +- crates/precompile/src/bls12_381/g2_add.rs | 2 +- crates/precompile/src/bls12_381/g2_msm.rs | 2 +- .../precompile/src/bls12_381/map_fp2_to_g2.rs | 6 +- .../precompile/src/bls12_381/map_fp_to_g1.rs | 4 +- crates/precompile/src/bls12_381/pairing.rs | 2 +- crates/precompile/src/bn128.rs | 92 ++++++++++++++----- crates/precompile/src/hash.rs | 13 +-- crates/precompile/src/identity.rs | 2 +- crates/precompile/src/interface.rs | 46 +++++++++- crates/precompile/src/kzg_point_evaluation.rs | 4 +- crates/precompile/src/lib.rs | 58 +++++++++++- crates/precompile/src/modexp.rs | 58 ++++++------ crates/precompile/src/secp256k1.rs | 6 +- crates/precompile/src/secp256r1.rs | 29 ++++-- 24 files changed, 340 insertions(+), 128 deletions(-) diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index bf960a1e51..a79e260087 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -101,6 +101,7 @@ impl PrecompileProvider for EthPrecompiles { let Some(precompile) = self.precompiles.get(address) else { return Ok(None); }; + let mut result = InterpreterResult { result: InstructionResult::Return, gas: Gas::new(gas_limit), @@ -120,7 +121,7 @@ impl PrecompileProvider for EthPrecompiles { CallInput::Bytes(bytes) => bytes.0.iter().as_slice(), }; - match (*precompile)(input_bytes, gas_limit) { + match (*precompile)(input_bytes, gas_limit, self.precompiles.crypto()) { Ok(output) => { let underflow = result.gas.record_cost(output.gas_used); assert!(underflow, "Gas underflow is not possible"); diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index d29e566765..cef2029f94 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -146,12 +146,16 @@ pub mod bn128_pair { pub const GRANITE_MAX_INPUT_SIZE: usize = 112687; /// Bn128 pair precompile. pub const GRANITE: PrecompileWithAddress = - PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit| { - run_pair(input, gas_limit) + PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit, crypto| { + run_pair(input, gas_limit, crypto) }); /// Run the bn128 pair precompile with Optimism input limit. - pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + pub fn run_pair( + input: &[u8], + gas_limit: u64, + crypto: &dyn precompile::Crypto, + ) -> PrecompileResult { if input.len() > GRANITE_MAX_INPUT_SIZE { return Err(PrecompileError::Bn128PairLength); } @@ -160,6 +164,7 @@ pub mod bn128_pair { bn128::pair::ISTANBUL_PAIR_PER_POINT, bn128::pair::ISTANBUL_PAIR_BASE, gas_limit, + crypto, ) } } @@ -190,33 +195,45 @@ pub mod bls12_381 { PrecompileWithAddress(PAIRING_ADDRESS, run_pair); /// 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( + input: &[u8], + gas_limit: u64, + crypto: &dyn precompile::Crypto, + ) -> 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(), )); } - precompile::bls12_381::g1_msm::g1_msm(input, gas_limit) + precompile::bls12_381::g1_msm::g1_msm(input, gas_limit, crypto) } /// 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( + input: &[u8], + gas_limit: u64, + crypto: &dyn precompile::Crypto, + ) -> 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(), )); } - precompile::bls12_381::g2_msm::g2_msm(input, gas_limit) + precompile::bls12_381::g2_msm::g2_msm(input, gas_limit, crypto) } /// Run the pairing precompile with Optimism input limit. - pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + pub fn run_pair( + input: &[u8], + gas_limit: u64, + crypto: &dyn precompile::Crypto, + ) -> 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(), )); } - precompile::bls12_381::pairing::pairing(input, gas_limit) + precompile::bls12_381::pairing::pairing(input, gas_limit, crypto) } } @@ -255,7 +272,7 @@ mod tests { let expected = hex::decode("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(); - let outcome = bn128_pair::run_pair(&input, 260_000).unwrap(); + let outcome = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto).unwrap(); assert_eq!(outcome.bytes, expected); // Invalid input length @@ -268,17 +285,17 @@ mod tests { ) .unwrap(); - let res = bn128_pair::run_pair(&input, 260_000); + let res = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto); assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); // Valid input length shorter than 112687 let input = vec![1u8; 586 * bn128::PAIR_ELEMENT_LEN]; - let res = bn128_pair::run_pair(&input, 260_000); + let res = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto); assert!(matches!(res, Err(PrecompileError::OutOfGas))); // Input length longer than 112687 let input = vec![1u8; 587 * bn128::PAIR_ELEMENT_LEN]; - let res = bn128_pair::run_pair(&input, 260_000); + let res = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto); assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); } @@ -320,7 +337,7 @@ 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(&input, 260_000, &precompile::DefaultCrypto); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) @@ -331,7 +348,7 @@ 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(&input, 260_000, &precompile::DefaultCrypto); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) @@ -342,7 +359,7 @@ 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(&input, 260_000, &precompile::DefaultCrypto); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) diff --git a/crates/precompile/bench/blake2.rs b/crates/precompile/bench/blake2.rs index 053552fad4..facf51eb84 100644 --- a/crates/precompile/bench/blake2.rs +++ b/crates/precompile/bench/blake2.rs @@ -20,7 +20,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/2_rounds", |b| { let input = &inputs[0]; // 2 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -28,7 +30,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/4_rounds", |b| { let input = &inputs[1]; // 4 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -36,7 +40,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/64_rounds", |b| { let input = &inputs[2]; // 64 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -44,7 +50,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/10_rounds", |b| { let input = &inputs[3]; // 10 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -52,7 +60,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/12_rounds", |b| { let input = &inputs[4]; // 12 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -60,7 +70,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/512_rounds", |b| { let input = &inputs[5]; // 512 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -68,7 +80,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/1024_rounds", |b| { let input = &inputs[6]; // 1024 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -76,7 +90,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/100K_rounds", |b| { let input = &inputs[7]; // 100000 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); @@ -84,7 +100,9 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/200K_rounds", |b| { let input = &inputs[8]; // 200000 rounds b.iter(|| { - black_box(blake2::run(black_box(input), u64::MAX).unwrap()); + black_box( + blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), + ); }); }); diff --git a/crates/precompile/bench/ecrecover.rs b/crates/precompile/bench/ecrecover.rs index dd2ff2fa5c..5cb2f1f4c1 100644 --- a/crates/precompile/bench/ecrecover.rs +++ b/crates/precompile/bench/ecrecover.rs @@ -27,6 +27,13 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, M>) { let message_and_signature = Bytes::from(message_and_signature); group.bench_function("ecrecover precompile", |b| { - b.iter(|| ec_recover_run(&message_and_signature, u64::MAX).unwrap()) + b.iter(|| { + ec_recover_run( + &message_and_signature, + u64::MAX, + &revm_precompile::DefaultCrypto, + ) + .unwrap() + }) }); } diff --git a/crates/precompile/bench/eip1962.rs b/crates/precompile/bench/eip1962.rs index 92b547da95..95febdd1f0 100644 --- a/crates/precompile/bench/eip1962.rs +++ b/crates/precompile/bench/eip1962.rs @@ -22,7 +22,15 @@ pub fn add_bn128_add_benches(group: &mut BenchmarkGroup<'_, M>) let input = Bytes::from(ecadd_input); group.bench_function("bn128 add precompile", |b| { - b.iter(|| run_add(&input, ISTANBUL_ADD_GAS_COST, 150).unwrap()) + b.iter(|| { + run_add( + &input, + ISTANBUL_ADD_GAS_COST, + 150, + &revm_precompile::DefaultCrypto, + ) + .unwrap() + }) }); } @@ -38,7 +46,15 @@ pub fn add_bn128_mul_benches(group: &mut BenchmarkGroup<'_, M>) let input = Bytes::from(ecmul_input); group.bench_function("bn128 mul precompile", |b| { - b.iter(|| run_mul(&input, ISTANBUL_MUL_GAS_COST, 6000).unwrap()) + b.iter(|| { + run_mul( + &input, + ISTANBUL_MUL_GAS_COST, + 6000, + &revm_precompile::DefaultCrypto, + ) + .unwrap() + }) }); } @@ -69,6 +85,7 @@ pub fn add_bn128_pair_benches(group: &mut BenchmarkGroup<'_, M>) ISTANBUL_PAIR_PER_POINT, ISTANBUL_PAIR_BASE, u64::MAX, + &revm_precompile::DefaultCrypto, ) .unwrap() }) diff --git a/crates/precompile/bench/eip2537.rs b/crates/precompile/bench/eip2537.rs index 124ed82427..acd75182dc 100644 --- a/crates/precompile/bench/eip2537.rs +++ b/crates/precompile/bench/eip2537.rs @@ -152,7 +152,7 @@ pub fn add_g1_add_benches(group: &mut BenchmarkGroup<'_, M>) { let precompile = *PRECOMPILE.precompile(); group.bench_function("g1_add", |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } @@ -167,7 +167,7 @@ pub fn add_g2_add_benches(group: &mut BenchmarkGroup<'_, M>) { let precompile = *PRECOMPILE.precompile(); group.bench_function("g2_add", |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } @@ -185,7 +185,7 @@ pub fn add_g1_msm_benches(group: &mut BenchmarkGroup<'_, M>) { let input = Bytes::from(test_vector); group.bench_function(format!("g1_msm (size {size})"), |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } } @@ -230,7 +230,7 @@ pub fn add_g2_msm_benches(group: &mut BenchmarkGroup<'_, M>) { let input = Bytes::from(test_vector); group.bench_function(format!("g2_msm (size {size})"), |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } } @@ -263,7 +263,7 @@ pub fn add_pairing_benches(group: &mut BenchmarkGroup<'_, M>) { let input = Bytes::from(test_vector); group.bench_function(format!("pairing ({pairs} pairs)"), |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } } @@ -284,7 +284,7 @@ pub fn add_map_fp_to_g1_benches(group: &mut BenchmarkGroup<'_, M let precompile = *PRECOMPILE.precompile(); group.bench_function("map_fp_to_g1", |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } @@ -311,6 +311,6 @@ pub fn add_map_fp2_to_g2_benches(group: &mut BenchmarkGroup<'_, let precompile = *PRECOMPILE.precompile(); group.bench_function("map_fp2_to_g2", |b| { - b.iter(|| precompile(&input, u64::MAX).unwrap()); + b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); }); } diff --git a/crates/precompile/bench/eip4844.rs b/crates/precompile/bench/eip4844.rs index c9c4a65c6e..eb6f141ba2 100644 --- a/crates/precompile/bench/eip4844.rs +++ b/crates/precompile/bench/eip4844.rs @@ -18,6 +18,6 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, M>) { let gas = 50000; group.bench_function("kzg precompile", |b| { - b.iter(|| run(&kzg_input, gas).unwrap()) + b.iter(|| run(&kzg_input, gas, &revm_precompile::DefaultCrypto).unwrap()) }); } diff --git a/crates/precompile/src/blake2.rs b/crates/precompile/src/blake2.rs index 6c446152a9..1582faa10f 100644 --- a/crates/precompile/src/blake2.rs +++ b/crates/precompile/src/blake2.rs @@ -11,7 +11,7 @@ pub const FUN: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_addre /// reference: /// input format: /// [4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f] -pub fn run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { if input.len() != INPUT_LENGTH { return Err(PrecompileError::Blake2WrongLength); } @@ -639,7 +639,7 @@ mod tests { let time = Instant::now(); for i in 0..3000 { - let _ = run(&input[i % 3], u64::MAX).unwrap(); + let _ = run(&input[i % 3], u64::MAX, &crate::DefaultCrypto).unwrap(); } println!("duration: {:?}", time.elapsed()); } diff --git a/crates/precompile/src/bls12_381/g1_add.rs b/crates/precompile/src/bls12_381/g1_add.rs index c8aa2f80f0..64d1989a48 100644 --- a/crates/precompile/src/bls12_381/g1_add.rs +++ b/crates/precompile/src/bls12_381/g1_add.rs @@ -14,7 +14,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_ADD_ADDRE /// Output is an encoding of addition operation result - single G1 point (`128` /// bytes). /// See also: -pub fn g1_add(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn g1_add(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { if G1_ADD_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index f47802ef4b..1e20d67cbf 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -20,7 +20,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_MSM_ADDRE /// Output is an encoding of multi-scalar-multiplication operation result - single G1 /// point (`128` bytes). /// See also: -pub fn g1_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn g1_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % G1_MSM_INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( @@ -63,7 +63,7 @@ mod test { #[test] fn bls_g1multiexp_g1_not_on_curve_but_in_subgroup() { let input = Bytes::from(hex!("000000000000000000000000000000000a2833e497b38ee3ca5c62828bf4887a9f940c9e426c7890a759c20f248c23a7210d2432f4c98a514e524b5184a0ddac00000000000000000000000000000000150772d56bf9509469f9ebcd6e47570429fd31b0e262b66d512e245c38ec37255529f2271fd70066473e393a8bead0c30000000000000000000000000000000000000000000000000000000000000000")); - let fail = g1_msm(&input, G1_MSM_BASE_GAS_FEE); + let fail = g1_msm(&input, G1_MSM_BASE_GAS_FEE, &crate::DefaultCrypto); assert_eq!( fail, Err(PrecompileError::Other( diff --git a/crates/precompile/src/bls12_381/g2_add.rs b/crates/precompile/src/bls12_381/g2_add.rs index bcd4f7984e..9694282508 100644 --- a/crates/precompile/src/bls12_381/g2_add.rs +++ b/crates/precompile/src/bls12_381/g2_add.rs @@ -15,7 +15,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_ADD_ADDRE /// Output is an encoding of addition operation result - single G2 point (`256` /// bytes). /// See also -pub fn g2_add(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn g2_add(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { if G2_ADD_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index 98dfa71768..1d79791ce1 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -20,7 +20,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_MSM_ADDRE /// Output is an encoding of multi-scalar-multiplication operation result - single G2 /// point (`256` bytes). /// See also: -pub fn g2_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn g2_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % G2_MSM_INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( 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 50f67a32cb..d5812b7a89 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -17,7 +17,11 @@ pub const PRECOMPILE: PrecompileWithAddress = /// an element of Fp2. Output of this call is 256 bytes and is an encoded G2 /// point. /// See also: -pub fn map_fp2_to_g2(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn map_fp2_to_g2( + input: &[u8], + gas_limit: u64, + _crypto: &dyn crate::Crypto, +) -> PrecompileResult { if MAP_FP2_TO_G2_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } 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 de4ee4503e..45ab765648 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -13,7 +13,7 @@ pub const PRECOMPILE: PrecompileWithAddress = /// Field-to-curve call expects 64 bytes as an input that is interpreted as an /// element of Fp. Output of this call is 128 bytes and is an encoded G1 point. /// See also: -pub fn map_fp_to_g1(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn map_fp_to_g1(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { if MAP_FP_TO_G1_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -47,7 +47,7 @@ mod test { #[test] fn sanity_test() { let input = Bytes::from(hex!("000000000000000000000000000000006900000000000000636f6e7472616374595a603f343061cd305a03f40239f5ffff31818185c136bc2595f2aa18e08f17")); - let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE_GAS_FEE); + let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE_GAS_FEE, &crate::DefaultCrypto); assert_eq!( fail, Err(PrecompileError::Other("non-canonical fp value".to_string())) diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index 6f9a59bcbd..b0ca4f6b49 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -25,7 +25,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(PAIRING_ADDR /// target field and 0x00 otherwise. /// /// See also: -pub fn pairing(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn pairing(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % PAIRING_INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index 3cad806801..72f8a505c1 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -27,8 +27,8 @@ pub mod add { /// Bn128 add precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { - run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit) + PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { + run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit, crypto) }); /// Bn128 add precompile with BYZANTIUM gas rules @@ -36,8 +36,8 @@ pub mod add { /// Bn128 add precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { - run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit) + PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { + run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit, crypto) }); } @@ -53,8 +53,8 @@ pub mod mul { /// Bn128 mul precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { - run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit) + PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { + run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit, crypto) }); /// Bn128 mul precompile with BYZANTIUM gas rules @@ -62,8 +62,8 @@ pub mod mul { /// Bn128 mul precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { - run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit) + PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { + run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit, crypto) }); } @@ -82,12 +82,13 @@ pub mod pair { /// Bn128 pair precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { run_pair( input, ISTANBUL_PAIR_PER_POINT, ISTANBUL_PAIR_BASE, gas_limit, + crypto, ) }); @@ -99,12 +100,13 @@ pub mod pair { /// Bn128 pair precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { run_pair( input, BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, gas_limit, + crypto, ) }); } @@ -149,7 +151,12 @@ pub const MUL_INPUT_LEN: usize = G1_LEN + SCALAR_LEN; pub const PAIR_ELEMENT_LEN: usize = G1_LEN + G2_LEN; /// Run the Bn128 add precompile -pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { +pub fn run_add( + input: &[u8], + gas_cost: u64, + gas_limit: u64, + _crypto: &dyn crate::Crypto, +) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -164,7 +171,12 @@ pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult } /// Run the Bn128 mul precompile -pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { +pub fn run_mul( + input: &[u8], + gas_cost: u64, + gas_limit: u64, + _crypto: &dyn crate::Crypto, +) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -184,6 +196,7 @@ pub fn run_pair( pair_per_point_cost: u64, pair_base_cost: u64, gas_limit: u64, + _crypto: &dyn crate::Crypto, ) -> PrecompileResult { let gas_used = (input.len() / PAIR_ELEMENT_LEN) as u64 * pair_per_point_cost + pair_base_cost; if gas_used > gas_limit { @@ -250,7 +263,7 @@ mod tests { ) .unwrap(); - let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto).unwrap(); assert_eq!(outcome.bytes, expected); // Zero sum test @@ -269,7 +282,7 @@ mod tests { ) .unwrap(); - let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto).unwrap(); assert_eq!(outcome.bytes, expected); // Out of gas test @@ -282,7 +295,7 @@ mod tests { ) .unwrap(); - let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 499); + let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 499, &crate::DefaultCrypto); assert!(matches!(res, Err(PrecompileError::OutOfGas))); @@ -295,7 +308,7 @@ mod tests { ) .unwrap(); - let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto).unwrap(); assert_eq!(outcome.bytes, expected); // Point not on curve fail @@ -308,7 +321,7 @@ mod tests { ) .unwrap(); - let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500); + let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto); assert!(matches!( res, Err(PrecompileError::Bn128AffineGFailedToCreate) @@ -331,7 +344,13 @@ mod tests { ) .unwrap(); - let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + let outcome = run_mul( + &input, + BYZANTIUM_MUL_GAS_COST, + 40_000, + &crate::DefaultCrypto, + ) + .unwrap(); assert_eq!(outcome.bytes, expected); // Out of gas test @@ -343,7 +362,12 @@ mod tests { ) .unwrap(); - let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 39_999); + let res = run_mul( + &input, + BYZANTIUM_MUL_GAS_COST, + 39_999, + &crate::DefaultCrypto, + ); assert!(matches!(res, Err(PrecompileError::OutOfGas))); // Zero multiplication test @@ -361,7 +385,13 @@ mod tests { ) .unwrap(); - let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + let outcome = run_mul( + &input, + BYZANTIUM_MUL_GAS_COST, + 40_000, + &crate::DefaultCrypto, + ) + .unwrap(); assert_eq!(outcome.bytes, expected); // No input test @@ -373,7 +403,13 @@ mod tests { ) .unwrap(); - let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + let outcome = run_mul( + &input, + BYZANTIUM_MUL_GAS_COST, + 40_000, + &crate::DefaultCrypto, + ) + .unwrap(); assert_eq!(outcome.bytes, expected); // Point not on curve fail @@ -385,7 +421,12 @@ mod tests { ) .unwrap(); - let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000); + let res = run_mul( + &input, + BYZANTIUM_MUL_GAS_COST, + 40_000, + &crate::DefaultCrypto, + ); assert!(matches!( res, Err(PrecompileError::Bn128AffineGFailedToCreate) @@ -419,6 +460,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, + &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); @@ -446,6 +488,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 259_999, + &crate::DefaultCrypto, ); assert!(matches!(res, Err(PrecompileError::OutOfGas))); @@ -460,6 +503,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, + &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); @@ -481,6 +525,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, + &crate::DefaultCrypto, ); assert!(matches!( res, @@ -502,6 +547,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, + &crate::DefaultCrypto, ); assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); @@ -526,6 +572,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, + &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); @@ -548,6 +595,7 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, + &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); diff --git a/crates/precompile/src/hash.rs b/crates/precompile/src/hash.rs index 58286d6485..dce89cbc3e 100644 --- a/crates/precompile/src/hash.rs +++ b/crates/precompile/src/hash.rs @@ -2,7 +2,6 @@ //! More details in [`sha256_run`] and [`ripemd160_run`] use super::calc_linear_cost_u32; use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; -use sha2::Digest; /// SHA-256 precompile pub const SHA256: PrecompileWithAddress = @@ -18,12 +17,12 @@ pub const RIPEMD160: PrecompileWithAddress = /// - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) /// - [Solidity Documentation on Mathematical and Cryptographic Functions](https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions) /// - [Address 0x02](https://etherscan.io/address/0000000000000000000000000000000000000002) -pub fn sha256_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn sha256_run(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> PrecompileResult { let cost = calc_linear_cost_u32(input.len(), 60, 12); if cost > gas_limit { Err(PrecompileError::OutOfGas) } else { - let output = sha2::Sha256::digest(input); + let output = crypto.sha256(input); Ok(PrecompileOutput::new(cost, output.to_vec().into())) } } @@ -34,16 +33,12 @@ pub fn sha256_run(input: &[u8], gas_limit: u64) -> PrecompileResult { /// - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) /// - [Solidity Documentation on Mathematical and Cryptographic Functions](https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions) /// - [Address 03](https://etherscan.io/address/0000000000000000000000000000000000000003) -pub fn ripemd160_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn ripemd160_run(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> PrecompileResult { let gas_used = calc_linear_cost_u32(input.len(), 600, 120); if gas_used > gas_limit { Err(PrecompileError::OutOfGas) } else { - let mut hasher = ripemd::Ripemd160::new(); - hasher.update(input); - - let mut output = [0u8; 32]; - hasher.finalize_into((&mut output[12..]).into()); + let output = crypto.ripemd160(input); Ok(PrecompileOutput::new(gas_used, output.to_vec().into())) } } diff --git a/crates/precompile/src/identity.rs b/crates/precompile/src/identity.rs index 9377bf440c..6af4c5725d 100644 --- a/crates/precompile/src/identity.rs +++ b/crates/precompile/src/identity.rs @@ -17,7 +17,7 @@ pub const IDENTITY_PER_WORD: u64 = 3; /// See: /// /// See: -pub fn identity_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn identity_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let gas_used = calc_linear_cost_u32(input.len(), IDENTITY_BASE, IDENTITY_PER_WORD); if gas_used > gas_limit { return Err(PrecompileError::OutOfGas); diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index 1c9c683458..2d0195d6bd 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -1,8 +1,8 @@ //! Interface for the precompiles. It contains the precompile result type, //! the precompile output type, and the precompile error type. -use core::fmt; +use core::fmt::{self, Debug}; use primitives::Bytes; -use std::string::String; +use std::{boxed::Box, string::String}; /// A precompile operation result type /// @@ -46,8 +46,20 @@ impl PrecompileOutput { } } -/// Precompile function type. Takes input and gas limit and returns precompile result. -pub type PrecompileFn = fn(&[u8], u64) -> PrecompileResult; +/// Crypto operations trait for precompiles. +pub trait Crypto: Send + Sync + Debug { + /// Clone box type + fn clone_box(&self) -> Box; + + /// Compute SHA-256 hash + fn sha256(&self, input: &[u8]) -> [u8; 32]; + + /// Compute RIPEMD-160 hash + fn ripemd160(&self, input: &[u8]) -> [u8; 32]; +} + +/// Precompile function type. Takes input, gas limit, and crypto implementation and returns precompile result. +pub type PrecompileFn = fn(&[u8], u64, &dyn Crypto) -> PrecompileResult; /// Precompile error type. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -121,3 +133,29 @@ impl fmt::Display for PrecompileError { f.write_str(s) } } + +/// Default implementation of the Crypto trait using the existing crypto libraries. +#[derive(Clone, Debug)] +pub struct DefaultCrypto; + +impl Crypto for DefaultCrypto { + fn clone_box(&self) -> Box { + Box::new(self.clone()) + } + + fn sha256(&self, input: &[u8]) -> [u8; 32] { + use sha2::Digest; + let output = sha2::Sha256::digest(input); + output.into() + } + + fn ripemd160(&self, input: &[u8]) -> [u8; 32] { + use ripemd::Digest; + let mut hasher = ripemd::Ripemd160::new(); + hasher.update(input); + + let mut output = [0u8; 32]; + hasher.finalize_into((&mut output[12..]).into()); + output + } +} diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index 9fb761cd7b..be09a4a503 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -37,7 +37,7 @@ pub const RETURN_VALUE: &[u8; 64] = &hex!( /// | versioned_hash | z | y | commitment | proof | /// | 32 | 32 | 32 | 48 | 48 | /// with z and y being padded 32 byte big endian values -pub fn run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { if gas_limit < GAS_COST { return Err(PrecompileError::OutOfGas); } @@ -137,7 +137,7 @@ mod tests { let expected_output = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); let gas = 50000; - let output = run(&input, gas).unwrap(); + let output = run(&input, gas, &crate::DefaultCrypto).unwrap(); assert_eq!(output.gas_used, gas); assert_eq!(output.bytes[..], expected_output); } diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 4cbb7eeee6..1499dccded 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -67,12 +67,34 @@ pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { } /// Precompiles contain map of precompile addresses to functions and HashSet of precompile addresses. -#[derive(Clone, Default, Debug)] +#[derive(Debug)] pub struct Precompiles { /// Precompiles inner: HashMap, /// Addresses of precompile addresses: HashSet
, + /// Crypto implementation + crypto: Box, +} + +impl Clone for Precompiles { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + addresses: self.addresses.clone(), + crypto: self.crypto.clone_box(), + } + } +} + +impl Default for Precompiles { + fn default() -> Self { + Self { + inner: Default::default(), + addresses: Default::default(), + crypto: Box::new(DefaultCrypto), + } + } } impl Precompiles { @@ -89,6 +111,26 @@ impl Precompiles { } } + /// Creates a new Precompiles instance with a custom crypto implementation. + pub fn with_crypto(spec: PrecompileSpecId, crypto: Box) -> Self { + let base = Self::new(spec).clone(); + Self { + inner: base.inner, + addresses: base.addresses, + crypto, + } + } + + /// Returns the crypto implementation. + pub fn crypto(&self) -> &dyn Crypto { + &*self.crypto + } + + /// Sets a custom crypto implementation. + pub fn set_crypto(&mut self, crypto: Box) { + self.crypto = crypto; + } + /// Returns precompiles for Homestead spec. pub fn homestead() -> &'static Self { static INSTANCE: OnceBox = OnceBox::new(); @@ -171,7 +213,7 @@ impl Precompiles { if #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] { let precompile = kzg_point_evaluation::POINT_EVALUATION.clone(); } else { - let precompile = PrecompileWithAddress(u64_to_address(0x0A), |_,_| Err(PrecompileError::Fatal("c-kzg feature is not enabled".into()))); + let precompile = PrecompileWithAddress(u64_to_address(0x0A), |_,_,_| Err(PrecompileError::Fatal("c-kzg feature is not enabled".into()))); } } @@ -278,7 +320,11 @@ impl Precompiles { let addresses = inner.keys().cloned().collect::>(); - Self { inner, addresses } + Self { + inner, + addresses, + crypto: self.crypto.clone_box(), + } } /// Returns intersection of `self` and `other`. @@ -295,7 +341,11 @@ impl Precompiles { let addresses = inner.keys().cloned().collect::>(); - Self { inner, addresses } + Self { + inner, + addresses, + crypto: self.crypto.clone_box(), + } } } diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index 08300abe3c..629f532635 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -45,7 +45,11 @@ fn modexp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec { /// See: /// See: -pub fn byzantium_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn byzantium_run( + input: &[u8], + gas_limit: u64, + _crypto: &dyn crate::Crypto, +) -> PrecompileResult { run_inner::<_, false>(input, gas_limit, 0, |a, b, c, d| { byzantium_gas_calc(a, b, c, d) }) @@ -53,7 +57,7 @@ pub fn byzantium_run(input: &[u8], gas_limit: u64) -> PrecompileResult { /// See: /// Gas cost of berlin is modified from byzantium. -pub fn berlin_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn berlin_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { run_inner::<_, false>(input, gas_limit, 200, |a, b, c, d| { berlin_gas_calc(a, b, c, d) }) @@ -61,7 +65,7 @@ pub fn berlin_run(input: &[u8], gas_limit: u64) -> PrecompileResult { /// See: /// Gas cost of berlin is modified from byzantium. -pub fn osaka_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn osaka_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { run_inner::<_, true>(input, gas_limit, 500, |a, b, c, d| { osaka_gas_calc(a, b, c, d) }) @@ -418,7 +422,7 @@ mod tests { fn test_byzantium_modexp_gas() { for (test, &test_gas) in TESTS.iter().zip(BYZANTIUM_GAS.iter()) { let input = hex::decode(test.input).unwrap(); - let res = byzantium_run(&input, 100_000_000).unwrap(); + let res = byzantium_run(&input, 100_000_000, &crate::DefaultCrypto).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( res.gas_used, test_gas, @@ -433,7 +437,7 @@ mod tests { fn test_berlin_modexp_gas() { for (test, &test_gas) in TESTS.iter().zip(BERLIN_GAS.iter()) { let input = hex::decode(test.input).unwrap(); - let res = berlin_run(&input, 100_000_000).unwrap(); + let res = berlin_run(&input, 100_000_000, &crate::DefaultCrypto).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( res.gas_used, test_gas, @@ -448,7 +452,7 @@ mod tests { fn test_osaka_modexp_gas() { for (test, &test_gas) in TESTS.iter().zip(OSAKA_GAS.iter()) { let input = hex::decode(test.input).unwrap(); - let res = osaka_run(&input, 100_000_000).unwrap(); + let res = osaka_run(&input, 100_000_000, &crate::DefaultCrypto).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( res.gas_used, test_gas, @@ -461,7 +465,7 @@ mod tests { #[test] fn test_berlin_modexp_empty_input() { - let res = berlin_run(&Bytes::new(), 100_000).unwrap(); + let res = berlin_run(&Bytes::new(), 100_000, &crate::DefaultCrypto).unwrap(); let expected: Vec = Vec::new(); assert_eq!(res.bytes, expected) } @@ -526,7 +530,7 @@ mod tests { ]; for test in test_inputs { let input = test.input(); - let res = osaka_run(&input, 100_000_000).err(); + let res = osaka_run(&input, 100_000_000, &crate::DefaultCrypto).err(); if res != test.expected { panic!("test failed: {test:?} result: {res:?}"); } @@ -545,7 +549,7 @@ mod tests { 07", ) .unwrap(); - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!(res.bytes, vec![0x00], "0^5 mod 7 should be 0"); // Test case 2: Base equals modulus @@ -558,7 +562,7 @@ mod tests { 07", ) .unwrap(); - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!(res.bytes, vec![0x00], "7^3 mod 7 should be 0"); // Test case 3: Exponent is zero (result should always be 1) @@ -570,7 +574,7 @@ mod tests { 07", ) .unwrap(); - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!(res.bytes, vec![0x01], "5^0 mod 7 should be 1"); // Test case 4: Large base with small modulus @@ -584,7 +588,7 @@ mod tests { 03", ) .unwrap(); - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); // (2^256 - 1) = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // This is divisible by 3, so (2^256 - 1) mod 3 = 0 // Therefore 0^2 mod 3 = 0 @@ -599,14 +603,14 @@ mod tests { fn test_modexp_gas_edge_cases() { // Test minimum gas consumption with empty input // Byzantium has min_gas of 0 for empty input - let res = byzantium_run(&[], 100_000).unwrap(); + let res = byzantium_run(&[], 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!( res.gas_used, 0, "Empty input should use 0 gas for Byzantium" ); // Berlin has min_gas of 200 - let res = berlin_run(&[], 100_000).unwrap(); + let res = berlin_run(&[], 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!( res.gas_used, 200, "Empty input should use minimum gas 200 for Berlin" @@ -623,11 +627,11 @@ mod tests { ) .unwrap(); // For Byzantium, check that it computes correctly - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!(res.bytes, vec![0x00], "1^1 mod 1 = 0"); // For Berlin, minimum gas is 200 - let res = berlin_run(&input, 100_000).unwrap(); + let res = berlin_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!(res.gas_used, 200, "Berlin should use minimum gas of 200"); } @@ -643,7 +647,7 @@ mod tests { 0000000000000000000000000000000000000000000000000000000000000101", ) .unwrap(); - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); assert_eq!( res.bytes.len(), 32, @@ -665,8 +669,8 @@ mod tests { ) .unwrap(); - let byzantium_res = byzantium_run(&input, 10_000_000).unwrap(); - let berlin_res = berlin_run(&input, 10_000_000).unwrap(); + let byzantium_res = byzantium_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); + let berlin_res = berlin_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); assert!( berlin_res.gas_used < byzantium_res.gas_used, @@ -694,7 +698,7 @@ mod tests { .unwrap(); // Should succeed with exactly 1024 bytes - let res = osaka_run(&input, 100_000_000); + let res = osaka_run(&input, 100_000_000, &crate::DefaultCrypto); assert!(res.is_ok(), "1024-byte base should be allowed"); // Test with 1025 bytes - should fail @@ -708,7 +712,7 @@ mod tests { ) .unwrap(); - let res = osaka_run(&input_fail, 100_000_000); + let res = osaka_run(&input_fail, 100_000_000, &crate::DefaultCrypto); assert!( matches!(res, Err(PrecompileError::ModexpEip7823LimitSize)), "1025-byte base should be rejected" @@ -726,7 +730,7 @@ mod tests { ) .unwrap(); - let res = byzantium_run(&input, 100_000).unwrap(); + let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); // Should pad with zeros and compute ff00^ff00 mod ff00 assert!(res.bytes.len() == 2, "Result should be 2 bytes"); } @@ -744,7 +748,7 @@ mod tests { ) .unwrap(); - let res = byzantium_run(&input, 10_000_000).unwrap(); + let res = byzantium_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); assert_eq!(res.bytes.len(), 32, "Result should be 32 bytes"); // (2^256 - 1)^1 mod (2^256 - 2) = 1 assert_eq!(res.bytes[31], 1, "Max value mod (max-1) should be 1"); @@ -773,9 +777,9 @@ mod tests { for test_input in test_cases { let input = hex::decode(test_input).unwrap(); - let byzantium_res = byzantium_run(&input, 10_000_000).unwrap(); - let berlin_res = berlin_run(&input, 10_000_000).unwrap(); - let osaka_res = osaka_run(&input, 10_000_000).unwrap(); + let byzantium_res = byzantium_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); + let berlin_res = berlin_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); + let osaka_res = osaka_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); assert_eq!( byzantium_res.bytes, berlin_res.bytes, @@ -799,7 +803,7 @@ mod tests { .unwrap(); // Provide insufficient gas - let res = byzantium_run(&input, 1000); + let res = byzantium_run(&input, 1000, &crate::DefaultCrypto); assert!( matches!(res, Err(PrecompileError::OutOfGas)), "Should return OutOfGas error with insufficient gas" diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 2ac987af13..374f0d4792 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -30,7 +30,11 @@ pub const ECRECOVER: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_address(1), ec_recover_run); /// `ecrecover` precompile function. Read more about input and output format in [this module docs](self). -pub fn ec_recover_run(input: &[u8], gas_limit: u64) -> PrecompileResult { +pub fn ec_recover_run( + input: &[u8], + gas_limit: u64, + _crypto: &dyn crate::Crypto, +) -> PrecompileResult { const ECRECOVER_BASE: u64 = 3_000; if ECRECOVER_BASE > gas_limit { diff --git a/crates/precompile/src/secp256r1.rs b/crates/precompile/src/secp256r1.rs index 323f803f69..8e70cd5a50 100644 --- a/crates/precompile/src/secp256r1.rs +++ b/crates/precompile/src/secp256r1.rs @@ -46,8 +46,8 @@ pub const P256VERIFY_OSAKA: PrecompileWithAddress = /// | signed message hash | r | s | public key x | public key y | /// | :-----------------: | :-: | :-: | :----------: | :----------: | /// | 32 | 32 | 32 | 32 | 32 | -pub fn p256_verify(input: &[u8], gas_limit: u64) -> PrecompileResult { - p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE) +pub fn p256_verify(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> PrecompileResult { + p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE, crypto) } /// secp256r1 precompile logic with Osaka gas cost. It takes the input bytes sent to the precompile @@ -59,15 +59,24 @@ pub fn p256_verify(input: &[u8], gas_limit: u64) -> PrecompileResult { /// | signed message hash | r | s | public key x | public key y | /// | :-----------------: | :-: | :-: | :----------: | :----------: | /// | 32 | 32 | 32 | 32 | 32 | -pub fn p256_verify_osaka(input: &[u8], gas_limit: u64) -> PrecompileResult { - p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE_OSAKA) +pub fn p256_verify_osaka( + input: &[u8], + gas_limit: u64, + crypto: &dyn crate::Crypto, +) -> PrecompileResult { + p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE_OSAKA, crypto) } -fn p256_verify_inner(input: &[u8], gas_limit: u64, gas_cost: u64) -> PrecompileResult { +fn p256_verify_inner( + input: &[u8], + gas_limit: u64, + gas_cost: u64, + crypto: &dyn crate::Crypto, +) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); } - let result = if verify_impl(input).is_some() { + let result = if verify_impl(input, crypto).is_some() { B256::with_last_byte(1).into() } else { Bytes::new() @@ -77,7 +86,7 @@ fn p256_verify_inner(input: &[u8], gas_limit: u64, gas_cost: u64) -> PrecompileR /// Returns `Some(())` if the signature included in the input byte slice is /// valid, `None` otherwise. -pub fn verify_impl(input: &[u8]) -> Option<()> { +pub fn verify_impl(input: &[u8], _crypto: &dyn crate::Crypto) -> Option<()> { if input.len() != 160 { return None; } @@ -130,7 +139,7 @@ mod test { fn test_sig_verify(#[case] input: &str, #[case] expect_success: bool) { let input = Bytes::from_hex(input).unwrap(); let target_gas = 3_500u64; - let outcome = p256_verify(&input, target_gas).unwrap(); + let outcome = p256_verify(&input, target_gas, &crate::DefaultCrypto).unwrap(); assert_eq!(outcome.gas_used, 3_450u64); let expected_result = if expect_success { B256::with_last_byte(1).into() @@ -144,7 +153,7 @@ mod test { fn test_not_enough_gas_errors() { let input = Bytes::from_hex("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e").unwrap(); let target_gas = 2_500u64; - let result = p256_verify(&input, target_gas); + let result = p256_verify(&input, target_gas, &crate::DefaultCrypto); assert!(result.is_err()); assert_eq!(result.err(), Some(PrecompileError::OutOfGas)); @@ -155,7 +164,7 @@ mod test { #[case::fail_1("b5a77e7a90aa14e0bf5f337f06f597148676424fae26e175c6e5621c34351955289f319789da424845c9eac935245fcddd805950e2f02506d09be7e411199556d262144475b1fa46ad85250728c600c53dfd10f8b3f4adf140e27241aec3c2daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaef8afe82d200a5bb36b5462166e8ce77f2d831a52ef2135b2af188110beaefb1", false)] fn test_verify_impl(#[case] input: &str, #[case] expect_success: bool) { let input = Bytes::from_hex(input).unwrap(); - let result = verify_impl(&input); + let result = verify_impl(&input, &crate::DefaultCrypto); assert_eq!(result.is_some(), expect_success); } From 76787ffb58593df7584d1716300e6a2db97170fd Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 03:51:13 +0200 Subject: [PATCH 03/78] chore: add gas_limit to revme evm (#2779) --- bins/revme/src/cmd/evmrunner.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 8fda0fac16..87ca3c7cc2 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -40,12 +40,18 @@ pub struct Cmd { /// Overrides the positional `bytecode` argument. #[arg(long)] path: Option, + /// Whether to run in benchmarking mode #[arg(long)] bench: bool, + /// Hex-encoded input/calldata bytes #[arg(long, default_value = "")] input: String, + /// Gas limit + #[arg(long, default_value = "1000000000")] + gas_limit: u64, + /// Whether to print the state #[arg(long)] state: bool, @@ -92,6 +98,7 @@ impl Cmd { .kind(TxKind::Call(BENCH_TARGET)) .data(input) .nonce(nonce) + .gas_limit(self.gas_limit) .build() .unwrap(); From 1ad68df196b3441588de935e8eb28a58849e487a Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 03:52:19 +0200 Subject: [PATCH 04/78] chore: collapse debug info for interpreter macros (#2780) Without this attribute, debug info will point into the macro, but this is quite annoying when debugging/profiling. e.g. `gas!` will show up in a separate stack frame in `samply`. Reference: https://doc.rust-lang.org/nightly/reference/attributes/debugger.html#r-attributes.debugger.collapse_debuginfo --- crates/interpreter/src/instructions/macros.rs | 27 +++++++++++-------- crates/interpreter/src/macros.rs | 2 ++ 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index b361c0369a..5af7001c27 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -2,6 +2,7 @@ /// `const` Option `?`. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! tri { ($e:expr) => { match $e { @@ -13,6 +14,7 @@ macro_rules! tri { /// Fails the instruction if the current call is static. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! require_non_staticcall { ($interpreter:expr) => { if $interpreter.runtime_flag.is_static() { @@ -25,6 +27,7 @@ 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)] macro_rules! otry { ($expression: expr) => {{ let Some(value) = $expression else { @@ -34,19 +37,9 @@ macro_rules! otry { }}; } -/// Error if the current call is executing EOF. -#[macro_export] -macro_rules! require_eof { - ($interpreter:expr) => { - if !$interpreter.runtime_flag.is_eof() { - $interpreter.halt($crate::InstructionResult::EOFOpcodeDisabledInLegacy); - return; - } - }; -} - /// Check if the `SPEC` is enabled, and fail the instruction if it is not. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! check { ($interpreter:expr, $min:ident) => { if !$interpreter @@ -62,6 +55,7 @@ macro_rules! check { /// Records a `gas` cost and fails the instruction if it would exceed the available gas. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! gas { ($interpreter:expr, $gas:expr) => { $crate::gas!($interpreter, $gas, ()) @@ -76,6 +70,7 @@ macro_rules! gas { /// 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, ()) @@ -94,6 +89,7 @@ macro_rules! gas_or_fail { /// Resizes the interpreterreter memory if necessary. Fails the instruction if the memory or gas limit /// is exceeded. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! resize_memory { ($interpreter:expr, $offset:expr, $len:expr) => { $crate::resize_memory!($interpreter, $offset, $len, ()) @@ -113,6 +109,7 @@ macro_rules! resize_memory { /// Pops n values from the stack. Fails the instruction if n values can't be popped. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! popn { ([ $($x:ident),* ],$interpreterreter:expr $(,$ret:expr)? ) => { let Some([$( $x ),*]) = $interpreterreter.stack.popn() else { @@ -124,6 +121,7 @@ macro_rules! popn { #[doc(hidden)] #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! _count { (@count) => { 0 }; (@count $head:tt $($tail:tt)*) => { 1 + _count!(@count $($tail)*) }; @@ -132,6 +130,7 @@ macro_rules! _count { /// Pops n values from the stack and returns the top value. Fails the instruction if n values can't be popped. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! popn_top { ([ $($x:ident),* ], $top:ident, $interpreter:expr $(,$ret:expr)? ) => { /* @@ -152,6 +151,7 @@ macro_rules! popn_top { /// Pushes a `B256` value onto the stack. Fails the instruction if the stack is full. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! push { ($interpreter:expr, $x:expr $(,$ret:item)?) => ( if !($interpreter.stack.push($x)) { @@ -163,6 +163,7 @@ macro_rules! push { /// Converts a `U256` value to a `u64`, saturating to `MAX` if the value is too large. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! as_u64_saturated { ($v:expr) => { match $v.as_limbs() { @@ -179,6 +180,7 @@ macro_rules! as_u64_saturated { /// Converts a `U256` value to a `usize`, saturating to `MAX` if the value is too large. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! as_usize_saturated { ($v:expr) => { usize::try_from($crate::as_u64_saturated!($v)).unwrap_or(usize::MAX) @@ -187,6 +189,7 @@ macro_rules! as_usize_saturated { /// Converts a `U256` value to a `isize`, saturating to `isize::MAX` if the value is too large. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! as_isize_saturated { ($v:expr) => { // `isize_try_from(u64::MAX)`` will fail and return isize::MAX @@ -197,6 +200,7 @@ macro_rules! as_isize_saturated { /// Converts a `U256` value to a `usize`, failing the instruction if the value is too large. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! as_usize_or_fail { ($interpreter:expr, $v:expr) => { $crate::as_usize_or_fail_ret!($interpreter, $v, ()) @@ -209,6 +213,7 @@ macro_rules! as_usize_or_fail { /// Converts a `U256` value to a `usize` and returns `ret`, /// failing the instruction if the value is too large. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! as_usize_or_fail_ret { ($interpreter:expr, $v:expr, $ret:expr) => { $crate::as_usize_or_fail_ret!( diff --git a/crates/interpreter/src/macros.rs b/crates/interpreter/src/macros.rs index 7b28fdefd6..004d940122 100644 --- a/crates/interpreter/src/macros.rs +++ b/crates/interpreter/src/macros.rs @@ -1,6 +1,7 @@ /// Macro that triggers `unreachable!` in debug builds but uses unchecked unreachable in release builds. /// This provides better error messages during development while optimizing for performance in release. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! debug_unreachable { ($($t:tt)*) => { if cfg!(debug_assertions) { @@ -15,6 +16,7 @@ macro_rules! debug_unreachable { /// In debug builds, this will trigger unreachable code if the assumption is false. /// In release builds, this serves as an optimization hint. #[macro_export] +#[collapse_debuginfo(yes)] macro_rules! assume { ($e:expr $(,)?) => { if !$e { From 9c0a3d2f42c919b570ad8aa3aba0d537dc563063 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 12:01:57 +0200 Subject: [PATCH 05/78] chore: fix clippy (#2785) --- bins/revme/src/cmd/bench/transfer_multi.rs | 2 +- crates/precompile/src/blake2.rs | 3 ++- crates/precompile/src/bls12_381/g1_msm.rs | 2 +- crates/precompile/src/bls12_381/g2_msm.rs | 2 +- crates/precompile/src/bls12_381/pairing.rs | 2 +- crates/precompile/src/bn128.rs | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/bins/revme/src/cmd/bench/transfer_multi.rs b/bins/revme/src/cmd/bench/transfer_multi.rs index 9c3e85eefb..a6e0bcd639 100644 --- a/bins/revme/src/cmd/bench/transfer_multi.rs +++ b/bins/revme/src/cmd/bench/transfer_multi.rs @@ -73,7 +73,7 @@ pub fn run(criterion: &mut Criterion) { |inputs| { for (i, tx) in inputs.into_iter().enumerate() { let _ = evm.transact_one(tx).unwrap(); - if i % 40 == 0 { + if i.is_multiple_of(40) { evm.commit_inner(); } } diff --git a/crates/precompile/src/blake2.rs b/crates/precompile/src/blake2.rs index 1582faa10f..6a56acf64d 100644 --- a/crates/precompile/src/blake2.rs +++ b/crates/precompile/src/blake2.rs @@ -190,6 +190,7 @@ macro_rules! _MM_SHUFFLE { /// Code adapted from https://github.com/oconnor663/blake2_simd/blob/82b3e2aee4d2384aabbeb146058301ff0dbd453f/blake2b/src/avx2.rs #[cfg(all(target_feature = "avx2", feature = "std"))] +#[allow(clippy::ptr_offset_with_cast)] // From array_refs mod avx2 { #[cfg(target_arch = "x86")] use core::arch::x86::*; @@ -510,7 +511,7 @@ mod avx2 { #[inline(always)] pub(crate) fn count_high(count: Count) -> Word { - (count >> 8 * size_of::()) as Word + (count >> Word::BITS as usize) as Word } #[inline(always)] diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index 1e20d67cbf..d6aea05020 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -22,7 +22,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_MSM_ADDRE /// See also: pub fn g1_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let input_len = input.len(); - if input_len == 0 || input_len % G1_MSM_INPUT_LENGTH != 0 { + if input_len == 0 || !input_len.is_multiple_of(G1_MSM_INPUT_LENGTH) { return Err(PrecompileError::Other(format!( "G1MSM input length should be multiple of {G1_MSM_INPUT_LENGTH}, was {input_len}", ))); diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index 1d79791ce1..f6322d5ff3 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -22,7 +22,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_MSM_ADDRE /// See also: pub fn g2_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let input_len = input.len(); - if input_len == 0 || input_len % G2_MSM_INPUT_LENGTH != 0 { + if input_len == 0 || !input_len.is_multiple_of(G2_MSM_INPUT_LENGTH) { return Err(PrecompileError::Other(format!( "G2MSM input length should be multiple of {G2_MSM_INPUT_LENGTH}, was {input_len}", ))); diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index b0ca4f6b49..d50586fdf9 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -27,7 +27,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(PAIRING_ADDR /// See also: pub fn pairing(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { let input_len = input.len(); - if input_len == 0 || input_len % PAIRING_INPUT_LENGTH != 0 { + if input_len == 0 || !input_len.is_multiple_of(PAIRING_INPUT_LENGTH) { return Err(PrecompileError::Other(format!( "Pairing input length should be multiple of {PAIRING_INPUT_LENGTH}, was {input_len}" ))); diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index 72f8a505c1..555b96da4d 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -203,7 +203,7 @@ pub fn run_pair( return Err(PrecompileError::OutOfGas); } - if input.len() % PAIR_ELEMENT_LEN != 0 { + if !input.len().is_multiple_of(PAIR_ELEMENT_LEN) { return Err(PrecompileError::Bn128PairLength); } From 7f081bf23bd74c2c73e112eff338bae6817ae1c4 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 14:04:25 +0200 Subject: [PATCH 06/78] chore: add OnceLock re-export with no_std support (#2787) --- Cargo.lock | 4 +-- Cargo.toml | 1 - crates/bytecode/Cargo.toml | 2 -- crates/bytecode/src/legacy/jump_map.rs | 9 ++---- crates/op-revm/Cargo.toml | 4 --- crates/op-revm/src/precompiles.rs | 15 ++++----- crates/precompile/Cargo.toml | 4 --- crates/precompile/src/lib.rs | 31 +++++++++--------- crates/primitives/Cargo.toml | 6 +++- crates/primitives/src/lib.rs | 2 ++ crates/primitives/src/once_lock.rs | 45 ++++++++++++++++++++++++++ 11 files changed, 78 insertions(+), 45 deletions(-) create mode 100644 crates/primitives/src/once_lock.rs diff --git a/Cargo.lock b/Cargo.lock index 09958e91f3..0c4a321d41 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3039,7 +3039,6 @@ dependencies = [ "alloy-primitives", "alloy-sol-types", "auto_impl", - "once_cell", "revm", "rstest", "serde", @@ -3795,7 +3794,6 @@ name = "revm-bytecode" version = "6.1.0" dependencies = [ "bitvec", - "once_cell", "paste", "phf", "revm-primitives", @@ -3932,7 +3930,6 @@ dependencies = [ "k256", "kzg-rs", "libsecp256k1", - "once_cell", "p256", "rand 0.9.1", "revm-primitives", @@ -3950,6 +3947,7 @@ version = "20.1.0" dependencies = [ "alloy-primitives", "num_enum", + "once_cell", "serde", ] diff --git a/Cargo.toml b/Cargo.toml index b096e420d4..2a7b79cac9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,7 +108,6 @@ auto_impl = "1.3.0" bitflags = { version = "2.9.1", default-features = false } cfg-if = { version = "1.0", default-features = false } derive-where = { version = "1.5.0", default-features = false } -once_cell = { version = "1.21", default-features = false } rand = "0.9" tokio = "1.45" either = { version = "1.15.0", default-features = false } diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index 78114d50f8..134122d5e1 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -22,7 +22,6 @@ primitives.workspace = true # Jumpmap bitvec = { workspace = true, features = ["alloc"] } -once_cell = { workspace = true, features = ["alloc"] } # Optional serde = { workspace = true, features = ["derive", "rc"], optional = true } @@ -37,7 +36,6 @@ std = [ "serde?/std", "primitives/std", "bitvec/std", - "once_cell/std", "phf?/std", ] hashbrown = ["primitives/hashbrown"] diff --git a/crates/bytecode/src/legacy/jump_map.rs b/crates/bytecode/src/legacy/jump_map.rs index d66dceab28..b4a99ebd7f 100644 --- a/crates/bytecode/src/legacy/jump_map.rs +++ b/crates/bytecode/src/legacy/jump_map.rs @@ -3,8 +3,7 @@ use core::{ cmp::Ordering, hash::{Hash, Hasher}, }; -use once_cell::race::OnceBox; -use primitives::hex; +use primitives::{hex, OnceLock}; use std::{fmt::Debug, sync::Arc}; /// A table of valid `jump` destinations. @@ -80,10 +79,8 @@ impl Debug for JumpTable { impl Default for JumpTable { #[inline] fn default() -> Self { - static DEFAULT: OnceBox = OnceBox::new(); - DEFAULT - .get_or_init(|| Self::new(BitVec::default()).into()) - .clone() + static DEFAULT: OnceLock = OnceLock::new(); + DEFAULT.get_or_init(|| Self::new(BitVec::default())).clone() } } diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 5b8f39ae75..c4a93b0516 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -21,9 +21,6 @@ workspace = true revm.workspace = true auto_impl.workspace = true -# static precompile sets. -once_cell = { workspace = true, features = ["alloc"] } - # Optional serde = { workspace = true, features = ["derive", "rc"], optional = true } @@ -41,7 +38,6 @@ std = [ "serde?/std", "revm/std", "alloy-sol-types/std", - "once_cell/std", "sha2/std", "serde_json/std", "alloy-primitives/std", diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index cef2029f94..1d38296d00 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -1,6 +1,5 @@ //! Contains Optimism specific precompiles. use crate::OpSpecId; -use once_cell::race::OnceBox; use revm::{ context::Cfg, context_interface::ContextTr, @@ -10,7 +9,7 @@ use revm::{ self, bn128, secp256r1, PrecompileError, PrecompileResult, PrecompileWithAddress, Precompiles, }, - primitives::{hardfork::SpecId, Address}, + primitives::{hardfork::SpecId, Address, OnceLock}, }; use std::boxed::Box; use std::string::String; @@ -56,29 +55,29 @@ impl OpPrecompiles { /// Returns precompiles for Fjord spec. pub fn fjord() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Precompiles::cancun().clone(); // RIP-7212: secp256r1 P256verify precompiles.extend([secp256r1::P256VERIFY]); - Box::new(precompiles) + precompiles }) } /// Returns precompiles for Granite spec. pub fn granite() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = fjord().clone(); // Restrict bn256Pairing input size precompiles.extend([bn128_pair::GRANITE]); - Box::new(precompiles) + precompiles }) } /// Returns precompiles for isthumus spec. pub fn isthmus() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = granite().clone(); // Prague bls12 precompiles @@ -89,7 +88,7 @@ pub fn isthmus() -> &'static Precompiles { bls12_381::ISTHMUS_G2_MSM, bls12_381::ISTHMUS_PAIRING, ]); - Box::new(precompiles) + precompiles }) } diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 450736a400..61a02a7b22 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -25,9 +25,6 @@ aurora-engine-modexp.workspace = true # gmp wrapper rug = { workspace = true, features = ["integer"], optional = true } -# static precompile sets. -once_cell = { workspace = true, features = ["alloc"] } - # ecRecover k256 = { workspace = true, features = ["ecdsa"] } secp256k1 = { workspace = true, features = [ @@ -85,7 +82,6 @@ default = ["std", "c-kzg", "secp256k1", "portable", "blst"] std = [ "primitives/std", "k256/std", - "once_cell/std", "ripemd/std", "sha2/std", "c-kzg?/std", diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 1499dccded..8de8c7d71f 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -57,8 +57,7 @@ use aurora_engine_modexp as _; use cfg_if::cfg_if; use core::hash::Hash; -use once_cell::race::OnceBox; -use primitives::{hardfork::SpecId, Address, HashMap, HashSet}; +use primitives::{hardfork::SpecId, Address, HashMap, HashSet, OnceLock}; use std::{boxed::Box, vec::Vec}; /// Calculate the linear cost of a precompile. @@ -133,7 +132,7 @@ impl Precompiles { /// Returns precompiles for Homestead spec. pub fn homestead() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Precompiles::default(); precompiles.extend([ @@ -142,7 +141,7 @@ impl Precompiles { hash::RIPEMD160, identity::FUN, ]); - Box::new(precompiles) + precompiles }) } @@ -153,7 +152,7 @@ impl Precompiles { /// Returns precompiles for Byzantium spec. pub fn byzantium() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::homestead().clone(); precompiles.extend([ @@ -165,13 +164,13 @@ impl Precompiles { bn128::mul::BYZANTIUM, bn128::pair::BYZANTIUM, ]); - Box::new(precompiles) + precompiles }) } /// Returns precompiles for Istanbul spec. pub fn istanbul() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::byzantium().clone(); precompiles.extend([ @@ -182,20 +181,20 @@ impl Precompiles { // EIP-152: Add BLAKE2 compression function `F` precompile. blake2::FUN, ]); - Box::new(precompiles) + precompiles }) } /// Returns precompiles for Berlin spec. pub fn berlin() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::istanbul().clone(); precompiles.extend([ // EIP-2565: ModExp Gas Cost. modexp::BERLIN, ]); - Box::new(precompiles) + precompiles }) } @@ -204,7 +203,7 @@ impl Precompiles { /// If the `c-kzg` feature is not enabled KZG Point Evaluation precompile will not be included, /// effectively making this the same as Berlin. pub fn cancun() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::berlin().clone(); @@ -222,27 +221,27 @@ impl Precompiles { precompile, ]); - Box::new(precompiles) + precompiles }) } /// Returns precompiles for Prague spec. pub fn prague() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::cancun().clone(); precompiles.extend(bls12_381::precompiles()); - Box::new(precompiles) + precompiles }) } /// Returns precompiles for Osaka spec. pub fn osaka() -> &'static Self { - static INSTANCE: OnceBox = OnceBox::new(); + static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::prague().clone(); precompiles.extend([modexp::OSAKA, secp256r1::P256VERIFY_OSAKA]); - Box::new(precompiles) + precompiles }) } diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index dc6f7a321e..0fdadd579b 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -22,13 +22,17 @@ alloy-primitives = { workspace = true, features = ["rlp", "map"] } # mics num_enum = { version = "0.7.3", default-features = false } +once_cell = { version = "1.21", default-features = false, features = [ + "alloc", + "race", +] } # Optional serde = { workspace = true, features = ["derive", "rc"], optional = true } [features] default = ["std"] -std = ["alloy-primitives/std", "serde?/std", "num_enum/std"] +std = ["alloy-primitives/std", "serde?/std", "num_enum/std", "once_cell/std"] serde = ["dep:serde", "alloy-primitives/serde"] map-foldhash = ["alloy-primitives/map-foldhash"] diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index 7c60172a0f..b78028d94a 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -17,8 +17,10 @@ pub mod eip7825; pub mod eip7907; pub mod eip7918; pub mod hardfork; +mod once_lock; pub use constants::*; +pub use once_lock::OnceLock; // Reexport alloy primitives. diff --git a/crates/primitives/src/once_lock.rs b/crates/primitives/src/once_lock.rs new file mode 100644 index 0000000000..fd863846bc --- /dev/null +++ b/crates/primitives/src/once_lock.rs @@ -0,0 +1,45 @@ +//! `OnceLock` abstraction that uses [`std::sync::OnceLock`] when available, once_cell otherwise. + +#[cfg(not(feature = "std"))] +mod no_std_impl { + use once_cell::race::OnceBox; + use std::boxed::Box; + + /// A thread-safe cell which can be written to only once. + #[derive(Debug)] + pub struct OnceLock { + inner: OnceBox, + } + + impl Default for OnceLock { + fn default() -> Self { + Self::new() + } + } + + impl OnceLock { + /// Creates a new empty OnceLock. + pub const fn new() -> Self { + Self { + inner: OnceBox::new(), + } + } + + /// Gets the contents of the OnceLock, initializing it if necessary. + pub fn get_or_init(&self, f: F) -> &T + where + F: FnOnce() -> T, + T: Into>, + { + self.inner.get_or_init(|| f().into()) + } + } +} + +#[cfg(feature = "std")] +use once_cell as _; +#[cfg(feature = "std")] +pub use std::sync::OnceLock; + +#[cfg(not(feature = "std"))] +pub use no_std_impl::OnceLock; From c925acc4f4b5964e446acbb34620ce541a6b2ccd Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 14:10:19 +0200 Subject: [PATCH 07/78] ci: unpin typos (#2788) --- .github/workflows/ci.yml | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f9d19b12ef..03a3fbf842 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -111,7 +111,6 @@ jobs: components: rustfmt - run: cargo fmt --all --check - # Check crates correctly propagate features feature-propagation: runs-on: ubuntu-latest timeout-minutes: 20 @@ -123,13 +122,9 @@ jobs: zepter --version time zepter run check - typos-check: - name: TyposCheck - timeout-minutes: 5 + typos: runs-on: ubuntu-latest + timeout-minutes: 30 steps: - uses: actions/checkout@v4 - - uses: crate-ci/typos@v1.22.7 - with: - config: ./typos.toml - isolated: true + - uses: crate-ci/typos@v1 From c2a069d16391cc4f5c113f9c61ed42e6e733c130 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:16:37 +0200 Subject: [PATCH 08/78] chore: add rust-version and note about MSRV (#2789) Having rust-version set helps Cargo produce better error messages if the installed version is lower than the minimum specified. --- .github/workflows/ci.yml | 2 +- Cargo.toml | 3 ++- README.md | 6 ++++++ bins/revme/Cargo.toml | 1 + crates/bytecode/Cargo.toml | 1 + crates/context/Cargo.toml | 1 + crates/context/interface/Cargo.toml | 1 + crates/database/Cargo.toml | 21 +++++++++++---------- crates/database/interface/Cargo.toml | 15 +++------------ crates/handler/Cargo.toml | 1 + crates/inspector/Cargo.toml | 1 + crates/interpreter/Cargo.toml | 8 ++------ crates/op-revm/Cargo.toml | 1 + crates/precompile/Cargo.toml | 1 + crates/primitives/Cargo.toml | 1 + crates/revm/Cargo.toml | 1 + crates/state/Cargo.toml | 8 ++------ crates/statetest-types/Cargo.toml | 1 + examples/block_traces/Cargo.toml | 1 + examples/cheatcode_inspector/Cargo.toml | 1 + examples/contract_deployment/Cargo.toml | 1 + examples/custom_opcodes/Cargo.toml | 3 ++- examples/database_components/Cargo.toml | 1 + examples/erc20_gas/Cargo.toml | 1 + examples/my_evm/Cargo.toml | 1 + examples/uniswap_get_reserves/Cargo.toml | 1 + examples/uniswap_v2_usdc_swap/Cargo.toml | 1 + 27 files changed, 48 insertions(+), 37 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 03a3fbf842..80e2ee562b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: strategy: fail-fast: false matrix: - rust: ["stable", "beta", "nightly"] + rust: ["1.88", "stable", "nightly"] flags: ["--no-default-features", "", "--all-features"] steps: - uses: actions/checkout@v4 diff --git a/Cargo.toml b/Cargo.toml index 2a7b79cac9..6238be62ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -132,8 +132,9 @@ categories = ["no-std", "compilers", "cryptography::cryptocurrencies"] keywords = ["revm", "evm", "ethereum", "blockchain", "no_std"] repository = "https://github.com/bluealloy/revm" documentation = "https://bluealloy.github.io/revm/" -homepage = "" +homepage = "https://github.com/bluealloy/revm" edition = "2021" +rust-version = "1.88.0" [workspace.lints] rust.missing_debug_implementations = "warn" diff --git a/README.md b/README.md index 57a72e32a1..d0b30177e6 100644 --- a/README.md +++ b/README.md @@ -60,6 +60,12 @@ Some quick links can be found here. Some point to code documentation or the book * How to run Ethereum test can be found here: [book](https://bluealloy.github.io/revm/revme.html#running-eth-tests) * If there is more need for explanations please open a PR request. +## Supported Rust Versions (MSRV) + +Revm always aims to stay up-to-date with the latest stable Rust release. + +The Minimum Supported Rust Version (MSRV) may be updated at any time, so we can take advantage of new features and improvements in Rust. + ### Community: For questions please open a github issue or join the public telegram group: [https://t.me/+Ig4WDWOzikA3MzA0](https://t.me/+Ig4WDWOzikA3MzA0) diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 20c416ed6e..d35a1bc3d2 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -7,6 +7,7 @@ edition.workspace = true keywords.workspace = true license.workspace = true repository.workspace = true +rust-version.workspace = true [dependencies] # revm diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index 134122d5e1..c0eaf54d4f 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 6da5d5496d..6a61e6efd9 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index de26f16d8d..1e72618b9e 100644 --- a/crates/context/interface/Cargo.toml +++ b/crates/context/interface/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 97e27554c2..1424eb9bba 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true @@ -27,8 +28,8 @@ serde = { workspace = true, features = ["derive", "rc"], optional = true } # alloydb tokio = { workspace = true, features = [ - "rt-multi-thread", - "macros", + "rt-multi-thread", + "macros", ], optional = true } alloy-provider = { workspace = true, optional = true } alloy-eips = { workspace = true, optional = true } @@ -48,7 +49,7 @@ std = [ "database-interface/std", "primitives/std", "state/std", - "serde_json/std" + "serde_json/std", ] serde = [ "dep:serde", @@ -56,13 +57,13 @@ serde = [ "bytecode/serde", "database-interface/serde", "primitives/serde", - "state/serde" + "state/serde", ] alloydb = [ - "std", - "database-interface/asyncdb", - "dep:tokio", - "dep:alloy-provider", - "dep:alloy-eips", - "dep:alloy-transport", + "std", + "database-interface/asyncdb", + "dep:tokio", + "dep:alloy-provider", + "dep:alloy-eips", + "dep:alloy-transport", ] diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index 49ef0ba52c..f898efb4e2 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true @@ -37,16 +38,6 @@ rstest.workspace = true [features] default = ["std"] -std = [ - "serde?/std", - "primitives/std", - "state/std", - "either/std" -] -serde = [ - "dep:serde", - "primitives/serde", - "state/serde", - "either/serde" -] +std = ["serde?/std", "primitives/std", "state/std", "either/std"] +serde = ["dep:serde", "primitives/serde", "state/serde", "either/serde"] asyncdb = ["dep:tokio", "tokio/rt-multi-thread"] diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index eb5a2a201f..7cb95a10a3 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 1777ade610..553f176b5a 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index a03818785f..a07f25631a 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true @@ -30,12 +31,7 @@ bincode.workspace = true [features] default = ["std"] -std = [ - "serde?/std", - "primitives/std", - "context-interface/std", - "bytecode/std" -] +std = ["serde?/std", "primitives/std", "context-interface/std", "bytecode/std"] hashbrown = ["primitives/hashbrown"] serde = [ "dep:serde", diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index c4a93b0516..cd359e6f6f 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 61a02a7b22..e84b8f53fd 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 0fdadd579b..55d3e9c548 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 491c4ba9b7..6849bbf4d0 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 2ec2dbc95e..efc15e41af 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true @@ -29,10 +30,5 @@ serde = { workspace = true, features = ["derive", "rc"], optional = true } [features] default = ["std"] -std = [ - "serde?/std", - "primitives/std", - "bitflags/std", - "bytecode/std" -] +std = ["serde?/std", "primitives/std", "bitflags/std", "bytecode/std"] serde = ["dep:serde", "primitives/serde", "bitflags/serde", "bytecode/serde"] diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index e866c2100c..be5f10e420 100644 --- a/crates/statetest-types/Cargo.toml +++ b/crates/statetest-types/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/block_traces/Cargo.toml b/examples/block_traces/Cargo.toml index c21dc78c70..86f232819a 100644 --- a/examples/block_traces/Cargo.toml +++ b/examples/block_traces/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/cheatcode_inspector/Cargo.toml b/examples/cheatcode_inspector/Cargo.toml index b346d37688..1baa4e61b1 100644 --- a/examples/cheatcode_inspector/Cargo.toml +++ b/examples/cheatcode_inspector/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/contract_deployment/Cargo.toml b/examples/contract_deployment/Cargo.toml index 2586794344..2128c754d6 100644 --- a/examples/contract_deployment/Cargo.toml +++ b/examples/contract_deployment/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/custom_opcodes/Cargo.toml b/examples/custom_opcodes/Cargo.toml index 8a269c1503..f93d35af68 100644 --- a/examples/custom_opcodes/Cargo.toml +++ b/examples/custom_opcodes/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true @@ -17,4 +18,4 @@ rustdoc-args = ["--cfg", "docsrs"] workspace = true [dependencies] -revm = {workspace = true, features = ["std", "tracer"]} +revm = { workspace = true, features = ["std", "tracer"] } diff --git a/examples/database_components/Cargo.toml b/examples/database_components/Cargo.toml index 8aff4db8e7..9b06a437e7 100644 --- a/examples/database_components/Cargo.toml +++ b/examples/database_components/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/erc20_gas/Cargo.toml b/examples/erc20_gas/Cargo.toml index 2101c4a4c0..fb302eb5d8 100644 --- a/examples/erc20_gas/Cargo.toml +++ b/examples/erc20_gas/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/my_evm/Cargo.toml b/examples/my_evm/Cargo.toml index 9453097a42..b5a335171a 100644 --- a/examples/my_evm/Cargo.toml +++ b/examples/my_evm/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/uniswap_get_reserves/Cargo.toml b/examples/uniswap_get_reserves/Cargo.toml index d1d8d8df2d..846e226655 100644 --- a/examples/uniswap_get_reserves/Cargo.toml +++ b/examples/uniswap_get_reserves/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true diff --git a/examples/uniswap_v2_usdc_swap/Cargo.toml b/examples/uniswap_v2_usdc_swap/Cargo.toml index 90fd3f1372..e4157d015c 100644 --- a/examples/uniswap_v2_usdc_swap/Cargo.toml +++ b/examples/uniswap_v2_usdc_swap/Cargo.toml @@ -8,6 +8,7 @@ keywords.workspace = true license.workspace = true repository.workspace = true readme.workspace = true +rust-version.workspace = true [package.metadata.docs.rs] all-features = true From 15eddc42d4d3e11a4c4996ccc51f68b34a3b7802 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 16:17:29 +0200 Subject: [PATCH 09/78] chore: rename custom-precompile-journal (#2792) Same format as all the others. The name actually matters for the bench workflow to skip building. --- Cargo.lock | 16 ++++++++-------- examples/custom_precompile_journal/Cargo.toml | 6 +----- examples/custom_precompile_journal/src/main.rs | 4 +++- 3 files changed, 12 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0c4a321d41..78488c542c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1560,14 +1560,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "custom_precompile_journal" -version = "0.1.0" -dependencies = [ - "anyhow", - "revm", -] - [[package]] name = "darling" version = "0.20.11" @@ -1869,6 +1861,14 @@ dependencies = [ "revm", ] +[[package]] +name = "example-custom-precompile-journal" +version = "0.1.0" +dependencies = [ + "anyhow", + "revm", +] + [[package]] name = "example-database-components" version = "0.0.0" diff --git a/examples/custom_precompile_journal/Cargo.toml b/examples/custom_precompile_journal/Cargo.toml index cc46f6f2f5..d450da17a2 100644 --- a/examples/custom_precompile_journal/Cargo.toml +++ b/examples/custom_precompile_journal/Cargo.toml @@ -1,12 +1,8 @@ [package] -name = "custom_precompile_journal" +name = "example-custom-precompile-journal" version = "0.1.0" edition = "2021" -[[bin]] -name = "custom_precompile_journal" -path = "src/main.rs" - [dependencies] revm = { path = "../../crates/revm", features = ["optional_eip3607"] } anyhow = "1.0" diff --git a/examples/custom_precompile_journal/src/main.rs b/examples/custom_precompile_journal/src/main.rs index 2aaf791a62..6a4595775c 100644 --- a/examples/custom_precompile_journal/src/main.rs +++ b/examples/custom_precompile_journal/src/main.rs @@ -6,7 +6,9 @@ //! 3. Modifying account balances and storage from within a precompile //! 4. Integrating the custom precompile into a custom EVM implementation -use custom_precompile_journal::{precompile_provider::CUSTOM_PRECOMPILE_ADDRESS, CustomEvm}; +use example_custom_precompile_journal::{ + precompile_provider::CUSTOM_PRECOMPILE_ADDRESS, CustomEvm, +}; use revm::{ context::{result::InvalidTransaction, Context, ContextSetters, ContextTr, TxEnv}, context_interface::result::EVMError, From e42a93a86580da9c861e568f24d86482532f3560 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 24 Jul 2025 17:21:18 +0200 Subject: [PATCH 10/78] perf: improve inspector loop (#2776) --- crates/inspector/src/handler.rs | 106 ++++++++++++-------- crates/interpreter/src/interpreter_types.rs | 2 +- 2 files changed, 65 insertions(+), 43 deletions(-) diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index ba2b8570d5..43c7979770 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -7,6 +7,7 @@ use interpreter::{ FrameInput, Host, InitialAndFloorGas, InstructionContext, InstructionResult, Interpreter, InterpreterAction, InterpreterTypes, }; +use state::bytecode::opcode; /// Trait that extends [`Handler`] with inspection functionality. /// @@ -182,21 +183,13 @@ where CTX: ContextTr + Host, IT: InterpreterTypes, { - let mut log_num = context.journal_mut().logs().len(); - // Main loop - while interpreter.bytecode.is_not_end() { - // Get current opcode. - let opcode = interpreter.bytecode.opcode(); - - // Call Inspector step. + loop { inspector.step(interpreter, context); - if interpreter.bytecode.is_end() { - break; - } // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction // it will do noop and just stop execution of this contract + let opcode = interpreter.bytecode.opcode(); interpreter.bytecode.relative_jump(1); // Execute instruction. @@ -206,51 +199,80 @@ where }; instructions[opcode as usize](instruction_context); - // check if new log is added - let new_log = context.journal_mut().logs().len(); - if log_num < new_log { - // as there is a change in log number this means new log is added - let log = context.journal_mut().logs().last().unwrap().clone(); - inspector.log(interpreter, context, log); - log_num = new_log; + if (opcode::LOG0..=opcode::LOG4).contains(&opcode) { + inspect_log(interpreter, context, &mut inspector); } - // if loops is ending, break the loop so we can revert to the previous pointer and then call step_end. - if interpreter.bytecode.is_end() { - break; + let done = interpreter.bytecode.is_end(); + if done { + interpreter.bytecode.revert_to_previous_pointer(); } - // Call step_end. inspector.step_end(interpreter, context); - } - interpreter.bytecode.revert_to_previous_pointer(); - // call step_end again to handle the last instruction - inspector.step_end(interpreter, context); + if done { + break; + } + } let next_action = interpreter.take_next_action(); - // handle selfdestruct + // Handle selfdestruct. if let InterpreterAction::Return(result) = &next_action { if result.result == InstructionResult::SelfDestruct { - match context.journal_mut().journal().last() { - Some(JournalEntry::AccountDestroyed { - address, - target, - had_balance, - .. - }) => { - inspector.selfdestruct(*address, *target, *had_balance); - } - Some(JournalEntry::BalanceTransfer { - from, to, balance, .. - }) => { - inspector.selfdestruct(*from, *to, *balance); - } - _ => {} - } + inspect_selfdestruct(context, &mut inspector); } } next_action } + +#[inline(never)] +#[cold] +fn inspect_log( + interpreter: &mut Interpreter, + context: &mut CTX, + inspector: &mut impl Inspector, +) where + CTX: ContextTr + Host, + IT: InterpreterTypes, +{ + // `LOG*` instruction reverted. + if interpreter + .bytecode + .action() + .as_ref() + .is_some_and(|x| x.is_return()) + { + return; + } + + let log = context.journal_mut().logs().last().unwrap().clone(); + inspector.log(interpreter, context, log); +} + +#[inline(never)] +#[cold] +fn inspect_selfdestruct(context: &mut CTX, inspector: &mut impl Inspector) +where + CTX: ContextTr + Host, + IT: InterpreterTypes, +{ + if let Some( + JournalEntry::AccountDestroyed { + address: contract, + target: to, + had_balance: balance, + .. + } + | JournalEntry::BalanceTransfer { + from: contract, + to, + balance, + .. + }, + ) = context.journal_mut().journal().last() + { + inspector.selfdestruct(*contract, *to, *balance); + } +} diff --git a/crates/interpreter/src/interpreter_types.rs b/crates/interpreter/src/interpreter_types.rs index 810d1eec62..2d81406892 100644 --- a/crates/interpreter/src/interpreter_types.rs +++ b/crates/interpreter/src/interpreter_types.rs @@ -262,7 +262,7 @@ pub trait LoopControl { /// /// Previous pointer can be restored by calling [`LoopControl::revert_to_previous_pointer`]. fn set_action(&mut self, action: InterpreterAction); - /// Takes next action. + /// Returns the current action. fn action(&mut self) -> &mut Option; /// Returns instruction result #[inline] From 665f524c3d3eff418e86969bddc417049303bfc8 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 25 Jul 2025 11:48:19 +0200 Subject: [PATCH 11/78] chore: reuse global crypto provide idea (#2786) * add bn128 * add rest of impls * add cfg_if * uniform reexport * refactor * nit: function names * remove refs from blake * type alias + inlines * use trait for version hash * remove Result * test dynamic dispatch * revert static call * chore: reuse global crypto provide idea * fix compilation * add default impl to Crypto trait * nit rm alloc * nits * fix lock compilation * return bool for p256 verify fn --------- Co-authored-by: Kevaundray Wedderburn --- crates/handler/src/precompile_provider.rs | 2 +- crates/op-revm/src/precompiles.rs | 49 ++--- crates/precompile/bench/blake2.rs | 36 +--- crates/precompile/bench/ecrecover.rs | 9 +- crates/precompile/bench/eip1962.rs | 21 +-- crates/precompile/bench/eip2537.rs | 14 +- crates/precompile/bench/eip4844.rs | 2 +- crates/precompile/src/blake2.rs | 10 +- crates/precompile/src/bls12_381.rs | 20 +- crates/precompile/src/bls12_381/arkworks.rs | 22 +-- crates/precompile/src/bls12_381/blst.rs | 23 +-- crates/precompile/src/bls12_381/g1_add.rs | 8 +- crates/precompile/src/bls12_381/g1_msm.rs | 13 +- crates/precompile/src/bls12_381/g2_add.rs | 8 +- crates/precompile/src/bls12_381/g2_msm.rs | 13 +- .../precompile/src/bls12_381/map_fp2_to_g2.rs | 16 +- .../precompile/src/bls12_381/map_fp_to_g1.rs | 14 +- crates/precompile/src/bls12_381/pairing.rs | 7 +- crates/precompile/src/bn128.rs | 107 +++-------- crates/precompile/src/bn128/arkworks.rs | 6 +- crates/precompile/src/bn128/substrate.rs | 6 +- crates/precompile/src/hash.rs | 10 +- crates/precompile/src/identity.rs | 2 +- crates/precompile/src/interface.rs | 178 +++++++++++++++--- crates/precompile/src/kzg_point_evaluation.rs | 18 +- crates/precompile/src/lib.rs | 60 +----- crates/precompile/src/modexp.rs | 65 +++---- crates/precompile/src/secp256k1.rs | 12 +- crates/precompile/src/secp256r1.rs | 40 ++-- crates/primitives/src/once_lock.rs | 8 + crates/revm/src/lib.rs | 1 + 31 files changed, 366 insertions(+), 434 deletions(-) diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index a79e260087..62ca92d473 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -121,7 +121,7 @@ impl PrecompileProvider for EthPrecompiles { CallInput::Bytes(bytes) => bytes.0.iter().as_slice(), }; - match (*precompile)(input_bytes, gas_limit, self.precompiles.crypto()) { + match (*precompile)(input_bytes, gas_limit) { Ok(output) => { let underflow = result.gas.record_cost(output.gas_used); assert!(underflow, "Gas underflow is not possible"); diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index 1d38296d00..d7e2c8e4e3 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -145,16 +145,12 @@ pub mod bn128_pair { pub const GRANITE_MAX_INPUT_SIZE: usize = 112687; /// Bn128 pair precompile. pub const GRANITE: PrecompileWithAddress = - PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit, crypto| { - run_pair(input, gas_limit, crypto) + PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit| { + run_pair(input, gas_limit) }); /// Run the bn128 pair precompile with Optimism input limit. - pub fn run_pair( - input: &[u8], - gas_limit: u64, - crypto: &dyn precompile::Crypto, - ) -> PrecompileResult { + pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > GRANITE_MAX_INPUT_SIZE { return Err(PrecompileError::Bn128PairLength); } @@ -163,7 +159,6 @@ pub mod bn128_pair { bn128::pair::ISTANBUL_PAIR_PER_POINT, bn128::pair::ISTANBUL_PAIR_BASE, gas_limit, - crypto, ) } } @@ -194,45 +189,33 @@ pub mod bls12_381 { PrecompileWithAddress(PAIRING_ADDRESS, run_pair); /// Run the g1 msm precompile with Optimism input limit. - pub fn run_g1_msm( - input: &[u8], - gas_limit: u64, - crypto: &dyn precompile::Crypto, - ) -> PrecompileResult { + pub fn run_g1_msm(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(), )); } - precompile::bls12_381::g1_msm::g1_msm(input, gas_limit, crypto) + 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, - crypto: &dyn precompile::Crypto, - ) -> PrecompileResult { + pub fn run_g2_msm(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(), )); } - precompile::bls12_381::g2_msm::g2_msm(input, gas_limit, crypto) + 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, - crypto: &dyn precompile::Crypto, - ) -> PrecompileResult { + pub fn run_pair(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(), )); } - precompile::bls12_381::pairing::pairing(input, gas_limit, crypto) + precompile::bls12_381::pairing::pairing(input, gas_limit) } } @@ -271,7 +254,7 @@ mod tests { let expected = hex::decode("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(); - let outcome = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto).unwrap(); + let outcome = bn128_pair::run_pair(&input, 260_000).unwrap(); assert_eq!(outcome.bytes, expected); // Invalid input length @@ -284,17 +267,17 @@ mod tests { ) .unwrap(); - let res = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto); + let res = bn128_pair::run_pair(&input, 260_000); assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); // Valid input length shorter than 112687 let input = vec![1u8; 586 * bn128::PAIR_ELEMENT_LEN]; - let res = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto); + let res = bn128_pair::run_pair(&input, 260_000); assert!(matches!(res, Err(PrecompileError::OutOfGas))); // Input length longer than 112687 let input = vec![1u8; 587 * bn128::PAIR_ELEMENT_LEN]; - let res = bn128_pair::run_pair(&input, 260_000, &precompile::DefaultCrypto); + let res = bn128_pair::run_pair(&input, 260_000); assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); } @@ -336,7 +319,7 @@ 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, &precompile::DefaultCrypto); + let res = run_g1_msm(&input, 260_000); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) @@ -347,7 +330,7 @@ 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, &precompile::DefaultCrypto); + let res = run_g2_msm(&input, 260_000); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) @@ -358,7 +341,7 @@ 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, &precompile::DefaultCrypto); + let res = bls12_381::run_pair(&input, 260_000); assert!( matches!(res, Err(PrecompileError::Other(msg)) if msg.contains("input length too long")) diff --git a/crates/precompile/bench/blake2.rs b/crates/precompile/bench/blake2.rs index facf51eb84..053552fad4 100644 --- a/crates/precompile/bench/blake2.rs +++ b/crates/precompile/bench/blake2.rs @@ -20,9 +20,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/2_rounds", |b| { let input = &inputs[0]; // 2 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -30,9 +28,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/4_rounds", |b| { let input = &inputs[1]; // 4 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -40,9 +36,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/64_rounds", |b| { let input = &inputs[2]; // 64 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -50,9 +44,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/10_rounds", |b| { let input = &inputs[3]; // 10 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -60,9 +52,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/12_rounds", |b| { let input = &inputs[4]; // 12 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -70,9 +60,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/512_rounds", |b| { let input = &inputs[5]; // 512 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -80,9 +68,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/1024_rounds", |b| { let input = &inputs[6]; // 1024 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -90,9 +76,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/100K_rounds", |b| { let input = &inputs[7]; // 100000 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); @@ -100,9 +84,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, criterion::measurement::WallTi group.bench_function("blake2/200K_rounds", |b| { let input = &inputs[8]; // 200000 rounds b.iter(|| { - black_box( - blake2::run(black_box(input), u64::MAX, &revm_precompile::DefaultCrypto).unwrap(), - ); + black_box(blake2::run(black_box(input), u64::MAX).unwrap()); }); }); diff --git a/crates/precompile/bench/ecrecover.rs b/crates/precompile/bench/ecrecover.rs index 5cb2f1f4c1..dd2ff2fa5c 100644 --- a/crates/precompile/bench/ecrecover.rs +++ b/crates/precompile/bench/ecrecover.rs @@ -27,13 +27,6 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, M>) { let message_and_signature = Bytes::from(message_and_signature); group.bench_function("ecrecover precompile", |b| { - b.iter(|| { - ec_recover_run( - &message_and_signature, - u64::MAX, - &revm_precompile::DefaultCrypto, - ) - .unwrap() - }) + b.iter(|| ec_recover_run(&message_and_signature, u64::MAX).unwrap()) }); } diff --git a/crates/precompile/bench/eip1962.rs b/crates/precompile/bench/eip1962.rs index 95febdd1f0..92b547da95 100644 --- a/crates/precompile/bench/eip1962.rs +++ b/crates/precompile/bench/eip1962.rs @@ -22,15 +22,7 @@ pub fn add_bn128_add_benches(group: &mut BenchmarkGroup<'_, M>) let input = Bytes::from(ecadd_input); group.bench_function("bn128 add precompile", |b| { - b.iter(|| { - run_add( - &input, - ISTANBUL_ADD_GAS_COST, - 150, - &revm_precompile::DefaultCrypto, - ) - .unwrap() - }) + b.iter(|| run_add(&input, ISTANBUL_ADD_GAS_COST, 150).unwrap()) }); } @@ -46,15 +38,7 @@ pub fn add_bn128_mul_benches(group: &mut BenchmarkGroup<'_, M>) let input = Bytes::from(ecmul_input); group.bench_function("bn128 mul precompile", |b| { - b.iter(|| { - run_mul( - &input, - ISTANBUL_MUL_GAS_COST, - 6000, - &revm_precompile::DefaultCrypto, - ) - .unwrap() - }) + b.iter(|| run_mul(&input, ISTANBUL_MUL_GAS_COST, 6000).unwrap()) }); } @@ -85,7 +69,6 @@ pub fn add_bn128_pair_benches(group: &mut BenchmarkGroup<'_, M>) ISTANBUL_PAIR_PER_POINT, ISTANBUL_PAIR_BASE, u64::MAX, - &revm_precompile::DefaultCrypto, ) .unwrap() }) diff --git a/crates/precompile/bench/eip2537.rs b/crates/precompile/bench/eip2537.rs index acd75182dc..124ed82427 100644 --- a/crates/precompile/bench/eip2537.rs +++ b/crates/precompile/bench/eip2537.rs @@ -152,7 +152,7 @@ pub fn add_g1_add_benches(group: &mut BenchmarkGroup<'_, M>) { let precompile = *PRECOMPILE.precompile(); group.bench_function("g1_add", |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } @@ -167,7 +167,7 @@ pub fn add_g2_add_benches(group: &mut BenchmarkGroup<'_, M>) { let precompile = *PRECOMPILE.precompile(); group.bench_function("g2_add", |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } @@ -185,7 +185,7 @@ pub fn add_g1_msm_benches(group: &mut BenchmarkGroup<'_, M>) { let input = Bytes::from(test_vector); group.bench_function(format!("g1_msm (size {size})"), |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } } @@ -230,7 +230,7 @@ pub fn add_g2_msm_benches(group: &mut BenchmarkGroup<'_, M>) { let input = Bytes::from(test_vector); group.bench_function(format!("g2_msm (size {size})"), |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } } @@ -263,7 +263,7 @@ pub fn add_pairing_benches(group: &mut BenchmarkGroup<'_, M>) { let input = Bytes::from(test_vector); group.bench_function(format!("pairing ({pairs} pairs)"), |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } } @@ -284,7 +284,7 @@ pub fn add_map_fp_to_g1_benches(group: &mut BenchmarkGroup<'_, M let precompile = *PRECOMPILE.precompile(); group.bench_function("map_fp_to_g1", |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } @@ -311,6 +311,6 @@ pub fn add_map_fp2_to_g2_benches(group: &mut BenchmarkGroup<'_, let precompile = *PRECOMPILE.precompile(); group.bench_function("map_fp2_to_g2", |b| { - b.iter(|| precompile(&input, u64::MAX, &revm_precompile::DefaultCrypto).unwrap()); + b.iter(|| precompile(&input, u64::MAX).unwrap()); }); } diff --git a/crates/precompile/bench/eip4844.rs b/crates/precompile/bench/eip4844.rs index eb6f141ba2..c9c4a65c6e 100644 --- a/crates/precompile/bench/eip4844.rs +++ b/crates/precompile/bench/eip4844.rs @@ -18,6 +18,6 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, M>) { let gas = 50000; group.bench_function("kzg precompile", |b| { - b.iter(|| run(&kzg_input, gas, &revm_precompile::DefaultCrypto).unwrap()) + b.iter(|| run(&kzg_input, gas).unwrap()) }); } diff --git a/crates/precompile/src/blake2.rs b/crates/precompile/src/blake2.rs index 6a56acf64d..82bfca129c 100644 --- a/crates/precompile/src/blake2.rs +++ b/crates/precompile/src/blake2.rs @@ -1,6 +1,6 @@ //! Blake2 precompile. More details in [`run`] -use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; const F_ROUND: u64 = 1; const INPUT_LENGTH: usize = 213; @@ -11,13 +11,13 @@ pub const FUN: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_addre /// reference: /// input format: /// [4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f] -pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn run(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() != INPUT_LENGTH { return Err(PrecompileError::Blake2WrongLength); } // Parse number of rounds (4 bytes) - let rounds = u32::from_be_bytes(input[..4].try_into().unwrap()) as usize; + let rounds = u32::from_be_bytes(input[..4].try_into().unwrap()); let gas_used = rounds as u64 * F_ROUND; if gas_used > gas_limit { return Err(PrecompileError::OutOfGas); @@ -52,7 +52,7 @@ pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Precomp let t_0 = u64::from_le_bytes(input[196..204].try_into().unwrap()); let t_1 = u64::from_le_bytes(input[204..212].try_into().unwrap()); - algo::compress(rounds, &mut h, m, [t_0, t_1], f); + crypto().blake2_compress(rounds, &mut h, m, [t_0, t_1], f); let mut out = [0u8; 64]; for (i, h) in (0..64).step_by(8).zip(h.iter()) { @@ -640,7 +640,7 @@ mod tests { let time = Instant::now(); for i in 0..3000 { - let _ = run(&input[i % 3], u64::MAX, &crate::DefaultCrypto).unwrap(); + let _ = run(&input[i % 3], u64::MAX).unwrap(); } println!("duration: {:?}", time.elapsed()); } diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs index 879dcd60bc..5695c8cb77 100644 --- a/crates/precompile/src/bls12_381.rs +++ b/crates/precompile/src/bls12_381.rs @@ -4,23 +4,29 @@ use crate::PrecompileWithAddress; cfg_if::cfg_if! { if #[cfg(feature = "blst")]{ - mod blst; - use blst as crypto_backend; + pub(crate) mod blst; + pub(crate) use blst as crypto_backend; } else { - mod arkworks; - use arkworks as crypto_backend; + pub(crate) mod arkworks; + pub(crate) use arkworks as crypto_backend; } } // Re-export type aliases for use in submodules -use crate::bls12_381_const::FP_LENGTH; -type G1Point = ([u8; FP_LENGTH], [u8; FP_LENGTH]); -type G2Point = ( +use crate::bls12_381_const::{FP_LENGTH, SCALAR_LENGTH}; +/// G1 point represented as two field elements (x, y coordinates) +pub type G1Point = ([u8; FP_LENGTH], [u8; FP_LENGTH]); +/// G2 point represented as four field elements (x0, x1, y0, y1 coordinates) +pub type G2Point = ( [u8; FP_LENGTH], [u8; FP_LENGTH], [u8; FP_LENGTH], [u8; FP_LENGTH], ); +/// G1 point and scalar pair for MSM operations +pub type G1PointScalar = (G1Point, [u8; SCALAR_LENGTH]); +/// G2 point and scalar pair for MSM operations +pub type G2PointScalar = (G2Point, [u8; SCALAR_LENGTH]); type PairingPair = (G1Point, G2Point); pub mod g1_add; diff --git a/crates/precompile/src/bls12_381/arkworks.rs b/crates/precompile/src/bls12_381/arkworks.rs index b8eb0a437a..f557457b7c 100644 --- a/crates/precompile/src/bls12_381/arkworks.rs +++ b/crates/precompile/src/bls12_381/arkworks.rs @@ -360,7 +360,7 @@ 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(super) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { +pub fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { if pairs.is_empty() { return Ok(true); } @@ -405,10 +405,7 @@ pub(super) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result Result<[u8; G1_LENGTH], PrecompileError> { +pub fn p1_add_affine_bytes(a: G1Point, b: G1Point) -> Result<[u8; G1_LENGTH], PrecompileError> { let (a_x, a_y) = a; let (b_x, b_y) = b; // Parse first point @@ -426,10 +423,7 @@ pub(super) fn p1_add_affine_bytes( /// Performs point addition on two G2 points taking byte coordinates. #[inline] -pub(super) fn p2_add_affine_bytes( - a: G2Point, - b: G2Point, -) -> Result<[u8; G2_LENGTH], PrecompileError> { +pub fn p2_add_affine_bytes(a: G2Point, b: G2Point) -> Result<[u8; G2_LENGTH], PrecompileError> { let (a_x_0, a_x_1, a_y_0, a_y_1) = a; let (b_x_0, b_x_1, b_y_0, b_y_1) = b; // Parse first point @@ -447,9 +441,7 @@ pub(super) fn p2_add_affine_bytes( /// Maps a field element to a G1 point from bytes #[inline] -pub(super) fn map_fp_to_g1_bytes( - fp_bytes: &[u8; FP_LENGTH], -) -> Result<[u8; G1_LENGTH], PrecompileError> { +pub fn map_fp_to_g1_bytes(fp_bytes: &[u8; FP_LENGTH]) -> Result<[u8; G1_LENGTH], PrecompileError> { let fp = read_fp(fp_bytes)?; let result = map_fp_to_g1(&fp); Ok(encode_g1_point(&result)) @@ -457,7 +449,7 @@ pub(super) fn map_fp_to_g1_bytes( /// Maps field elements to a G2 point from bytes #[inline] -pub(super) fn map_fp2_to_g2_bytes( +pub fn map_fp2_to_g2_bytes( fp2_x: &[u8; FP_LENGTH], fp2_y: &[u8; FP_LENGTH], ) -> Result<[u8; G2_LENGTH], PrecompileError> { @@ -468,7 +460,7 @@ pub(super) fn map_fp2_to_g2_bytes( /// Performs multi-scalar multiplication (MSM) for G1 points taking byte inputs. #[inline] -pub(super) fn p1_msm_bytes( +pub fn p1_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G1_LENGTH], PrecompileError> { let mut g1_points = Vec::new(); @@ -505,7 +497,7 @@ pub(super) fn p1_msm_bytes( /// Performs multi-scalar multiplication (MSM) for G2 points taking byte inputs. #[inline] -pub(super) fn p2_msm_bytes( +pub fn p2_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G2_LENGTH], PrecompileError> { let mut g2_points = Vec::new(); diff --git a/crates/precompile/src/bls12_381/blst.rs b/crates/precompile/src/bls12_381/blst.rs index 822eed35ba..83dfb282f6 100644 --- a/crates/precompile/src/bls12_381/blst.rs +++ b/crates/precompile/src/bls12_381/blst.rs @@ -2,6 +2,7 @@ use super::{G1Point, G2Point, PairingPair}; use crate::{ + bls12_381::{G1PointScalar, G2PointScalar}, bls12_381_const::{FP_LENGTH, G1_LENGTH, G2_LENGTH, SCALAR_LENGTH, SCALAR_LENGTH_BITS}, PrecompileError, }; @@ -622,7 +623,7 @@ fn is_valid_be(input: &[u8; 48]) -> bool { /// Performs point addition on two G1 points taking byte coordinates. #[inline] -pub(super) fn p1_add_affine_bytes( +pub(crate) fn p1_add_affine_bytes( a: G1Point, b: G1Point, ) -> Result<[u8; G1_LENGTH], crate::PrecompileError> { @@ -643,7 +644,7 @@ pub(super) fn p1_add_affine_bytes( /// Performs point addition on two G2 points taking byte coordinates. #[inline] -pub(super) fn p2_add_affine_bytes( +pub(crate) fn p2_add_affine_bytes( a: G2Point, b: G2Point, ) -> Result<[u8; G2_LENGTH], crate::PrecompileError> { @@ -664,7 +665,7 @@ pub(super) fn p2_add_affine_bytes( /// Maps a field element to a G1 point from bytes #[inline] -pub(super) fn map_fp_to_g1_bytes( +pub(crate) fn map_fp_to_g1_bytes( fp_bytes: &[u8; FP_LENGTH], ) -> Result<[u8; G1_LENGTH], crate::PrecompileError> { let fp = read_fp(fp_bytes)?; @@ -674,7 +675,7 @@ pub(super) fn map_fp_to_g1_bytes( /// Maps field elements to a G2 point from bytes #[inline] -pub(super) fn map_fp2_to_g2_bytes( +pub(crate) fn map_fp2_to_g2_bytes( fp2_x: &[u8; FP_LENGTH], fp2_y: &[u8; FP_LENGTH], ) -> Result<[u8; G2_LENGTH], crate::PrecompileError> { @@ -685,10 +686,8 @@ pub(super) fn map_fp2_to_g2_bytes( /// Performs multi-scalar multiplication (MSM) for G1 points taking byte inputs. #[inline] -pub(super) fn p1_msm_bytes( - point_scalar_pairs: impl Iterator< - Item = Result<(G1Point, [u8; SCALAR_LENGTH]), crate::PrecompileError>, - >, +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(); @@ -724,10 +723,8 @@ pub(super) fn p1_msm_bytes( /// Performs multi-scalar multiplication (MSM) for G2 points taking byte inputs. #[inline] -pub(super) fn p2_msm_bytes( - point_scalar_pairs: impl Iterator< - Item = Result<(G2Point, [u8; SCALAR_LENGTH]), crate::PrecompileError>, - >, +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(); @@ -763,7 +760,7 @@ pub(super) 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(super) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { +pub(crate) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { if pairs.is_empty() { return Ok(true); } diff --git a/crates/precompile/src/bls12_381/g1_add.rs b/crates/precompile/src/bls12_381/g1_add.rs index 64d1989a48..606bb686cf 100644 --- a/crates/precompile/src/bls12_381/g1_add.rs +++ b/crates/precompile/src/bls12_381/g1_add.rs @@ -1,10 +1,9 @@ //! BLS12-381 G1 add precompile. More details in [`g1_add`] -use super::crypto_backend::p1_add_affine_bytes; 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::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_ADD_ADDRESS, g1_add); @@ -14,7 +13,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_ADD_ADDRE /// Output is an encoding of addition operation result - single G1 point (`128` /// bytes). /// See also: -pub fn g1_add(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn g1_add(input: &[u8], gas_limit: u64) -> PrecompileResult { if G1_ADD_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -33,8 +32,7 @@ pub fn g1_add(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Prec let a = (*a_x, *a_y); let b = (*b_x, *b_y); - // Get unpadded result from crypto backend - let unpadded_result = p1_add_affine_bytes(a, b)?; + let unpadded_result = crypto().bls12_381_g1_add(a, b)?; // Pad the result for EVM compatibility let padded_result = pad_g1_point(&unpadded_result); diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index d6aea05020..493616594e 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -1,13 +1,12 @@ //! BLS12-381 G1 msm precompile. More details in [`g1_msm`] -use super::crypto_backend::p1_msm_bytes; -use super::G1Point; 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::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1MSM precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_MSM_ADDRESS, g1_msm); @@ -20,7 +19,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_MSM_ADDRE /// Output is an encoding of multi-scalar-multiplication operation result - single G1 /// point (`128` bytes). /// See also: -pub fn g1_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn g1_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || !input_len.is_multiple_of(G1_MSM_INPUT_LENGTH) { return Err(PrecompileError::Other(format!( @@ -34,7 +33,7 @@ pub fn g1_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Prec return Err(PrecompileError::OutOfGas); } - let valid_pairs_iter = (0..k).map(|i| { + let mut valid_pairs_iter = (0..k).map(|i| { let start = i * G1_MSM_INPUT_LENGTH; let padded_g1 = &input[start..start + PADDED_G1_LENGTH]; let scalar_bytes = &input[start + PADDED_G1_LENGTH..start + G1_MSM_INPUT_LENGTH]; @@ -47,7 +46,7 @@ pub fn g1_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Prec Ok((point, scalar_array)) }); - let unpadded_result = p1_msm_bytes(valid_pairs_iter)?; + let unpadded_result = crypto().bls12_381_g1_msm(&mut valid_pairs_iter)?; // Pad the result for EVM compatibility let padded_result = pad_g1_point(&unpadded_result); @@ -63,7 +62,7 @@ mod test { #[test] fn bls_g1multiexp_g1_not_on_curve_but_in_subgroup() { let input = Bytes::from(hex!("000000000000000000000000000000000a2833e497b38ee3ca5c62828bf4887a9f940c9e426c7890a759c20f248c23a7210d2432f4c98a514e524b5184a0ddac00000000000000000000000000000000150772d56bf9509469f9ebcd6e47570429fd31b0e262b66d512e245c38ec37255529f2271fd70066473e393a8bead0c30000000000000000000000000000000000000000000000000000000000000000")); - let fail = g1_msm(&input, G1_MSM_BASE_GAS_FEE, &crate::DefaultCrypto); + let fail = g1_msm(&input, G1_MSM_BASE_GAS_FEE); assert_eq!( fail, Err(PrecompileError::Other( diff --git a/crates/precompile/src/bls12_381/g2_add.rs b/crates/precompile/src/bls12_381/g2_add.rs index 9694282508..2d3d1265c8 100644 --- a/crates/precompile/src/bls12_381/g2_add.rs +++ b/crates/precompile/src/bls12_381/g2_add.rs @@ -1,10 +1,9 @@ //! BLS12-381 G2 add precompile. More details in [`g2_add`] -use super::crypto_backend::p2_add_affine_bytes; 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::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2ADD precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_ADD_ADDRESS, g2_add); @@ -15,7 +14,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_ADD_ADDRE /// Output is an encoding of addition operation result - single G2 point (`256` /// bytes). /// See also -pub fn g2_add(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn g2_add(input: &[u8], gas_limit: u64) -> PrecompileResult { if G2_ADD_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -34,8 +33,7 @@ pub fn g2_add(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Prec let a = (*a_x_0, *a_x_1, *a_y_0, *a_y_1); let b = (*b_x_0, *b_x_1, *b_y_0, *b_y_1); - // Get unpadded result from crypto backend - let unpadded_result = p2_add_affine_bytes(a, b)?; + let unpadded_result = crypto().bls12_381_g2_add(a, b)?; // Pad the result for EVM compatibility let padded_result = pad_g2_point(&unpadded_result); diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index f6322d5ff3..6d2830ee6a 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -1,13 +1,11 @@ //! BLS12-381 G2 msm precompile. More details in [`g2_msm`] -use super::crypto_backend::p2_msm_bytes; use super::utils::{pad_g2_point, remove_g2_padding}; -use super::G2Point; 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::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2MSM precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_MSM_ADDRESS, g2_msm); @@ -20,7 +18,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_MSM_ADDRE /// Output is an encoding of multi-scalar-multiplication operation result - single G2 /// point (`256` bytes). /// See also: -pub fn g2_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn g2_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || !input_len.is_multiple_of(G2_MSM_INPUT_LENGTH) { return Err(PrecompileError::Other(format!( @@ -34,7 +32,7 @@ pub fn g2_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Prec return Err(PrecompileError::OutOfGas); } - let valid_pairs_iter = (0..k).map(|i| { + let mut valid_pairs_iter = (0..k).map(|i| { let start = i * G2_MSM_INPUT_LENGTH; let padded_g2 = &input[start..start + PADDED_G2_LENGTH]; let scalar_bytes = &input[start + PADDED_G2_LENGTH..start + G2_MSM_INPUT_LENGTH]; @@ -43,11 +41,10 @@ pub fn g2_msm(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Prec let [x_0, x_1, y_0, y_1] = remove_g2_padding(padded_g2)?; let scalar_array: [u8; SCALAR_LENGTH] = scalar_bytes.try_into().unwrap(); - let point: G2Point = (*x_0, *x_1, *y_0, *y_1); - Ok((point, scalar_array)) + Ok(((*x_0, *x_1, *y_0, *y_1), scalar_array)) }); - let unpadded_result = p2_msm_bytes(valid_pairs_iter)?; + let unpadded_result = crypto().bls12_381_g2_msm(&mut valid_pairs_iter)?; // Pad the result for EVM compatibility let padded_result = pad_g2_point(&unpadded_result); 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 d5812b7a89..a0c0a928dd 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -1,12 +1,9 @@ //! BLS12-381 map fp2 to g2 precompile. More details in [`map_fp2_to_g2`] -use super::{ - crypto_backend::map_fp2_to_g2_bytes, - utils::{pad_g2_point, remove_fp_padding}, -}; +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::PrecompileWithAddress; +use crate::{crypto, PrecompileWithAddress}; use crate::{PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP2_TO_G2 precompile. @@ -17,11 +14,7 @@ pub const PRECOMPILE: PrecompileWithAddress = /// an element of Fp2. Output of this call is 256 bytes and is an encoded G2 /// point. /// See also: -pub fn map_fp2_to_g2( - input: &[u8], - gas_limit: u64, - _crypto: &dyn crate::Crypto, -) -> PrecompileResult { +pub fn map_fp2_to_g2(input: &[u8], gas_limit: u64) -> PrecompileResult { if MAP_FP2_TO_G2_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -36,8 +29,7 @@ pub fn map_fp2_to_g2( let input_p0_x = remove_fp_padding(&input[..PADDED_FP_LENGTH])?; let input_p0_y = remove_fp_padding(&input[PADDED_FP_LENGTH..PADDED_FP2_LENGTH])?; - // Get unpadded result from crypto backend - let unpadded_result = map_fp2_to_g2_bytes(input_p0_x, input_p0_y)?; + let unpadded_result = crypto().bls12_381_fp2_to_g2((*input_p0_x, *input_p0_y))?; // Pad the result for EVM compatibility let padded_result = pad_g2_point(&unpadded_result); 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 45ab765648..b52b9cc2ce 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -1,10 +1,7 @@ //! BLS12-381 map fp to g1 precompile. More details in [`map_fp_to_g1`] -use super::{ - crypto_backend::map_fp_to_g1_bytes, - utils::{pad_g1_point, remove_fp_padding}, -}; +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::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP_TO_G1 precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -13,7 +10,7 @@ pub const PRECOMPILE: PrecompileWithAddress = /// Field-to-curve call expects 64 bytes as an input that is interpreted as an /// element of Fp. Output of this call is 128 bytes and is an encoded G1 point. /// See also: -pub fn map_fp_to_g1(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn map_fp_to_g1(input: &[u8], gas_limit: u64) -> PrecompileResult { if MAP_FP_TO_G1_BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -27,8 +24,7 @@ pub fn map_fp_to_g1(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) - let input_p0 = remove_fp_padding(input)?; - // Get unpadded result from crypto backend - let unpadded_result = map_fp_to_g1_bytes(input_p0)?; + let unpadded_result = crypto().bls12_381_fp_to_g1(input_p0)?; // Pad the result for EVM compatibility let padded_result = pad_g1_point(&unpadded_result); @@ -47,7 +43,7 @@ mod test { #[test] fn sanity_test() { let input = Bytes::from(hex!("000000000000000000000000000000006900000000000000636f6e7472616374595a603f343061cd305a03f40239f5ffff31818185c136bc2595f2aa18e08f17")); - let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE_GAS_FEE, &crate::DefaultCrypto); + let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE_GAS_FEE); assert_eq!( fail, Err(PrecompileError::Other("non-canonical fp value".to_string())) diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index d50586fdf9..1b20b8d99b 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -1,12 +1,11 @@ //! BLS12-381 pairing precompile. More details in [`pairing`] -use super::crypto_backend::pairing_check_bytes; 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 crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; use primitives::B256; use std::vec::Vec; @@ -25,7 +24,7 @@ pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(PAIRING_ADDR /// target field and 0x00 otherwise. /// /// See also: -pub fn pairing(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn pairing(input: &[u8], gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || !input_len.is_multiple_of(PAIRING_INPUT_LENGTH) { return Err(PrecompileError::Other(format!( @@ -53,7 +52,7 @@ pub fn pairing(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Pre pairs.push(((*a_x, *a_y), (*b_x_0, *b_x_1, *b_y_0, *b_y_1))); } - let result = pairing_check_bytes(&pairs)?; + let result = crypto().bls12_381_pairing_check(&pairs)?; let result = if result { 1 } else { 0 }; Ok(PrecompileOutput::new( diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index 555b96da4d..089f6b05d3 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -1,5 +1,6 @@ //! BN128 precompiles added in [`EIP-1962`](https://eips.ethereum.org/EIPS/eip-1962) use crate::{ + crypto, utilities::{bool_to_bytes32, right_pad}, Address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, }; @@ -7,11 +8,11 @@ use std::vec::Vec; cfg_if::cfg_if! { if #[cfg(feature = "bn")]{ - mod substrate; - use substrate::{g1_point_add, g1_point_mul, pairing_check}; + pub(crate) mod substrate; + pub(crate) use substrate as crypto_backend; } else { - mod arkworks; - use arkworks::{g1_point_add, g1_point_mul, pairing_check}; + pub(crate) mod arkworks; + pub(crate) use arkworks as crypto_backend; } } @@ -27,8 +28,8 @@ pub mod add { /// Bn128 add precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { - run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit, crypto) + PrecompileWithAddress(ADDRESS, |input, gas_limit| { + run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit) }); /// Bn128 add precompile with BYZANTIUM gas rules @@ -36,8 +37,8 @@ pub mod add { /// Bn128 add precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { - run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit, crypto) + PrecompileWithAddress(ADDRESS, |input, gas_limit| { + run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit) }); } @@ -53,8 +54,8 @@ pub mod mul { /// Bn128 mul precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { - run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit, crypto) + PrecompileWithAddress(ADDRESS, |input, gas_limit| { + run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit) }); /// Bn128 mul precompile with BYZANTIUM gas rules @@ -62,8 +63,8 @@ pub mod mul { /// Bn128 mul precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { - run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit, crypto) + PrecompileWithAddress(ADDRESS, |input, gas_limit| { + run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit) }); } @@ -82,13 +83,12 @@ pub mod pair { /// Bn128 pair precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { + PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_pair( input, ISTANBUL_PAIR_PER_POINT, ISTANBUL_PAIR_BASE, gas_limit, - crypto, ) }); @@ -100,13 +100,12 @@ pub mod pair { /// Bn128 pair precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit, crypto| { + PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_pair( input, BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, gas_limit, - crypto, ) }); } @@ -151,12 +150,7 @@ pub const MUL_INPUT_LEN: usize = G1_LEN + SCALAR_LEN; pub const PAIR_ELEMENT_LEN: usize = G1_LEN + G2_LEN; /// Run the Bn128 add precompile -pub fn run_add( - input: &[u8], - gas_cost: u64, - gas_limit: u64, - _crypto: &dyn crate::Crypto, -) -> PrecompileResult { +pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -165,18 +159,13 @@ pub fn run_add( let p1_bytes = &input[..G1_LEN]; let p2_bytes = &input[G1_LEN..]; - let output = g1_point_add(p1_bytes, p2_bytes)?; + let output = crypto().bn128_g1_add(p1_bytes, p2_bytes)?; Ok(PrecompileOutput::new(gas_cost, output.into())) } /// Run the Bn128 mul precompile -pub fn run_mul( - input: &[u8], - gas_cost: u64, - gas_limit: u64, - _crypto: &dyn crate::Crypto, -) -> PrecompileResult { +pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -185,7 +174,7 @@ pub fn run_mul( let point_bytes = &input[..G1_LEN]; let scalar_bytes = &input[G1_LEN..G1_LEN + SCALAR_LEN]; - let output = g1_point_mul(point_bytes, scalar_bytes)?; + let output = crypto().bn128_g1_mul(point_bytes, scalar_bytes)?; Ok(PrecompileOutput::new(gas_cost, output.into())) } @@ -196,7 +185,6 @@ pub fn run_pair( pair_per_point_cost: u64, pair_base_cost: u64, gas_limit: u64, - _crypto: &dyn crate::Crypto, ) -> PrecompileResult { let gas_used = (input.len() / PAIR_ELEMENT_LEN) as u64 * pair_per_point_cost + pair_base_cost; if gas_used > gas_limit { @@ -225,7 +213,7 @@ pub fn run_pair( points.push((encoded_g1_element, encoded_g2_element)); } - let pairing_result = pairing_check(&points)?; + let pairing_result = crypto().bn128_pairing_check(&points)?; Ok(PrecompileOutput::new( gas_used, bool_to_bytes32(pairing_result), @@ -263,7 +251,7 @@ mod tests { ) .unwrap(); - let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto).unwrap(); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); assert_eq!(outcome.bytes, expected); // Zero sum test @@ -282,7 +270,7 @@ mod tests { ) .unwrap(); - let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto).unwrap(); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); assert_eq!(outcome.bytes, expected); // Out of gas test @@ -295,7 +283,7 @@ mod tests { ) .unwrap(); - let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 499, &crate::DefaultCrypto); + let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 499); assert!(matches!(res, Err(PrecompileError::OutOfGas))); @@ -308,7 +296,7 @@ mod tests { ) .unwrap(); - let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto).unwrap(); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); assert_eq!(outcome.bytes, expected); // Point not on curve fail @@ -321,7 +309,7 @@ mod tests { ) .unwrap(); - let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500, &crate::DefaultCrypto); + let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500); assert!(matches!( res, Err(PrecompileError::Bn128AffineGFailedToCreate) @@ -344,13 +332,7 @@ mod tests { ) .unwrap(); - let outcome = run_mul( - &input, - BYZANTIUM_MUL_GAS_COST, - 40_000, - &crate::DefaultCrypto, - ) - .unwrap(); + let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); assert_eq!(outcome.bytes, expected); // Out of gas test @@ -362,12 +344,7 @@ mod tests { ) .unwrap(); - let res = run_mul( - &input, - BYZANTIUM_MUL_GAS_COST, - 39_999, - &crate::DefaultCrypto, - ); + let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 39_999); assert!(matches!(res, Err(PrecompileError::OutOfGas))); // Zero multiplication test @@ -385,13 +362,7 @@ mod tests { ) .unwrap(); - let outcome = run_mul( - &input, - BYZANTIUM_MUL_GAS_COST, - 40_000, - &crate::DefaultCrypto, - ) - .unwrap(); + let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); assert_eq!(outcome.bytes, expected); // No input test @@ -403,13 +374,7 @@ mod tests { ) .unwrap(); - let outcome = run_mul( - &input, - BYZANTIUM_MUL_GAS_COST, - 40_000, - &crate::DefaultCrypto, - ) - .unwrap(); + let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); assert_eq!(outcome.bytes, expected); // Point not on curve fail @@ -421,12 +386,7 @@ mod tests { ) .unwrap(); - let res = run_mul( - &input, - BYZANTIUM_MUL_GAS_COST, - 40_000, - &crate::DefaultCrypto, - ); + let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000); assert!(matches!( res, Err(PrecompileError::Bn128AffineGFailedToCreate) @@ -460,7 +420,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, - &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); @@ -488,7 +447,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 259_999, - &crate::DefaultCrypto, ); assert!(matches!(res, Err(PrecompileError::OutOfGas))); @@ -503,7 +461,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, - &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); @@ -525,7 +482,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, - &crate::DefaultCrypto, ); assert!(matches!( res, @@ -547,7 +503,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, - &crate::DefaultCrypto, ); assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); @@ -572,7 +527,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, - &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); @@ -595,7 +549,6 @@ mod tests { BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, - &crate::DefaultCrypto, ) .unwrap(); assert_eq!(outcome.bytes, expected); diff --git a/crates/precompile/src/bn128/arkworks.rs b/crates/precompile/src/bn128/arkworks.rs index 63a14a9946..8ab430f484 100644 --- a/crates/precompile/src/bn128/arkworks.rs +++ b/crates/precompile/src/bn128/arkworks.rs @@ -180,7 +180,7 @@ pub(super) fn read_scalar(input: &[u8]) -> Fr { /// Performs point addition on two G1 points. #[inline] -pub(super) fn g1_point_add(p1_bytes: &[u8], p2_bytes: &[u8]) -> Result<[u8; 64], PrecompileError> { +pub(crate) fn g1_point_add(p1_bytes: &[u8], p2_bytes: &[u8]) -> Result<[u8; 64], PrecompileError> { let p1 = read_g1_point(p1_bytes)?; let p2 = read_g1_point(p2_bytes)?; @@ -194,7 +194,7 @@ pub(super) fn g1_point_add(p1_bytes: &[u8], p2_bytes: &[u8]) -> Result<[u8; 64], /// Performs a G1 scalar multiplication. #[inline] -pub(super) fn g1_point_mul( +pub(crate) fn g1_point_mul( point_bytes: &[u8], fr_bytes: &[u8], ) -> Result<[u8; 64], PrecompileError> { @@ -215,7 +215,7 @@ pub(super) fn g1_point_mul( /// Note: If the input is empty, this function returns true. /// This is different to EIP2537 which disallows the empty input. #[inline] -pub(super) fn pairing_check(pairs: &[(&[u8], &[u8])]) -> Result { +pub(crate) fn pairing_check(pairs: &[(&[u8], &[u8])]) -> Result { let mut g1_points = Vec::with_capacity(pairs.len()); let mut g2_points = Vec::with_capacity(pairs.len()); diff --git a/crates/precompile/src/bn128/substrate.rs b/crates/precompile/src/bn128/substrate.rs index ee3b5c162b..c0656d54f8 100644 --- a/crates/precompile/src/bn128/substrate.rs +++ b/crates/precompile/src/bn128/substrate.rs @@ -151,7 +151,7 @@ pub(super) fn read_scalar(input: &[u8]) -> bn::Fr { /// Performs point addition on two G1 points. #[inline] -pub(super) fn g1_point_add(p1_bytes: &[u8], p2_bytes: &[u8]) -> Result<[u8; 64], PrecompileError> { +pub(crate) fn g1_point_add(p1_bytes: &[u8], p2_bytes: &[u8]) -> Result<[u8; 64], PrecompileError> { let p1 = read_g1_point(p1_bytes)?; let p2 = read_g1_point(p2_bytes)?; let result = p1 + p2; @@ -160,7 +160,7 @@ pub(super) fn g1_point_add(p1_bytes: &[u8], p2_bytes: &[u8]) -> Result<[u8; 64], /// Performs a G1 scalar multiplication. #[inline] -pub(super) fn g1_point_mul( +pub(crate) fn g1_point_mul( point_bytes: &[u8], fr_bytes: &[u8], ) -> Result<[u8; 64], PrecompileError> { @@ -176,7 +176,7 @@ pub(super) fn g1_point_mul( /// Note: If the input is empty, this function returns true. /// This is different to EIP2537 which disallows the empty input. #[inline] -pub(super) fn pairing_check(pairs: &[(&[u8], &[u8])]) -> Result { +pub(crate) fn pairing_check(pairs: &[(&[u8], &[u8])]) -> Result { let mut parsed_pairs = Vec::with_capacity(pairs.len()); for (g1_bytes, g2_bytes) in pairs { diff --git a/crates/precompile/src/hash.rs b/crates/precompile/src/hash.rs index dce89cbc3e..2c81db2ef6 100644 --- a/crates/precompile/src/hash.rs +++ b/crates/precompile/src/hash.rs @@ -1,7 +1,7 @@ //! Hash precompiles, it contains SHA-256 and RIPEMD-160 hash precompiles //! More details in [`sha256_run`] and [`ripemd160_run`] use super::calc_linear_cost_u32; -use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; /// SHA-256 precompile pub const SHA256: PrecompileWithAddress = @@ -17,12 +17,12 @@ pub const RIPEMD160: PrecompileWithAddress = /// - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) /// - [Solidity Documentation on Mathematical and Cryptographic Functions](https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions) /// - [Address 0x02](https://etherscan.io/address/0000000000000000000000000000000000000002) -pub fn sha256_run(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn sha256_run(input: &[u8], gas_limit: u64) -> PrecompileResult { let cost = calc_linear_cost_u32(input.len(), 60, 12); if cost > gas_limit { Err(PrecompileError::OutOfGas) } else { - let output = crypto.sha256(input); + let output = crypto().sha256(input); Ok(PrecompileOutput::new(cost, output.to_vec().into())) } } @@ -33,12 +33,12 @@ pub fn sha256_run(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> P /// - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) /// - [Solidity Documentation on Mathematical and Cryptographic Functions](https://docs.soliditylang.org/en/develop/units-and-global-variables.html#mathematical-and-cryptographic-functions) /// - [Address 03](https://etherscan.io/address/0000000000000000000000000000000000000003) -pub fn ripemd160_run(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn ripemd160_run(input: &[u8], gas_limit: u64) -> PrecompileResult { let gas_used = calc_linear_cost_u32(input.len(), 600, 120); if gas_used > gas_limit { Err(PrecompileError::OutOfGas) } else { - let output = crypto.ripemd160(input); + let output = crypto().ripemd160(input); Ok(PrecompileOutput::new(gas_used, output.to_vec().into())) } } diff --git a/crates/precompile/src/identity.rs b/crates/precompile/src/identity.rs index 6af4c5725d..9377bf440c 100644 --- a/crates/precompile/src/identity.rs +++ b/crates/precompile/src/identity.rs @@ -17,7 +17,7 @@ pub const IDENTITY_PER_WORD: u64 = 3; /// See: /// /// See: -pub fn identity_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn identity_run(input: &[u8], gas_limit: u64) -> PrecompileResult { let gas_used = calc_linear_cost_u32(input.len(), IDENTITY_BASE, IDENTITY_PER_WORD); if gas_used > gas_limit { return Err(PrecompileError::OutOfGas); diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index 2d0195d6bd..a5279a5e91 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -1,8 +1,28 @@ //! Interface for the precompiles. It contains the precompile result type, //! the precompile output type, and the precompile error type. use core::fmt::{self, Debug}; -use primitives::Bytes; -use std::{boxed::Box, string::String}; +use primitives::{Bytes, OnceLock}; +use std::{boxed::Box, string::String, vec::Vec}; + +use crate::bls12_381::{G1Point, G1PointScalar, G2Point, G2PointScalar}; + +/// Global crypto provider instance +static CRYPTO: OnceLock> = OnceLock::new(); + +/// Install a custom crypto provider globally. +pub fn install_crypto(crypto: C) -> bool { + if CRYPTO.get().is_some() { + return false; + } + + CRYPTO.get_or_init(|| Box::new(crypto)); + true +} + +/// Get the installed crypto provider, or the default if none is installed. +pub fn crypto() -> &'static dyn Crypto { + CRYPTO.get_or_init(|| Box::new(DefaultCrypto)).as_ref() +} /// A precompile operation result type /// @@ -48,18 +68,138 @@ impl PrecompileOutput { /// Crypto operations trait for precompiles. pub trait Crypto: Send + Sync + Debug { - /// Clone box type - fn clone_box(&self) -> Box; - /// Compute SHA-256 hash - fn sha256(&self, input: &[u8]) -> [u8; 32]; + #[inline] + fn sha256(&self, input: &[u8]) -> [u8; 32] { + use sha2::Digest; + let output = sha2::Sha256::digest(input); + output.into() + } /// Compute RIPEMD-160 hash - fn ripemd160(&self, input: &[u8]) -> [u8; 32]; + #[inline] + fn ripemd160(&self, input: &[u8]) -> [u8; 32] { + use ripemd::Digest; + let mut hasher = ripemd::Ripemd160::new(); + hasher.update(input); + + let mut output = [0u8; 32]; + hasher.finalize_into((&mut output[12..]).into()); + output + } + + /// BN128 elliptic curve addition. + #[inline] + fn bn128_g1_add(&self, p1: &[u8], p2: &[u8]) -> Result<[u8; 64], PrecompileError> { + crate::bn128::crypto_backend::g1_point_add(p1, p2) + } + + /// BN128 elliptic curve scalar multiplication. + #[inline] + fn bn128_g1_mul(&self, point: &[u8], scalar: &[u8]) -> Result<[u8; 64], PrecompileError> { + crate::bn128::crypto_backend::g1_point_mul(point, scalar) + } + + /// BN128 pairing check. + #[inline] + fn bn128_pairing_check(&self, pairs: &[(&[u8], &[u8])]) -> Result { + crate::bn128::crypto_backend::pairing_check(pairs) + } + + /// secp256k1 ECDSA signature recovery. + #[inline] + fn secp256k1_ecrecover( + &self, + sig: &[u8; 64], + recid: u8, + msg: &[u8; 32], + ) -> Result<[u8; 32], PrecompileError> { + crate::secp256k1::ecrecover_bytes(*sig, recid, *msg) + .ok_or_else(|| PrecompileError::other("ecrecover failed")) + } + + /// Modular exponentiation. + #[inline] + fn modexp(&self, base: &[u8], exp: &[u8], modulus: &[u8]) -> Result, PrecompileError> { + Ok(crate::modexp::modexp(base, exp, modulus)) + } + + /// Blake2 compression function. + #[inline] + fn blake2_compress(&self, rounds: u32, h: &mut [u64; 8], m: [u64; 16], t: [u64; 2], f: bool) { + crate::blake2::algo::compress(rounds as usize, h, m, t, f); + } + + /// secp256r1 (P-256) signature verification. + #[inline] + fn secp256r1_verify_signature(&self, msg: &[u8; 32], sig: &[u8; 64], pk: &[u8; 64]) -> bool { + crate::secp256r1::verify_signature(*msg, *sig, *pk).is_some() + } + + /// KZG point evaluation. + #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] + #[inline] + fn verify_kzg_proof( + &self, + z: &[u8; 32], + y: &[u8; 32], + commitment: &[u8; 48], + proof: &[u8; 48], + ) -> Result<(), PrecompileError> { + if !crate::kzg_point_evaluation::verify_kzg_proof(commitment, z, y, proof) { + return Err(PrecompileError::BlobVerifyKzgProofFailed); + } + + Ok(()) + } + + /// BLS12-381 G1 addition (returns 96-byte unpadded G1 point) + fn bls12_381_g1_add(&self, a: G1Point, b: G1Point) -> Result<[u8; 96], PrecompileError> { + crate::bls12_381::crypto_backend::p1_add_affine_bytes(a, b) + } + + /// BLS12-381 G1 multi-scalar multiplication (returns 96-byte unpadded G1 point) + fn bls12_381_g1_msm( + &self, + pairs: &mut dyn Iterator>, + ) -> Result<[u8; 96], PrecompileError> { + crate::bls12_381::crypto_backend::p1_msm_bytes(pairs) + } + + /// BLS12-381 G2 addition (returns 192-byte unpadded G2 point) + fn bls12_381_g2_add(&self, a: G2Point, b: G2Point) -> Result<[u8; 192], PrecompileError> { + crate::bls12_381::crypto_backend::p2_add_affine_bytes(a, b) + } + + /// BLS12-381 G2 multi-scalar multiplication (returns 192-byte unpadded G2 point) + fn bls12_381_g2_msm( + &self, + pairs: &mut dyn Iterator>, + ) -> Result<[u8; 192], PrecompileError> { + crate::bls12_381::crypto_backend::p2_msm_bytes(pairs) + } + + /// BLS12-381 pairing check. + fn bls12_381_pairing_check( + &self, + pairs: &[(G1Point, G2Point)], + ) -> Result { + crate::bls12_381::crypto_backend::pairing_check_bytes(pairs) + } + + /// BLS12-381 map field element to G1. + fn bls12_381_fp_to_g1(&self, fp: &[u8; 48]) -> Result<[u8; 96], PrecompileError> { + crate::bls12_381::crypto_backend::map_fp_to_g1_bytes(fp) + } + + /// BLS12-381 map field element to G2. + fn bls12_381_fp2_to_g2(&self, fp2: ([u8; 48], [u8; 48])) -> Result<[u8; 192], PrecompileError> { + crate::bls12_381::crypto_backend::map_fp2_to_g2_bytes(&fp2.0, &fp2.1) + } } /// Precompile function type. Takes input, gas limit, and crypto implementation and returns precompile result. -pub type PrecompileFn = fn(&[u8], u64, &dyn Crypto) -> PrecompileResult; +pub type PrecompileFn = fn(&[u8], u64) -> PrecompileResult; /// Precompile error type. #[derive(Clone, Debug, PartialEq, Eq, Hash)] @@ -138,24 +278,4 @@ impl fmt::Display for PrecompileError { #[derive(Clone, Debug)] pub struct DefaultCrypto; -impl Crypto for DefaultCrypto { - fn clone_box(&self) -> Box { - Box::new(self.clone()) - } - - fn sha256(&self, input: &[u8]) -> [u8; 32] { - use sha2::Digest; - let output = sha2::Sha256::digest(input); - output.into() - } - - fn ripemd160(&self, input: &[u8]) -> [u8; 32] { - use ripemd::Digest; - let mut hasher = ripemd::Ripemd160::new(); - hasher.update(input); - - let mut output = [0u8; 32]; - hasher.finalize_into((&mut output[12..]).into()); - output - } -} +impl Crypto for DefaultCrypto {} diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index be09a4a503..b0a656e40f 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -1,6 +1,8 @@ //! KZG point evaluation precompile added in [`EIP-4844`](https://eips.ethereum.org/EIPS/eip-4844) //! For more details check [`run`] function. -use crate::{Address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, +}; cfg_if::cfg_if! { if #[cfg(feature = "c-kzg")] { use c_kzg::{Bytes32, Bytes48}; @@ -9,7 +11,6 @@ cfg_if::cfg_if! { } } use primitives::hex_literal::hex; -use sha2::{Digest, Sha256}; /// KZG point evaluation precompile, containing address and function to run. pub const POINT_EVALUATION: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, run); @@ -37,7 +38,7 @@ pub const RETURN_VALUE: &[u8; 64] = &hex!( /// | versioned_hash | z | y | commitment | proof | /// | 32 | 32 | 32 | 48 | 48 | /// with z and y being padded 32 byte big endian values -pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn run(input: &[u8], gas_limit: u64) -> PrecompileResult { if gas_limit < GAS_COST { return Err(PrecompileError::OutOfGas); } @@ -59,9 +60,7 @@ pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Precomp let z = input[32..64].try_into().unwrap(); let y = input[64..96].try_into().unwrap(); let proof = input[144..192].try_into().unwrap(); - if !verify_kzg_proof(commitment, z, y, proof) { - return Err(PrecompileError::BlobVerifyKzgProofFailed); - } + crypto().verify_kzg_proof(z, y, commitment, proof)?; // Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values Ok(PrecompileOutput::new(GAS_COST, RETURN_VALUE.into())) @@ -70,7 +69,7 @@ pub fn run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> Precomp /// `VERSIONED_HASH_VERSION_KZG ++ sha256(commitment)[1..]` #[inline] pub fn kzg_to_versioned_hash(commitment: &[u8]) -> [u8; 32] { - let mut hash: [u8; 32] = Sha256::digest(commitment).into(); + let mut hash = crypto().sha256(commitment); hash[0] = VERSIONED_HASH_VERSION_KZG; hash } @@ -127,7 +126,8 @@ mod tests { // Test data from: https://github.com/ethereum/c-kzg-4844/blob/main/tests/verify_kzg_proof/kzg-mainnet/verify_kzg_proof_case_correct_proof_4_4/data.yaml let commitment = hex!("8f59a8d2a1a625a17f3fea0fe5eb8c896db3764f3185481bc22f91b4aaffcca25f26936857bc3a7c2539ea8ec3a952b7").to_vec(); - let mut versioned_hash = Sha256::digest(&commitment).to_vec(); + let crypto = &crate::DefaultCrypto; + let mut versioned_hash = crate::Crypto::sha256(crypto, &commitment).to_vec(); versioned_hash[0] = VERSIONED_HASH_VERSION_KZG; let z = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000").to_vec(); let y = hex!("1522a4a7f34e1ea350ae07c29c96c7e79655aa926122e95fe69fcbd932ca49e9").to_vec(); @@ -137,7 +137,7 @@ mod tests { let expected_output = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); let gas = 50000; - let output = run(&input, gas, &crate::DefaultCrypto).unwrap(); + let output = run(&input, gas).unwrap(); assert_eq!(output.gas_used, gas); assert_eq!(output.bytes[..], expected_output); } diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 8de8c7d71f..bf0389c5ea 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -58,7 +58,7 @@ use aurora_engine_modexp as _; use cfg_if::cfg_if; use core::hash::Hash; use primitives::{hardfork::SpecId, Address, HashMap, HashSet, OnceLock}; -use std::{boxed::Box, vec::Vec}; +use std::vec::Vec; /// Calculate the linear cost of a precompile. pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { @@ -66,34 +66,12 @@ pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { } /// Precompiles contain map of precompile addresses to functions and HashSet of precompile addresses. -#[derive(Debug)] +#[derive(Clone, Default, Debug)] pub struct Precompiles { /// Precompiles inner: HashMap, /// Addresses of precompile addresses: HashSet
, - /// Crypto implementation - crypto: Box, -} - -impl Clone for Precompiles { - fn clone(&self) -> Self { - Self { - inner: self.inner.clone(), - addresses: self.addresses.clone(), - crypto: self.crypto.clone_box(), - } - } -} - -impl Default for Precompiles { - fn default() -> Self { - Self { - inner: Default::default(), - addresses: Default::default(), - crypto: Box::new(DefaultCrypto), - } - } } impl Precompiles { @@ -110,26 +88,6 @@ impl Precompiles { } } - /// Creates a new Precompiles instance with a custom crypto implementation. - pub fn with_crypto(spec: PrecompileSpecId, crypto: Box) -> Self { - let base = Self::new(spec).clone(); - Self { - inner: base.inner, - addresses: base.addresses, - crypto, - } - } - - /// Returns the crypto implementation. - pub fn crypto(&self) -> &dyn Crypto { - &*self.crypto - } - - /// Sets a custom crypto implementation. - pub fn set_crypto(&mut self, crypto: Box) { - self.crypto = crypto; - } - /// Returns precompiles for Homestead spec. pub fn homestead() -> &'static Self { static INSTANCE: OnceLock = OnceLock::new(); @@ -212,7 +170,7 @@ impl Precompiles { if #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] { let precompile = kzg_point_evaluation::POINT_EVALUATION.clone(); } else { - let precompile = PrecompileWithAddress(u64_to_address(0x0A), |_,_,_| Err(PrecompileError::Fatal("c-kzg feature is not enabled".into()))); + let precompile = PrecompileWithAddress(u64_to_address(0x0A), |_,_| Err(PrecompileError::Fatal("c-kzg feature is not enabled".into()))); } } @@ -319,11 +277,7 @@ impl Precompiles { let addresses = inner.keys().cloned().collect::>(); - Self { - inner, - addresses, - crypto: self.crypto.clone_box(), - } + Self { inner, addresses } } /// Returns intersection of `self` and `other`. @@ -340,11 +294,7 @@ impl Precompiles { let addresses = inner.keys().cloned().collect::>(); - Self { - inner, - addresses, - crypto: self.crypto.clone_box(), - } + Self { inner, addresses } } } diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index 629f532635..c787de05f6 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -1,6 +1,7 @@ //! Modexp precompile added in [`EIP-198`](https://eips.ethereum.org/EIPS/eip-198) //! and reprices in berlin hardfork with [`EIP-2565`](https://eips.ethereum.org/EIPS/eip-2565). use crate::{ + crypto, utilities::{left_pad, left_pad_vec, right_pad_vec, right_pad_with_offset}, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, }; @@ -21,7 +22,7 @@ pub const OSAKA: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_add #[cfg(feature = "gmp")] /// GMP-based modular exponentiation implementation -fn modexp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec { +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); @@ -39,17 +40,13 @@ fn modexp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec { } #[cfg(not(feature = "gmp"))] -fn modexp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec { +pub(crate) fn modexp(base: &[u8], exponent: &[u8], modulus: &[u8]) -> Vec { aurora_engine_modexp::modexp(base, exponent, modulus) } /// See: /// See: -pub fn byzantium_run( - input: &[u8], - gas_limit: u64, - _crypto: &dyn crate::Crypto, -) -> PrecompileResult { +pub fn byzantium_run(input: &[u8], gas_limit: u64) -> PrecompileResult { run_inner::<_, false>(input, gas_limit, 0, |a, b, c, d| { byzantium_gas_calc(a, b, c, d) }) @@ -57,7 +54,7 @@ pub fn byzantium_run( /// See: /// Gas cost of berlin is modified from byzantium. -pub fn berlin_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn berlin_run(input: &[u8], gas_limit: u64) -> PrecompileResult { run_inner::<_, false>(input, gas_limit, 200, |a, b, c, d| { berlin_gas_calc(a, b, c, d) }) @@ -65,7 +62,7 @@ pub fn berlin_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> /// See: /// Gas cost of berlin is modified from byzantium. -pub fn osaka_run(input: &[u8], gas_limit: u64, _crypto: &dyn crate::Crypto) -> PrecompileResult { +pub fn osaka_run(input: &[u8], gas_limit: u64) -> PrecompileResult { run_inner::<_, true>(input, gas_limit, 500, |a, b, c, d| { osaka_gas_calc(a, b, c, d) }) @@ -162,7 +159,7 @@ where debug_assert_eq!(modulus.len(), mod_len); // Call the modexp. - let output = modexp(base, exponent, modulus); + let output = crypto().modexp(base, exponent, modulus)?; // Left pad the result to modulus length. bytes will always by less or equal to modulus length. Ok(PrecompileOutput::new( @@ -422,7 +419,7 @@ mod tests { fn test_byzantium_modexp_gas() { for (test, &test_gas) in TESTS.iter().zip(BYZANTIUM_GAS.iter()) { let input = hex::decode(test.input).unwrap(); - let res = byzantium_run(&input, 100_000_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000_000).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( res.gas_used, test_gas, @@ -437,7 +434,7 @@ mod tests { fn test_berlin_modexp_gas() { for (test, &test_gas) in TESTS.iter().zip(BERLIN_GAS.iter()) { let input = hex::decode(test.input).unwrap(); - let res = berlin_run(&input, 100_000_000, &crate::DefaultCrypto).unwrap(); + let res = berlin_run(&input, 100_000_000).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( res.gas_used, test_gas, @@ -452,7 +449,7 @@ mod tests { fn test_osaka_modexp_gas() { for (test, &test_gas) in TESTS.iter().zip(OSAKA_GAS.iter()) { let input = hex::decode(test.input).unwrap(); - let res = osaka_run(&input, 100_000_000, &crate::DefaultCrypto).unwrap(); + let res = osaka_run(&input, 100_000_000).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( res.gas_used, test_gas, @@ -465,7 +462,7 @@ mod tests { #[test] fn test_berlin_modexp_empty_input() { - let res = berlin_run(&Bytes::new(), 100_000, &crate::DefaultCrypto).unwrap(); + let res = berlin_run(&Bytes::new(), 100_000).unwrap(); let expected: Vec = Vec::new(); assert_eq!(res.bytes, expected) } @@ -530,7 +527,7 @@ mod tests { ]; for test in test_inputs { let input = test.input(); - let res = osaka_run(&input, 100_000_000, &crate::DefaultCrypto).err(); + let res = osaka_run(&input, 100_000_000).err(); if res != test.expected { panic!("test failed: {test:?} result: {res:?}"); } @@ -549,7 +546,7 @@ mod tests { 07", ) .unwrap(); - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); assert_eq!(res.bytes, vec![0x00], "0^5 mod 7 should be 0"); // Test case 2: Base equals modulus @@ -562,7 +559,7 @@ mod tests { 07", ) .unwrap(); - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); assert_eq!(res.bytes, vec![0x00], "7^3 mod 7 should be 0"); // Test case 3: Exponent is zero (result should always be 1) @@ -574,7 +571,7 @@ mod tests { 07", ) .unwrap(); - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); assert_eq!(res.bytes, vec![0x01], "5^0 mod 7 should be 1"); // Test case 4: Large base with small modulus @@ -588,7 +585,7 @@ mod tests { 03", ) .unwrap(); - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); // (2^256 - 1) = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff // This is divisible by 3, so (2^256 - 1) mod 3 = 0 // Therefore 0^2 mod 3 = 0 @@ -603,14 +600,14 @@ mod tests { fn test_modexp_gas_edge_cases() { // Test minimum gas consumption with empty input // Byzantium has min_gas of 0 for empty input - let res = byzantium_run(&[], 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&[], 100_000).unwrap(); assert_eq!( res.gas_used, 0, "Empty input should use 0 gas for Byzantium" ); // Berlin has min_gas of 200 - let res = berlin_run(&[], 100_000, &crate::DefaultCrypto).unwrap(); + let res = berlin_run(&[], 100_000).unwrap(); assert_eq!( res.gas_used, 200, "Empty input should use minimum gas 200 for Berlin" @@ -627,11 +624,11 @@ mod tests { ) .unwrap(); // For Byzantium, check that it computes correctly - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); assert_eq!(res.bytes, vec![0x00], "1^1 mod 1 = 0"); // For Berlin, minimum gas is 200 - let res = berlin_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = berlin_run(&input, 100_000).unwrap(); assert_eq!(res.gas_used, 200, "Berlin should use minimum gas of 200"); } @@ -647,7 +644,7 @@ mod tests { 0000000000000000000000000000000000000000000000000000000000000101", ) .unwrap(); - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); assert_eq!( res.bytes.len(), 32, @@ -669,8 +666,8 @@ mod tests { ) .unwrap(); - let byzantium_res = byzantium_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); - let berlin_res = berlin_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); + let byzantium_res = byzantium_run(&input, 10_000_000).unwrap(); + let berlin_res = berlin_run(&input, 10_000_000).unwrap(); assert!( berlin_res.gas_used < byzantium_res.gas_used, @@ -698,7 +695,7 @@ mod tests { .unwrap(); // Should succeed with exactly 1024 bytes - let res = osaka_run(&input, 100_000_000, &crate::DefaultCrypto); + let res = osaka_run(&input, 100_000_000); assert!(res.is_ok(), "1024-byte base should be allowed"); // Test with 1025 bytes - should fail @@ -712,7 +709,7 @@ mod tests { ) .unwrap(); - let res = osaka_run(&input_fail, 100_000_000, &crate::DefaultCrypto); + let res = osaka_run(&input_fail, 100_000_000); assert!( matches!(res, Err(PrecompileError::ModexpEip7823LimitSize)), "1025-byte base should be rejected" @@ -730,7 +727,7 @@ mod tests { ) .unwrap(); - let res = byzantium_run(&input, 100_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 100_000).unwrap(); // Should pad with zeros and compute ff00^ff00 mod ff00 assert!(res.bytes.len() == 2, "Result should be 2 bytes"); } @@ -748,7 +745,7 @@ mod tests { ) .unwrap(); - let res = byzantium_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); + let res = byzantium_run(&input, 10_000_000).unwrap(); assert_eq!(res.bytes.len(), 32, "Result should be 32 bytes"); // (2^256 - 1)^1 mod (2^256 - 2) = 1 assert_eq!(res.bytes[31], 1, "Max value mod (max-1) should be 1"); @@ -777,9 +774,9 @@ mod tests { for test_input in test_cases { let input = hex::decode(test_input).unwrap(); - let byzantium_res = byzantium_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); - let berlin_res = berlin_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); - let osaka_res = osaka_run(&input, 10_000_000, &crate::DefaultCrypto).unwrap(); + let byzantium_res = byzantium_run(&input, 10_000_000).unwrap(); + let berlin_res = berlin_run(&input, 10_000_000).unwrap(); + let osaka_res = osaka_run(&input, 10_000_000).unwrap(); assert_eq!( byzantium_res.bytes, berlin_res.bytes, @@ -803,7 +800,7 @@ mod tests { .unwrap(); // Provide insufficient gas - let res = byzantium_run(&input, 1000, &crate::DefaultCrypto); + let res = byzantium_run(&input, 1000); assert!( matches!(res, Err(PrecompileError::OutOfGas)), "Should return OutOfGas error with insufficient gas" diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 374f0d4792..5d412f649a 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -20,7 +20,7 @@ pub mod k256; pub mod parity_libsecp256k1; use crate::{ - utilities::right_pad, PrecompileError, PrecompileOutput, PrecompileResult, + crypto, utilities::right_pad, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, }; use primitives::{alloy_primitives::B512, Bytes, B256}; @@ -30,11 +30,7 @@ pub const ECRECOVER: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_address(1), ec_recover_run); /// `ecrecover` precompile function. Read more about input and output format in [this module docs](self). -pub fn ec_recover_run( - input: &[u8], - gas_limit: u64, - _crypto: &dyn crate::Crypto, -) -> PrecompileResult { +pub fn ec_recover_run(input: &[u8], gas_limit: u64) -> PrecompileResult { const ECRECOVER_BASE: u64 = 3_000; if ECRECOVER_BASE > gas_limit { @@ -52,12 +48,12 @@ pub fn ec_recover_run( let recid = input[63] - 27; let sig = <&B512>::try_from(&input[64..128]).unwrap(); - let res = ecrecover_bytes(sig.0, recid, msg.0); + let res = crypto().secp256k1_ecrecover(&sig.0, recid, &msg.0).ok(); let out = res.map(|o| o.to_vec().into()).unwrap_or_default(); Ok(PrecompileOutput::new(ECRECOVER_BASE, out)) } -fn ecrecover_bytes(sig: [u8; 64], recid: u8, msg: [u8; 32]) -> Option<[u8; 32]> { +pub(crate) fn ecrecover_bytes(sig: [u8; 64], recid: u8, msg: [u8; 32]) -> Option<[u8; 32]> { let sig = B512::from_slice(&sig); let msg = B256::from_slice(&msg); diff --git a/crates/precompile/src/secp256r1.rs b/crates/precompile/src/secp256r1.rs index 8e70cd5a50..b421a623e6 100644 --- a/crates/precompile/src/secp256r1.rs +++ b/crates/precompile/src/secp256r1.rs @@ -7,7 +7,8 @@ //! P256 elliptic curve. The [`P256VERIFY`] const represents the implementation of this precompile, //! with the address that it is currently deployed at. use crate::{ - u64_to_address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, + crypto, u64_to_address, PrecompileError, PrecompileOutput, PrecompileResult, + PrecompileWithAddress, }; use p256::{ ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey}, @@ -46,8 +47,8 @@ pub const P256VERIFY_OSAKA: PrecompileWithAddress = /// | signed message hash | r | s | public key x | public key y | /// | :-----------------: | :-: | :-: | :----------: | :----------: | /// | 32 | 32 | 32 | 32 | 32 | -pub fn p256_verify(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> PrecompileResult { - p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE, crypto) +pub fn p256_verify(input: &[u8], gas_limit: u64) -> PrecompileResult { + p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE) } /// secp256r1 precompile logic with Osaka gas cost. It takes the input bytes sent to the precompile @@ -59,24 +60,15 @@ pub fn p256_verify(input: &[u8], gas_limit: u64, crypto: &dyn crate::Crypto) -> /// | signed message hash | r | s | public key x | public key y | /// | :-----------------: | :-: | :-: | :----------: | :----------: | /// | 32 | 32 | 32 | 32 | 32 | -pub fn p256_verify_osaka( - input: &[u8], - gas_limit: u64, - crypto: &dyn crate::Crypto, -) -> PrecompileResult { - p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE_OSAKA, crypto) +pub fn p256_verify_osaka(input: &[u8], gas_limit: u64) -> PrecompileResult { + p256_verify_inner(input, gas_limit, P256VERIFY_BASE_GAS_FEE_OSAKA) } -fn p256_verify_inner( - input: &[u8], - gas_limit: u64, - gas_cost: u64, - crypto: &dyn crate::Crypto, -) -> PrecompileResult { +fn p256_verify_inner(input: &[u8], gas_limit: u64, gas_cost: u64) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); } - let result = if verify_impl(input, crypto).is_some() { + let result = if verify_impl(input) { B256::with_last_byte(1).into() } else { Bytes::new() @@ -86,9 +78,9 @@ fn p256_verify_inner( /// Returns `Some(())` if the signature included in the input byte slice is /// valid, `None` otherwise. -pub fn verify_impl(input: &[u8], _crypto: &dyn crate::Crypto) -> Option<()> { +pub fn verify_impl(input: &[u8]) -> bool { if input.len() != 160 { - return None; + return false; } // msg signed (msg is already the hash of the original message) @@ -98,10 +90,10 @@ pub fn verify_impl(input: &[u8], _crypto: &dyn crate::Crypto) -> Option<()> { // x, y: public key let pk = <&B512>::try_from(&input[96..160]).unwrap(); - verify_signature(msg.0, sig.0, pk.0) + crypto().secp256r1_verify_signature(&msg.0, &sig.0, &pk.0) } -fn verify_signature(msg: [u8; 32], sig: [u8; 64], pk: [u8; 64]) -> Option<()> { +pub(crate) fn verify_signature(msg: [u8; 32], sig: [u8; 64], pk: [u8; 64]) -> Option<()> { // Can fail only if the input is not exact length. let signature = Signature::from_slice(&sig).ok()?; // Decode the public key bytes (x,y coordinates) using EncodedPoint @@ -139,7 +131,7 @@ mod test { fn test_sig_verify(#[case] input: &str, #[case] expect_success: bool) { let input = Bytes::from_hex(input).unwrap(); let target_gas = 3_500u64; - let outcome = p256_verify(&input, target_gas, &crate::DefaultCrypto).unwrap(); + let outcome = p256_verify(&input, target_gas).unwrap(); assert_eq!(outcome.gas_used, 3_450u64); let expected_result = if expect_success { B256::with_last_byte(1).into() @@ -153,7 +145,7 @@ mod test { fn test_not_enough_gas_errors() { let input = Bytes::from_hex("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e").unwrap(); let target_gas = 2_500u64; - let result = p256_verify(&input, target_gas, &crate::DefaultCrypto); + let result = p256_verify(&input, target_gas); assert!(result.is_err()); assert_eq!(result.err(), Some(PrecompileError::OutOfGas)); @@ -164,8 +156,8 @@ mod test { #[case::fail_1("b5a77e7a90aa14e0bf5f337f06f597148676424fae26e175c6e5621c34351955289f319789da424845c9eac935245fcddd805950e2f02506d09be7e411199556d262144475b1fa46ad85250728c600c53dfd10f8b3f4adf140e27241aec3c2daaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaef8afe82d200a5bb36b5462166e8ce77f2d831a52ef2135b2af188110beaefb1", false)] fn test_verify_impl(#[case] input: &str, #[case] expect_success: bool) { let input = Bytes::from_hex(input).unwrap(); - let result = verify_impl(&input, &crate::DefaultCrypto); + let result = verify_impl(&input); - assert_eq!(result.is_some(), expect_success); + assert_eq!(result, expect_success); } } diff --git a/crates/primitives/src/once_lock.rs b/crates/primitives/src/once_lock.rs index fd863846bc..90d129ea6a 100644 --- a/crates/primitives/src/once_lock.rs +++ b/crates/primitives/src/once_lock.rs @@ -19,6 +19,7 @@ mod no_std_impl { impl OnceLock { /// Creates a new empty OnceLock. + #[inline] pub const fn new() -> Self { Self { inner: OnceBox::new(), @@ -26,6 +27,7 @@ mod no_std_impl { } /// Gets the contents of the OnceLock, initializing it if necessary. + #[inline] pub fn get_or_init(&self, f: F) -> &T where F: FnOnce() -> T, @@ -33,6 +35,12 @@ mod no_std_impl { { self.inner.get_or_init(|| f().into()) } + + /// Gets the contents of the OnceLock, returning None if it is not initialized. + #[inline] + pub fn get(&self) -> Option<&T> { + self.inner.get() + } } } diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 091f6807e7..6f4df789fc 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -36,3 +36,4 @@ pub use handler::{ SystemCallEvm, }; pub use inspector::{InspectCommitEvm, InspectEvm, Inspector}; +pub use precompile::install_crypto; From ccdbcc05d14ec02a2dd616015b8e918c1950a746 Mon Sep 17 00:00:00 2001 From: Quentin Sabah Date: Fri, 25 Jul 2025 11:57:53 +0200 Subject: [PATCH 12/78] docs: fix typos (#2800) --- crates/interpreter/src/instructions/macros.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 5af7001c27..300a7bfdac 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -86,7 +86,7 @@ macro_rules! gas_or_fail { }; } -/// Resizes the interpreterreter memory if necessary. Fails the instruction if the memory or gas limit +/// Resizes the interpreter memory if necessary. Fails the instruction if the memory or gas limit /// is exceeded. #[macro_export] #[collapse_debuginfo(yes)] @@ -111,9 +111,9 @@ macro_rules! resize_memory { #[macro_export] #[collapse_debuginfo(yes)] macro_rules! popn { - ([ $($x:ident),* ],$interpreterreter:expr $(,$ret:expr)? ) => { - let Some([$( $x ),*]) = $interpreterreter.stack.popn() else { - $interpreterreter.halt($crate::InstructionResult::StackUnderflow); + ([ $($x:ident),* ],$interpreter:expr $(,$ret:expr)? ) => { + let Some([$( $x ),*]) = $interpreter.stack.popn() else { + $interpreter.halt($crate::InstructionResult::StackUnderflow); return $($ret)?; }; }; From 6c6676aaeee521fbf89dbeb30a00d05ec4c37a23 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 25 Jul 2025 12:44:28 +0200 Subject: [PATCH 13/78] fix: nonce changed is not reverted in journal if fail due to insufficient balance (#2805) --- crates/handler/src/pre_execution.rs | 12 ++++++------ crates/op-revm/src/handler.rs | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index c1a9aa3816..7a7debca4b 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -138,12 +138,6 @@ pub fn validate_against_state_and_deduct_caller< is_nonce_check_disabled, )?; - // Bump the nonce for calls. Nonce for CREATE will be bumped in `make_create_frame`. - if tx.kind().is_call() { - // Nonce is already checked - caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); - } - let max_balance_spending = tx.max_balance_spending()?; // Check if account has enough balance for `gas_limit * max_fee`` and value transfer. @@ -178,6 +172,12 @@ pub fn validate_against_state_and_deduct_caller< caller_account.mark_touch(); caller_account.info.balance = new_balance; + // Bump the nonce for calls. Nonce for CREATE will be bumped in `make_create_frame`. + if tx.kind().is_call() { + // Nonce is already checked + caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); + } + journal.caller_accounting_journal_entry(tx.caller(), old_balance, tx.kind().is_call()); Ok(()) } diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index e696aba055..4d4a6d00ec 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -157,11 +157,6 @@ where )?; } - // Bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. - if tx.kind().is_call() { - caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); - } - let max_balance_spending = tx.max_balance_spending()?.saturating_add(additional_cost); // old balance is journaled before mint is incremented. @@ -210,6 +205,11 @@ where caller_account.mark_touch(); caller_account.info.balance = new_balance; + // Bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. + if tx.kind().is_call() { + caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); + } + // 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()); From 560d728d443609562e61cde47a585ab8fa62395d Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:05:17 +0200 Subject: [PATCH 14/78] chore: start InstructionResult at 1 (#2802) Makes `Result<(), InstructionResult>::Ok(())` equal 0. 0 as a value is cheaper on certain architectures to return from a function and/or to branch off of (e.g. `if is_ok() { ... }`). --- crates/interpreter/src/instruction_result.rs | 28 +++++++++----------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index a5c7485c55..e1c76d7546 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -4,16 +4,17 @@ use context_interface::{ }; use core::fmt::Debug; -#[repr(u8)] -#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] /// Result of executing an EVM instruction. +/// /// This enum represents all possible outcomes when executing an instruction, /// including successful execution, reverts, and various error conditions. +#[repr(u8)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum InstructionResult { /// Encountered a `STOP` opcode #[default] - Stop, + Stop = 1, // Start at 1 so that `Result<(), _>::Ok(())` is 0. /// Return from the current call. Return, /// Self-destruct the current contract. @@ -35,7 +36,7 @@ pub enum InstructionResult { // Error Codes /// Out of gas error. - OutOfGas = 0x50, + OutOfGas = 0x20, /// Out of gas error encountered during memory expansion. MemoryOOG, /// The memory limit of the EVM has been exceeded. @@ -195,19 +196,19 @@ impl InstructionResult { /// Returns whether the result is a success. #[inline] pub const fn is_ok(self) -> bool { - matches!(self, crate::return_ok!()) + matches!(self, return_ok!()) } #[inline] /// Returns whether the result is a success or revert (not an error). pub const fn is_ok_or_revert(self) -> bool { - matches!(self, crate::return_ok!() | crate::return_revert!()) + matches!(self, return_ok!() | return_revert!()) } /// Returns whether the result is a revert. #[inline] pub const fn is_revert(self) -> bool { - matches!(self, crate::return_revert!()) + matches!(self, return_revert!()) } /// Returns whether the result is an error. @@ -353,7 +354,7 @@ mod tests { use crate::InstructionResult; #[test] - fn all_results_are_covered() { + fn exhaustiveness() { match InstructionResult::Stop { return_error!() => {} return_revert!() => {} @@ -363,31 +364,29 @@ mod tests { #[test] fn test_results() { - let ok_results = vec![ + let ok_results = [ InstructionResult::Stop, InstructionResult::Return, InstructionResult::SelfDestruct, ]; - for result in ok_results { assert!(result.is_ok()); assert!(!result.is_revert()); assert!(!result.is_error()); } - let revert_results = vec![ + let revert_results = [ InstructionResult::Revert, InstructionResult::CallTooDeep, InstructionResult::OutOfFunds, ]; - for result in revert_results { assert!(!result.is_ok()); assert!(result.is_revert()); assert!(!result.is_error()); } - let error_results = vec![ + let error_results = [ InstructionResult::OutOfGas, InstructionResult::MemoryOOG, InstructionResult::MemoryLimitOOG, @@ -411,7 +410,6 @@ mod tests { InstructionResult::CreateInitCodeSizeLimit, InstructionResult::FatalExternalError, ]; - for result in error_results { assert!(!result.is_ok()); assert!(!result.is_revert()); From 1477307e9ba3bb7dfb5403475ea226410bbf5354 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:05:57 +0200 Subject: [PATCH 15/78] chore: fix run-tests.sh (#2801) --- crates/handler/src/validation.rs | 34 +++++++++++++++++++------------- scripts/run-tests.sh | 6 +++--- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index 73fccedcf8..52cb0fbb3d 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -389,13 +389,16 @@ mod tests { ]; let bytecode: Bytes = init_code.into(); let result = deploy_contract(bytecode, Some(SpecId::OSAKA)); - assert!(matches!( - result, - Ok(ExecutionResult::Halt { - reason: HaltReason::CreateContractSizeLimit, - .. - },) - )); + assert!( + matches!( + result, + Ok(ExecutionResult::Halt { + reason: HaltReason::CreateContractSizeLimit, + .. + },) + ), + "{result:?}" + ); } #[test] @@ -411,13 +414,16 @@ mod tests { ]; let bytecode: Bytes = init_code.into(); let result = deploy_contract(bytecode, Some(SpecId::PRAGUE)); - assert!(matches!( - result, - Ok(ExecutionResult::Halt { - reason: HaltReason::CreateContractSizeLimit, - .. - },) - )); + assert!( + matches!( + result, + Ok(ExecutionResult::Halt { + reason: HaltReason::CreateContractSizeLimit, + .. + },) + ), + "{result:?}" + ); } #[test] diff --git a/scripts/run-tests.sh b/scripts/run-tests.sh index 5826df605b..0f813f9b8b 100755 --- a/scripts/run-tests.sh +++ b/scripts/run-tests.sh @@ -1,7 +1,7 @@ -# ./run-tests --help +#!/usr/bin/env bash +set -eo pipefail -#!/bin/bash -set -e +# Usage: ./scripts/run-tests.sh --help # Version for the execution spec tests VERSION="v4.4.0" From 6a736b39e039200dbb6f254aa641875235b37e32 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 25 Jul 2025 15:12:41 +0200 Subject: [PATCH 16/78] chore: fix inspector, cleanup loop (#2797) --- crates/inspector/src/handler.rs | 26 +++------- crates/inspector/src/lib.rs | 47 +++++++++++++++++++ crates/interpreter/src/interpreter.rs | 23 ++------- .../src/interpreter/ext_bytecode.rs | 22 ++++----- crates/interpreter/src/interpreter_types.rs | 10 ++-- 5 files changed, 68 insertions(+), 60 deletions(-) diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index 43c7979770..10b07570ac 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -4,8 +4,8 @@ use handler::{evm::FrameTr, EvmTr, FrameResult, Handler, ItemOrResult}; use interpreter::{ instructions::InstructionTable, interpreter_types::{Jumps, LoopControl}, - FrameInput, Host, InitialAndFloorGas, InstructionContext, InstructionResult, Interpreter, - InterpreterAction, InterpreterTypes, + FrameInput, Host, InitialAndFloorGas, InstructionResult, Interpreter, InterpreterAction, + InterpreterTypes, }; use state::bytecode::opcode; @@ -185,32 +185,20 @@ where { loop { inspector.step(interpreter, context); + if interpreter.bytecode.is_end() { + break; + } - // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last - // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction - // it will do noop and just stop execution of this contract let opcode = interpreter.bytecode.opcode(); - interpreter.bytecode.relative_jump(1); - - // Execute instruction. - let instruction_context = InstructionContext { - interpreter, - host: context, - }; - instructions[opcode as usize](instruction_context); + interpreter.step(instructions, context); if (opcode::LOG0..=opcode::LOG4).contains(&opcode) { inspect_log(interpreter, context, &mut inspector); } - let done = interpreter.bytecode.is_end(); - if done { - interpreter.bytecode.revert_to_previous_pointer(); - } - inspector.step_end(interpreter, context); - if done { + if interpreter.bytecode.is_end() { break; } } diff --git a/crates/inspector/src/lib.rs b/crates/inspector/src/lib.rs index 3c7f331b2b..26998967f6 100644 --- a/crates/inspector/src/lib.rs +++ b/crates/inspector/src/lib.rs @@ -34,3 +34,50 @@ pub use inspect::{InspectCommitEvm, InspectEvm}; pub use inspector::*; pub use noop::NoOpInspector; pub use traits::*; + +#[cfg(test)] +mod tests { + use super::*; + use ::handler::{MainBuilder, MainContext}; + use context::{BlockEnv, CfgEnv, Context, Journal, TxEnv}; + use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; + use interpreter::{interpreter::EthInterpreter, InstructionResult, InterpreterTypes}; + use primitives::TxKind; + use state::{bytecode::opcode, Bytecode}; + + struct HaltInspector; + impl Inspector for HaltInspector { + fn step(&mut self, interp: &mut interpreter::Interpreter, _context: &mut CTX) { + interp.halt(InstructionResult::Stop); + } + } + + #[test] + fn test_step_halt() { + let bytecode = [opcode::INVALID]; + let r = run(&bytecode, HaltInspector); + dbg!(&r); + assert!(r.is_success()); + } + + fn run( + bytecode: &[u8], + inspector: impl Inspector< + Context, ()>, + EthInterpreter, + >, + ) -> context::result::ExecutionResult { + let bytecode = Bytecode::new_raw(bytecode.to_vec().into()); + let ctx = Context::mainnet().with_db(BenchmarkDB::new_bytecode(bytecode)); + let mut evm = ctx.build_mainnet_with_inspector(inspector); + evm.inspect_one_tx( + TxEnv::builder() + .caller(BENCH_CALLER) + .kind(TxKind::Call(BENCH_TARGET)) + .gas_limit(21100) + .build() + .unwrap(), + ) + .unwrap() + } +} diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index db0ae972f2..fffb852393 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -193,6 +193,7 @@ impl Interpreter { /// Takes the next action from the control and returns it. #[inline] pub fn take_next_action(&mut self) -> InterpreterAction { + self.bytecode.reset_action(); // Return next action if it is some. core::mem::take(self.bytecode.action()).expect("Interpreter to set action") } @@ -237,11 +238,7 @@ impl Interpreter { /// This uses dummy Host. #[inline] pub fn step_dummy(&mut self, instruction_table: &InstructionTable) { - let context = InstructionContext { - interpreter: self, - host: &mut DummyHost, - }; - context.step(instruction_table); + self.step(instruction_table, &mut DummyHost); } /// Executes the interpreter until it returns or stops. @@ -252,22 +249,8 @@ impl Interpreter { host: &mut H, ) -> InterpreterAction { while self.bytecode.is_not_end() { - // Get current opcode. - let opcode = self.bytecode.opcode(); - - // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last - // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction - // it will do noop and just stop execution of this contract - self.bytecode.relative_jump(1); - let context = InstructionContext { - interpreter: self, - host, - }; - // Execute instruction. - instruction_table[opcode as usize](context); + self.step(instruction_table, host); } - self.bytecode.revert_to_previous_pointer(); - self.take_next_action() } } diff --git a/crates/interpreter/src/interpreter/ext_bytecode.rs b/crates/interpreter/src/interpreter/ext_bytecode.rs index ede6bfcb02..2a0be8f1f9 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode.rs @@ -1,7 +1,7 @@ use super::{Immediates, Jumps, LegacyBytecode}; use crate::{interpreter_types::LoopControl, InterpreterAction}; use bytecode::{utils::read_u16, Bytecode}; -use core::{ops::Deref, ptr}; +use core::ops::Deref; use primitives::B256; #[cfg(feature = "serde")] @@ -14,10 +14,9 @@ pub struct ExtBytecode { /// Actions that the EVM should do. It contains return value of the Interpreter or inputs for `CALL` or `CREATE` instructions. /// For `RETURN` or `REVERT` instructions it contains the result of the instruction. pub action: Option, + has_set_action: bool, /// The base bytecode. base: Bytecode, - /// The previous instruction pointer. - previous_pointer: Option<*const u8>, /// The current instruction pointer. instruction_pointer: *const u8, } @@ -47,7 +46,7 @@ impl ExtBytecode { instruction_pointer, bytecode_hash: None, action: None, - previous_pointer: None, + has_set_action: false, } } @@ -59,7 +58,7 @@ impl ExtBytecode { instruction_pointer, bytecode_hash: Some(hash), action: None, - previous_pointer: None, + has_set_action: false, } } @@ -79,23 +78,18 @@ impl ExtBytecode { impl LoopControl for ExtBytecode { #[inline] fn is_end(&self) -> bool { - self.instruction_pointer.is_null() + self.has_set_action } #[inline] - fn revert_to_previous_pointer(&mut self) { - if let Some(previous_pointer) = self.previous_pointer { - self.instruction_pointer = previous_pointer; - } + fn reset_action(&mut self) { + self.has_set_action = false; } #[inline] fn set_action(&mut self, action: InterpreterAction) { + self.has_set_action = true; self.action = Some(action); - self.previous_pointer = Some(core::mem::replace( - &mut self.instruction_pointer, - ptr::null(), - )); } #[inline] diff --git a/crates/interpreter/src/interpreter_types.rs b/crates/interpreter/src/interpreter_types.rs index 2d81406892..c369e20dbc 100644 --- a/crates/interpreter/src/interpreter_types.rs +++ b/crates/interpreter/src/interpreter_types.rs @@ -254,13 +254,9 @@ pub trait LoopControl { } /// Is end of the loop. fn is_end(&self) -> bool; - /// Reverts to previous instruction pointer. - /// - /// After the loop is finished, the instruction pointer is set to the previous one. - fn revert_to_previous_pointer(&mut self); - /// Set return action and set instruction pointer to null. Preserve previous pointer - /// - /// Previous pointer can be restored by calling [`LoopControl::revert_to_previous_pointer`]. + /// Sets the `end` flag internally. Action should be taken after. + fn reset_action(&mut self); + /// Set return action. fn set_action(&mut self, action: InterpreterAction); /// Returns the current action. fn action(&mut self) -> &mut Option; From 80e09f643665f4154726bbcb2542fa5388634331 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Mon, 28 Jul 2025 10:53:53 +0200 Subject: [PATCH 17/78] fix(op-revm): system tx not enveloped (#2807) * Fix bug, system tx not enveloped and add test * Fix lint --- crates/op-revm/src/transaction/abstraction.rs | 8 +- crates/op-revm/tests/integration.rs | 17 ++ .../tests/testdata/test_system_call.json | 165 ++++++++++++++++++ 3 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 crates/op-revm/tests/testdata/test_system_call.json diff --git a/crates/op-revm/src/transaction/abstraction.rs b/crates/op-revm/src/transaction/abstraction.rs index 65b50e3ddd..2043f1ca0a 100644 --- a/crates/op-revm/src/transaction/abstraction.rs +++ b/crates/op-revm/src/transaction/abstraction.rs @@ -89,11 +89,15 @@ impl SystemCallTx for OpTransaction { system_contract_address: Address, data: Bytes, ) -> Self { - OpTransaction::new(TX::new_system_tx_with_caller( + let mut tx = OpTransaction::new(TX::new_system_tx_with_caller( caller, system_contract_address, data, - )) + )); + + tx.enveloped_tx = Some(Bytes::default()); + + tx } } diff --git a/crates/op-revm/tests/integration.rs b/crates/op-revm/tests/integration.rs index 2f7f2fcf96..cc7647b7f2 100644 --- a/crates/op-revm/tests/integration.rs +++ b/crates/op-revm/tests/integration.rs @@ -1,11 +1,13 @@ //! Integration tests for the `op-revm` crate. mod common; +use alloy_primitives::bytes; use common::compare_or_save_testdata; use op_revm::{ precompiles::bn128_pair::GRANITE_MAX_INPUT_SIZE, DefaultOp, L1BlockInfo, OpBuilder, OpHaltReason, OpSpecId, OpTransaction, }; +use revm::SystemCallEvm; use revm::{ bytecode::opcode, context::{ @@ -1072,3 +1074,18 @@ fn test_log_inspector() { compare_or_save_testdata("test_log_inspector.json", &output); } + +#[test] +fn test_system_call() { + let ctx = Context::op(); + + let mut evm = ctx.build_op(); + + evm.transact_system_call(BENCH_TARGET, bytes!("0x0001")) + .unwrap(); + + // Run evm. + let output = evm.replay().unwrap(); + + compare_or_save_testdata("test_system_call.json", &output); +} diff --git a/crates/op-revm/tests/testdata/test_system_call.json b/crates/op-revm/tests/testdata/test_system_call.json new file mode 100644 index 0000000000..c45ac37cc0 --- /dev/null +++ b/crates/op-revm/tests/testdata/test_system_call.json @@ -0,0 +1,165 @@ +{ + "result": { + "Success": { + "reason": "Stop", + "gas_used": 21020, + "gas_refunded": 0, + "logs": [], + "output": { + "Call": "0x" + } + } + }, + "state": { + "0x420000000000000000000000000000000000001b": { + "info": { + "balance": "0x0", + "nonce": 0, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "original_len": 0, + "jump_table": { + "order": "bitvec::order::Lsb0", + "head": { + "width": 8, + "index": 0 + }, + "bits": 0, + "data": [] + } + } + } + }, + "transaction_id": 1, + "storage": {}, + "status": "Touched | LoadedAsNotExisting" + }, + "0x4200000000000000000000000000000000000019": { + "info": { + "balance": "0x0", + "nonce": 0, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "original_len": 0, + "jump_table": { + "order": "bitvec::order::Lsb0", + "head": { + "width": 8, + "index": 0 + }, + "bits": 0, + "data": [] + } + } + } + }, + "transaction_id": 1, + "storage": {}, + "status": "Touched | LoadedAsNotExisting" + }, + "0xfffffffffffffffffffffffffffffffffffffffe": { + "info": { + "balance": "0x0", + "nonce": 1, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "original_len": 0, + "jump_table": { + "order": "bitvec::order::Lsb0", + "head": { + "width": 8, + "index": 0 + }, + "bits": 0, + "data": [] + } + } + } + }, + "transaction_id": 1, + "storage": {}, + "status": "Touched | LoadedAsNotExisting" + }, + "0x0000000000000000000000000000000000000000": { + "info": { + "balance": "0x0", + "nonce": 0, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "original_len": 0, + "jump_table": { + "order": "bitvec::order::Lsb0", + "head": { + "width": 8, + "index": 0 + }, + "bits": 0, + "data": [] + } + } + } + }, + "transaction_id": 1, + "storage": {}, + "status": "Touched | LoadedAsNotExisting" + }, + "0xffffffffffffffffffffffffffffffffffffffff": { + "info": { + "balance": "0x0", + "nonce": 0, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "original_len": 0, + "jump_table": { + "order": "bitvec::order::Lsb0", + "head": { + "width": 8, + "index": 0 + }, + "bits": 0, + "data": [] + } + } + } + }, + "transaction_id": 1, + "storage": {}, + "status": "Touched | LoadedAsNotExisting" + }, + "0x420000000000000000000000000000000000001a": { + "info": { + "balance": "0x0", + "nonce": 0, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "code": { + "LegacyAnalyzed": { + "bytecode": "0x00", + "original_len": 0, + "jump_table": { + "order": "bitvec::order::Lsb0", + "head": { + "width": 8, + "index": 0 + }, + "bits": 0, + "data": [] + } + } + } + }, + "transaction_id": 1, + "storage": {}, + "status": "Touched | LoadedAsNotExisting" + } + } +} \ No newline at end of file From 9bc0c04fda0891e0e8d2e2a6dfd0af81c2af18c4 Mon Sep 17 00:00:00 2001 From: Pratham Agarwal <32198580+Pratham1812@users.noreply.github.com> Date: Mon, 28 Jul 2025 16:07:00 +0530 Subject: [PATCH 18/78] feat: rename bn128 to bn254 for Ethereum standard consistency (#2810) * feat: rename bn128 to bn254 for Ethereum standard consistency * fix: renamed more occurences * fix: addresed nits --- crates/op-revm/src/precompiles.rs | 46 ++++++------ crates/op-revm/tests/integration.rs | 20 +++--- crates/precompile/bench/eip1962.rs | 20 +++--- crates/precompile/bench/main.rs | 8 +-- crates/precompile/src/{bn128.rs => bn254.rs} | 72 +++++++++---------- .../src/{bn128 => bn254}/arkworks.rs | 8 +-- .../src/{bn128 => bn254}/substrate.rs | 8 +-- crates/precompile/src/interface.rs | 36 +++++----- crates/precompile/src/lib.rs | 14 ++-- 9 files changed, 116 insertions(+), 116 deletions(-) rename crates/precompile/src/{bn128.rs => bn254.rs} (91%) rename crates/precompile/src/{bn128 => bn254}/arkworks.rs (96%) rename crates/precompile/src/{bn128 => bn254}/substrate.rs (96%) diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index d7e2c8e4e3..e4e14b9082 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -6,7 +6,7 @@ use revm::{ handler::{EthPrecompiles, PrecompileProvider}, interpreter::{InputsImpl, InterpreterResult}, precompile::{ - self, bn128, secp256r1, PrecompileError, PrecompileResult, PrecompileWithAddress, + self, bn254, secp256r1, PrecompileError, PrecompileResult, PrecompileWithAddress, Precompiles, }, primitives::{hardfork::SpecId, Address, OnceLock}, @@ -69,8 +69,8 @@ pub fn granite() -> &'static Precompiles { static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = fjord().clone(); - // Restrict bn256Pairing input size - precompiles.extend([bn128_pair::GRANITE]); + // Restrict bn254Pairing input size + precompiles.extend([bn254_pair::GRANITE]); precompiles }) } @@ -137,27 +137,27 @@ impl Default for OpPrecompiles { } } -/// Bn128 pair precompile. -pub mod bn128_pair { +/// Bn254 pair precompile. +pub mod bn254_pair { use super::*; - /// Max input size for the bn128 pair precompile. + /// Max input size for the bn254 pair precompile. pub const GRANITE_MAX_INPUT_SIZE: usize = 112687; - /// Bn128 pair precompile. + /// Bn254 pair precompile. pub const GRANITE: PrecompileWithAddress = - PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit| { + PrecompileWithAddress(bn254::pair::ADDRESS, |input, gas_limit| { run_pair(input, gas_limit) }); - /// Run the bn128 pair precompile with Optimism input limit. + /// Run the bn254 pair precompile with Optimism input limit. pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { if input.len() > GRANITE_MAX_INPUT_SIZE { - return Err(PrecompileError::Bn128PairLength); + return Err(PrecompileError::Bn254PairLength); } - bn128::run_pair( + bn254::run_pair( input, - bn128::pair::ISTANBUL_PAIR_PER_POINT, - bn128::pair::ISTANBUL_PAIR_BASE, + bn254::pair::ISTANBUL_PAIR_PER_POINT, + bn254::pair::ISTANBUL_PAIR_BASE, gas_limit, ) } @@ -234,7 +234,7 @@ mod tests { use std::vec; #[test] - fn test_bn128_pair() { + fn test_bn254_pair() { let input = hex::decode( "\ 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ @@ -254,7 +254,7 @@ mod tests { let expected = hex::decode("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(); - let outcome = bn128_pair::run_pair(&input, 260_000).unwrap(); + let outcome = bn254_pair::run_pair(&input, 260_000).unwrap(); assert_eq!(outcome.bytes, expected); // Invalid input length @@ -267,18 +267,18 @@ mod tests { ) .unwrap(); - let res = bn128_pair::run_pair(&input, 260_000); - assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); + let res = bn254_pair::run_pair(&input, 260_000); + assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); // Valid input length shorter than 112687 - let input = vec![1u8; 586 * bn128::PAIR_ELEMENT_LEN]; - let res = bn128_pair::run_pair(&input, 260_000); + let input = vec![1u8; 586 * bn254::PAIR_ELEMENT_LEN]; + let res = bn254_pair::run_pair(&input, 260_000); assert!(matches!(res, Err(PrecompileError::OutOfGas))); // Input length longer than 112687 - let input = vec![1u8; 587 * bn128::PAIR_ELEMENT_LEN]; - let res = bn128_pair::run_pair(&input, 260_000); - assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); + let input = vec![1u8; 587 * bn254::PAIR_ELEMENT_LEN]; + let res = bn254_pair::run_pair(&input, 260_000); + assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); } #[test] @@ -290,7 +290,7 @@ mod tests { #[test] fn test_cancun_precompiles_in_granite() { // granite has p256verify (fjord) - // granite has modification of cancun's bn128 pair (doesn't count as new precompile) + // granite has modification of cancun's bn254 pair (doesn't count as new precompile) assert_eq!(granite().difference(Precompiles::cancun()).len(), 1) } diff --git a/crates/op-revm/tests/integration.rs b/crates/op-revm/tests/integration.rs index cc7647b7f2..c20993daff 100644 --- a/crates/op-revm/tests/integration.rs +++ b/crates/op-revm/tests/integration.rs @@ -4,7 +4,7 @@ mod common; use alloy_primitives::bytes; use common::compare_or_save_testdata; use op_revm::{ - precompiles::bn128_pair::GRANITE_MAX_INPUT_SIZE, DefaultOp, L1BlockInfo, OpBuilder, + precompiles::bn254_pair::GRANITE_MAX_INPUT_SIZE, DefaultOp, L1BlockInfo, OpBuilder, OpHaltReason, OpSpecId, OpTransaction, }; use revm::SystemCallEvm; @@ -20,7 +20,7 @@ use revm::{ gas::{calculate_initial_tx_gas, InitialAndFloorGas}, Interpreter, InterpreterTypes, }, - precompile::{bls12_381_const, bls12_381_utils, bn128, secp256r1, u64_to_address}, + precompile::{bls12_381_const, bls12_381_utils, bn254, secp256r1, u64_to_address}, primitives::{eip7825, Address, Bytes, Log, TxKind, U256}, state::Bytecode, Context, ExecuteEvm, InspectEvm, Inspector, Journal, @@ -163,7 +163,7 @@ fn test_halted_tx_call_p256verify() { compare_or_save_testdata("test_halted_tx_call_p256verify.json", &output); } -fn bn128_pair_test_tx( +fn bn254_pair_test_tx( spec: OpSpecId, ) -> Context, CfgEnv, EmptyDB, Journal, L1BlockInfo> { @@ -176,7 +176,7 @@ fn bn128_pair_test_tx( OpTransaction::builder() .base( TxEnv::builder() - .kind(TxKind::Call(bn128::pair::ADDRESS)) + .kind(TxKind::Call(bn254::pair::ADDRESS)) .data(input) .gas_limit(initial_gas), ) @@ -186,8 +186,8 @@ fn bn128_pair_test_tx( } #[test] -fn test_halted_tx_call_bn128_pair_fjord() { - let ctx = bn128_pair_test_tx(OpSpecId::FJORD); +fn test_halted_tx_call_bn254_pair_fjord() { + let ctx = bn254_pair_test_tx(OpSpecId::FJORD); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -201,12 +201,12 @@ fn test_halted_tx_call_bn128_pair_fjord() { } )); - compare_or_save_testdata("test_halted_tx_call_bn128_pair_fjord.json", &output); + compare_or_save_testdata("test_halted_tx_call_bn254_pair_fjord.json", &output); } #[test] -fn test_halted_tx_call_bn128_pair_granite() { - let ctx = bn128_pair_test_tx(OpSpecId::GRANITE); +fn test_halted_tx_call_bn254_pair_granite() { + let ctx = bn254_pair_test_tx(OpSpecId::GRANITE); let mut evm = ctx.build_op(); let output = evm.replay().unwrap(); @@ -220,7 +220,7 @@ fn test_halted_tx_call_bn128_pair_granite() { } )); - compare_or_save_testdata("test_halted_tx_call_bn128_pair_granite.json", &output); + compare_or_save_testdata("test_halted_tx_call_bn254_pair_granite.json", &output); } #[test] diff --git a/crates/precompile/bench/eip1962.rs b/crates/precompile/bench/eip1962.rs index 92b547da95..afcc0b77f4 100644 --- a/crates/precompile/bench/eip1962.rs +++ b/crates/precompile/bench/eip1962.rs @@ -1,16 +1,16 @@ -//! Benchmarks for the BN128 precompiles +//! Benchmarks for the BN254 precompiles use criterion::{measurement::Measurement, BenchmarkGroup}; use primitives::hex; use primitives::Bytes; -use revm_precompile::bn128::{ +use revm_precompile::bn254::{ add::ISTANBUL_ADD_GAS_COST, mul::ISTANBUL_MUL_GAS_COST, pair::{ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT}, run_add, run_mul, run_pair, }; -/// Add benches for the BN128 add precompile -pub fn add_bn128_add_benches(group: &mut BenchmarkGroup<'_, M>) { +/// Add benches for the BN254 add precompile +pub fn add_bn254_add_benches(group: &mut BenchmarkGroup<'_, M>) { let ecadd_input = hex::decode( "\ 18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9\ @@ -21,13 +21,13 @@ pub fn add_bn128_add_benches(group: &mut BenchmarkGroup<'_, M>) .unwrap(); let input = Bytes::from(ecadd_input); - group.bench_function("bn128 add precompile", |b| { + group.bench_function("bn254 add precompile", |b| { b.iter(|| run_add(&input, ISTANBUL_ADD_GAS_COST, 150).unwrap()) }); } -/// Add benches for the BN128 mul precompile -pub fn add_bn128_mul_benches(group: &mut BenchmarkGroup<'_, M>) { +/// Add benches for the BN254 mul precompile +pub fn add_bn254_mul_benches(group: &mut BenchmarkGroup<'_, M>) { let ecmul_input = hex::decode( "\ 18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9\ @@ -37,13 +37,13 @@ pub fn add_bn128_mul_benches(group: &mut BenchmarkGroup<'_, M>) .unwrap(); let input = Bytes::from(ecmul_input); - group.bench_function("bn128 mul precompile", |b| { + group.bench_function("bn254 mul precompile", |b| { b.iter(|| run_mul(&input, ISTANBUL_MUL_GAS_COST, 6000).unwrap()) }); } -/// Add benches for the BN128 pair precompile -pub fn add_bn128_pair_benches(group: &mut BenchmarkGroup<'_, M>) { +/// Add benches for the BN254 pair precompile +pub fn add_bn254_pair_benches(group: &mut BenchmarkGroup<'_, M>) { let ecpair_input = hex::decode( "\ 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ diff --git a/crates/precompile/bench/main.rs b/crates/precompile/bench/main.rs index 153dc40ad1..dcb1bc6675 100644 --- a/crates/precompile/bench/main.rs +++ b/crates/precompile/bench/main.rs @@ -22,10 +22,10 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { eip2537::add_map_fp_to_g1_benches(&mut group); eip2537::add_map_fp2_to_g2_benches(&mut group); - // Run BN128 benchmarks - eip1962::add_bn128_add_benches(&mut group); - eip1962::add_bn128_mul_benches(&mut group); - eip1962::add_bn128_pair_benches(&mut group); + // Run BN254 benchmarks + eip1962::add_bn254_add_benches(&mut group); + eip1962::add_bn254_mul_benches(&mut group); + eip1962::add_bn254_pair_benches(&mut group); // Run secp256k1 benchmarks ecrecover::add_benches(&mut group); diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn254.rs similarity index 91% rename from crates/precompile/src/bn128.rs rename to crates/precompile/src/bn254.rs index 089f6b05d3..035b25caf3 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn254.rs @@ -1,4 +1,4 @@ -//! BN128 precompiles added in [`EIP-1962`](https://eips.ethereum.org/EIPS/eip-1962) +//! BN254 precompiles added in [`EIP-1962`](https://eips.ethereum.org/EIPS/eip-1962) use crate::{ crypto, utilities::{bool_to_bytes32, right_pad}, @@ -16,72 +16,72 @@ cfg_if::cfg_if! { } } -/// Bn128 add precompile +/// Bn254 add precompile pub mod add { use super::*; - /// Bn128 add precompile address + /// Bn254 add precompile address pub const ADDRESS: Address = crate::u64_to_address(6); - /// Bn128 add precompile with ISTANBUL gas rules + /// Bn254 add precompile with ISTANBUL gas rules pub const ISTANBUL_ADD_GAS_COST: u64 = 150; - /// Bn128 add precompile with ISTANBUL gas rules + /// Bn254 add precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit) }); - /// Bn128 add precompile with BYZANTIUM gas rules + /// Bn254 add precompile with BYZANTIUM gas rules pub const BYZANTIUM_ADD_GAS_COST: u64 = 500; - /// Bn128 add precompile with BYZANTIUM gas rules + /// Bn254 add precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit) }); } -/// Bn128 mul precompile +/// Bn254 mul precompile pub mod mul { use super::*; - /// Bn128 mul precompile address + /// Bn254 mul precompile address pub const ADDRESS: Address = crate::u64_to_address(7); - /// Bn128 mul precompile with ISTANBUL gas rules + /// Bn254 mul precompile with ISTANBUL gas rules pub const ISTANBUL_MUL_GAS_COST: u64 = 6_000; - /// Bn128 mul precompile with ISTANBUL gas rules + /// Bn254 mul precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit) }); - /// Bn128 mul precompile with BYZANTIUM gas rules + /// Bn254 mul precompile with BYZANTIUM gas rules pub const BYZANTIUM_MUL_GAS_COST: u64 = 40_000; - /// Bn128 mul precompile with BYZANTIUM gas rules + /// Bn254 mul precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit) }); } -/// Bn128 pair precompile +/// Bn254 pair precompile pub mod pair { use super::*; - /// Bn128 pair precompile address + /// Bn254 pair precompile address pub const ADDRESS: Address = crate::u64_to_address(8); - /// Bn128 pair precompile with ISTANBUL gas rules + /// Bn254 pair precompile with ISTANBUL gas rules pub const ISTANBUL_PAIR_PER_POINT: u64 = 34_000; - /// Bn128 pair precompile with ISTANBUL gas rules + /// Bn254 pair precompile with ISTANBUL gas rules pub const ISTANBUL_PAIR_BASE: u64 = 45_000; - /// Bn128 pair precompile with ISTANBUL gas rules + /// Bn254 pair precompile with ISTANBUL gas rules pub const ISTANBUL: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_pair( @@ -92,13 +92,13 @@ pub mod pair { ) }); - /// Bn128 pair precompile with BYZANTIUM gas rules + /// Bn254 pair precompile with BYZANTIUM gas rules pub const BYZANTIUM_PAIR_PER_POINT: u64 = 80_000; - /// Bn128 pair precompile with BYZANTIUM gas rules + /// Bn254 pair precompile with BYZANTIUM gas rules pub const BYZANTIUM_PAIR_BASE: u64 = 100_000; - /// Bn128 pair precompile with BYZANTIUM gas rules + /// Bn254 pair precompile with BYZANTIUM gas rules pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, |input, gas_limit| { run_pair( @@ -149,7 +149,7 @@ pub const MUL_INPUT_LEN: usize = G1_LEN + SCALAR_LEN; /// (128 bytes). pub const PAIR_ELEMENT_LEN: usize = G1_LEN + G2_LEN; -/// Run the Bn128 add precompile +/// Run the Bn254 add precompile pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); @@ -159,12 +159,12 @@ pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult let p1_bytes = &input[..G1_LEN]; let p2_bytes = &input[G1_LEN..]; - let output = crypto().bn128_g1_add(p1_bytes, p2_bytes)?; + let output = crypto().bn254_g1_add(p1_bytes, p2_bytes)?; Ok(PrecompileOutput::new(gas_cost, output.into())) } -/// Run the Bn128 mul precompile +/// Run the Bn254 mul precompile pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { return Err(PrecompileError::OutOfGas); @@ -174,12 +174,12 @@ pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult let point_bytes = &input[..G1_LEN]; let scalar_bytes = &input[G1_LEN..G1_LEN + SCALAR_LEN]; - let output = crypto().bn128_g1_mul(point_bytes, scalar_bytes)?; + let output = crypto().bn254_g1_mul(point_bytes, scalar_bytes)?; Ok(PrecompileOutput::new(gas_cost, output.into())) } -/// Run the Bn128 pair precompile +/// Run the Bn254 pair precompile pub fn run_pair( input: &[u8], pair_per_point_cost: u64, @@ -192,7 +192,7 @@ pub fn run_pair( } if !input.len().is_multiple_of(PAIR_ELEMENT_LEN) { - return Err(PrecompileError::Bn128PairLength); + return Err(PrecompileError::Bn254PairLength); } let elements = input.len() / PAIR_ELEMENT_LEN; @@ -213,7 +213,7 @@ pub fn run_pair( points.push((encoded_g1_element, encoded_g2_element)); } - let pairing_result = crypto().bn128_pairing_check(&points)?; + let pairing_result = crypto().bn254_pairing_check(&points)?; Ok(PrecompileOutput::new( gas_used, bool_to_bytes32(pairing_result), @@ -223,7 +223,7 @@ pub fn run_pair( #[cfg(test)] mod tests { use crate::{ - bn128::{ + bn254::{ add::BYZANTIUM_ADD_GAS_COST, mul::BYZANTIUM_MUL_GAS_COST, pair::{BYZANTIUM_PAIR_BASE, BYZANTIUM_PAIR_PER_POINT}, @@ -235,7 +235,7 @@ mod tests { use super::*; #[test] - fn test_alt_bn128_add() { + fn test_bn254_add() { let input = hex::decode( "\ 18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9\ @@ -312,12 +312,12 @@ mod tests { let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500); assert!(matches!( res, - Err(PrecompileError::Bn128AffineGFailedToCreate) + Err(PrecompileError::Bn254AffineGFailedToCreate) )); } #[test] - fn test_alt_bn128_mul() { + fn test_bn254_mul() { let input = hex::decode( "\ 2bd3e6d0f3b142924f5ca7b49ce5b9d54c4703d7ae5648e61d02268b1a0a9fb7\ @@ -389,12 +389,12 @@ mod tests { let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000); assert!(matches!( res, - Err(PrecompileError::Bn128AffineGFailedToCreate) + Err(PrecompileError::Bn254AffineGFailedToCreate) )); } #[test] - fn test_alt_bn128_pair() { + fn test_bn254_pair() { let input = hex::decode( "\ 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ @@ -485,7 +485,7 @@ mod tests { ); assert!(matches!( res, - Err(PrecompileError::Bn128AffineGFailedToCreate) + Err(PrecompileError::Bn254AffineGFailedToCreate) )); // Invalid input length @@ -504,7 +504,7 @@ mod tests { BYZANTIUM_PAIR_BASE, 260_000, ); - assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); + assert!(matches!(res, Err(PrecompileError::Bn254PairLength))); // Test with point at infinity - should return true (identity element) // G1 point at infinity (0,0) followed by a valid G2 point diff --git a/crates/precompile/src/bn128/arkworks.rs b/crates/precompile/src/bn254/arkworks.rs similarity index 96% rename from crates/precompile/src/bn128/arkworks.rs rename to crates/precompile/src/bn254/arkworks.rs index 8ab430f484..1572ad3786 100644 --- a/crates/precompile/src/bn128/arkworks.rs +++ b/crates/precompile/src/bn254/arkworks.rs @@ -27,7 +27,7 @@ fn read_fq(input_be: &[u8]) -> Result { input_le.reverse(); Fq::deserialize_uncompressed(&input_le[..]) - .map_err(|_| PrecompileError::Bn128FieldPointNotAMember) + .map_err(|_| PrecompileError::Bn254FieldPointNotAMember) } /// Reads a Fq2 (quadratic extension field element) from the input slice. /// @@ -64,7 +64,7 @@ fn new_g1_point(px: Fq, py: Fq) -> Result { // We cannot use `G1Affine::new` because that triggers an assert if the point is not on the curve. let point = G1Affine::new_unchecked(px, py); if !point.is_on_curve() || !point.is_in_correct_subgroup_assuming_on_curve() { - return Err(PrecompileError::Bn128AffineGFailedToCreate); + return Err(PrecompileError::Bn254AffineGFailedToCreate); } Ok(point) } @@ -72,7 +72,7 @@ fn new_g1_point(px: Fq, py: Fq) -> Result { /// Creates a new `G2` point from the given Fq2 coordinates. /// -/// G2 points in BN128 are defined over a quadratic extension field Fq2. +/// G2 points in BN254 are defined over a quadratic extension field Fq2. /// This function takes two Fq2 elements representing the x and y coordinates /// and creates a G2 point. /// @@ -89,7 +89,7 @@ fn new_g2_point(x: Fq2, y: Fq2) -> Result { // We cannot use `G1Affine::new` because that triggers an assert if the point is not on the curve. let point = G2Affine::new_unchecked(x, y); if !point.is_on_curve() || !point.is_in_correct_subgroup_assuming_on_curve() { - return Err(PrecompileError::Bn128AffineGFailedToCreate); + return Err(PrecompileError::Bn254AffineGFailedToCreate); } point }; diff --git a/crates/precompile/src/bn128/substrate.rs b/crates/precompile/src/bn254/substrate.rs similarity index 96% rename from crates/precompile/src/bn128/substrate.rs rename to crates/precompile/src/bn254/substrate.rs index c0656d54f8..d4e18cec4b 100644 --- a/crates/precompile/src/bn128/substrate.rs +++ b/crates/precompile/src/bn254/substrate.rs @@ -14,7 +14,7 @@ use std::vec::Vec; /// Panics if the input is not at least 32 bytes long. #[inline] fn read_fq(input: &[u8]) -> Result { - Fq::from_slice(&input[..FQ_LEN]).map_err(|_| PrecompileError::Bn128FieldPointNotAMember) + Fq::from_slice(&input[..FQ_LEN]).map_err(|_| PrecompileError::Bn254FieldPointNotAMember) } /// Reads a Fq2 (quadratic extension field element) from the input slice. /// @@ -49,13 +49,13 @@ fn new_g1_point(px: Fq, py: Fq) -> Result { } else { AffineG1::new(px, py) .map(Into::into) - .map_err(|_| PrecompileError::Bn128AffineGFailedToCreate) + .map_err(|_| PrecompileError::Bn254AffineGFailedToCreate) } } /// Creates a new `G2` point from the given Fq2 coordinates. /// -/// G2 points in BN128 are defined over a quadratic extension field Fq2. +/// G2 points in BN254 are defined over a quadratic extension field Fq2. /// This function takes two Fq2 elements representing the x and y coordinates /// and creates a G2 point. /// @@ -69,7 +69,7 @@ fn new_g2_point(x: Fq2, y: Fq2) -> Result { let point = if x.is_zero() && y.is_zero() { G2::zero() } else { - G2::from(AffineG2::new(x, y).map_err(|_| PrecompileError::Bn128AffineGFailedToCreate)?) + G2::from(AffineG2::new(x, y).map_err(|_| PrecompileError::Bn254AffineGFailedToCreate)?) }; Ok(point) diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index a5279a5e91..f9a5b77163 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -88,22 +88,22 @@ pub trait Crypto: Send + Sync + Debug { output } - /// BN128 elliptic curve addition. + /// BN254 elliptic curve addition. #[inline] - fn bn128_g1_add(&self, p1: &[u8], p2: &[u8]) -> Result<[u8; 64], PrecompileError> { - crate::bn128::crypto_backend::g1_point_add(p1, p2) + fn bn254_g1_add(&self, p1: &[u8], p2: &[u8]) -> Result<[u8; 64], PrecompileError> { + crate::bn254::crypto_backend::g1_point_add(p1, p2) } - /// BN128 elliptic curve scalar multiplication. + /// BN254 elliptic curve scalar multiplication. #[inline] - fn bn128_g1_mul(&self, point: &[u8], scalar: &[u8]) -> Result<[u8; 64], PrecompileError> { - crate::bn128::crypto_backend::g1_point_mul(point, scalar) + fn bn254_g1_mul(&self, point: &[u8], scalar: &[u8]) -> Result<[u8; 64], PrecompileError> { + crate::bn254::crypto_backend::g1_point_mul(point, scalar) } - /// BN128 pairing check. + /// BN254 pairing check. #[inline] - fn bn128_pairing_check(&self, pairs: &[(&[u8], &[u8])]) -> Result { - crate::bn128::crypto_backend::pairing_check(pairs) + fn bn254_pairing_check(&self, pairs: &[(&[u8], &[u8])]) -> Result { + crate::bn254::crypto_backend::pairing_check(pairs) } /// secp256k1 ECDSA signature recovery. @@ -218,12 +218,12 @@ pub enum PrecompileError { ModexpModOverflow, /// Modexp limit all input sizes. ModexpEip7823LimitSize, - /// Bn128 errors - Bn128FieldPointNotAMember, - /// Bn128 affine g failed to create - Bn128AffineGFailedToCreate, - /// Bn128 pair length - Bn128PairLength, + /// Bn254 errors + Bn254FieldPointNotAMember, + /// Bn254 affine g failed to create + Bn254AffineGFailedToCreate, + /// Bn254 pair length + Bn254PairLength, // Blob errors /// The input length is not exactly 192 bytes BlobInvalidInputLength, @@ -261,9 +261,9 @@ impl fmt::Display for PrecompileError { Self::ModexpBaseOverflow => "modexp base overflow", Self::ModexpModOverflow => "modexp mod overflow", Self::ModexpEip7823LimitSize => "Modexp limit all input sizes.", - Self::Bn128FieldPointNotAMember => "field point not a member of bn128 curve", - Self::Bn128AffineGFailedToCreate => "failed to create affine g point for bn128 curve", - Self::Bn128PairLength => "bn128 invalid pair length", + Self::Bn254FieldPointNotAMember => "field point not a member of bn254 curve", + Self::Bn254AffineGFailedToCreate => "failed to create affine g point for bn254 curve", + Self::Bn254PairLength => "bn254 invalid pair length", Self::BlobInvalidInputLength => "invalid blob input length", Self::BlobMismatchedVersion => "mismatched blob version", Self::BlobVerifyKzgProofFailed => "verifying blob kzg proof failed", diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index bf0389c5ea..4968f74556 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -12,7 +12,7 @@ pub mod blake2; pub mod bls12_381; pub mod bls12_381_const; pub mod bls12_381_utils; -pub mod bn128; +pub mod bn254; pub mod hash; pub mod identity; pub mod interface; @@ -118,9 +118,9 @@ impl Precompiles { modexp::BYZANTIUM, // EIP-196: Precompiled contracts for addition and scalar multiplication on the elliptic curve alt_bn128. // EIP-197: Precompiled contracts for optimal ate pairing check on the elliptic curve alt_bn128. - bn128::add::BYZANTIUM, - bn128::mul::BYZANTIUM, - bn128::pair::BYZANTIUM, + bn254::add::BYZANTIUM, + bn254::mul::BYZANTIUM, + bn254::pair::BYZANTIUM, ]); precompiles }) @@ -133,9 +133,9 @@ impl Precompiles { let mut precompiles = Self::byzantium().clone(); precompiles.extend([ // EIP-1108: Reduce alt_bn128 precompile gas costs. - bn128::add::ISTANBUL, - bn128::mul::ISTANBUL, - bn128::pair::ISTANBUL, + bn254::add::ISTANBUL, + bn254::mul::ISTANBUL, + bn254::pair::ISTANBUL, // EIP-152: Add BLAKE2 compression function `F` precompile. blake2::FUN, ]); From d30dc7f89ce7caccd83397027c3fee70d4459a19 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 28 Jul 2025 17:09:07 +0200 Subject: [PATCH 19/78] feat: Align naming of SystemCallEvm function to ExecuteEvm (#2814) --- book/src/external_state_transitions.md | 4 +- crates/handler/src/system_call.rs | 105 +++++++++++++++++++------ crates/op-revm/src/api/exec.rs | 2 +- crates/op-revm/tests/integration.rs | 4 +- examples/my_evm/README.md | 2 +- 5 files changed, 88 insertions(+), 29 deletions(-) diff --git a/book/src/external_state_transitions.md b/book/src/external_state_transitions.md index 131b1b012f..d7dee89c27 100644 --- a/book/src/external_state_transitions.md +++ b/book/src/external_state_transitions.md @@ -1,6 +1,6 @@ # External State Transitions (EIP-4788 & EIP-2935) -Some Ethereum Improvement Proposals (EIPs) require state transitions that are not triggered by regular user transactions, but are instead performed by the client using special system calls (such as `transact_system_call`). These transitions are part of the EVM state changes, but are initiated by the client at specific block boundaries (pre- or post-block hooks), as required by the EIP. +Some Ethereum Improvement Proposals (EIPs) require state transitions that are not triggered by regular user transactions, but are instead performed by the client using special system calls (such as `system_call`). These transitions are part of the EVM state changes, but are initiated by the client at specific block boundaries (pre- or post-block hooks), as required by the EIP. - [EIP-4788: Beacon block root in the EVM](https://eips.ethereum.org/EIPS/eip-4788) - [EIP-2935: Add `blockHash` and `blockNumber` to the EVM](https://eips.ethereum.org/EIPS/eip-2935) @@ -28,7 +28,7 @@ EIP-2935 introduces a system contract that stores recent block hashes, allowing ## How does this affect REVM users? -- To perform these block state transitions, the client or test harness should use the system call mechanism (`transact_system_call`) provided by REVM. +- To perform these block state transitions, the client or test harness should use the system call mechanism (`system_call`) provided by REVM. - REVM itself does not automatically perform these transitions; it expects the client to initiate them at the appropriate block boundaries, as specified by the EIPs. - If you are building a full Ethereum client or a test harness, you are responsible for performing these system calls at the appropriate block boundaries, as specified in the EIPs. - If you are only using REVM for transaction execution, you may need to ensure that the state of these system contracts is kept up to date externally. diff --git a/crates/handler/src/system_call.rs b/crates/handler/src/system_call.rs index 5f27a9fb85..dc7a01b5fa 100644 --- a/crates/handler/src/system_call.rs +++ b/crates/handler/src/system_call.rs @@ -2,20 +2,20 @@ //! //! These EIPs require the client to perform special system calls to update state (such as block hashes or beacon roots) at block boundaries, outside of normal EVM transaction execution. REVM provides the system call mechanism, but the actual state transitions must be performed by the client or test harness, not by the EVM itself. //! -//! # Example: Using `transact_system_call` for pre/post block hooks +//! # Example: Using `system_call` for pre/post block hooks //! -//! The client should use [`SystemCallEvm::transact_system_call`] method to perform required state updates before or after block execution, as specified by the EIP: +//! The client should use [`SystemCallEvm::system_call`] method to perform required state updates before or after block execution, as specified by the EIP: //! //! ```rust,ignore //! // Example: update beacon root (EIP-4788) at the start of a block //! let beacon_root: Bytes = ...; // obtained from consensus layer //! let beacon_contract: Address = "0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02".parse().unwrap(); -//! evm.transact_system_call(beacon_contract, beacon_root)?; +//! evm.system_call(beacon_contract, beacon_root)?; //! //! // Example: update block hash (EIP-2935) at the end of a block //! let block_hash: Bytes = ...; // new block hash //! let history_contract: Address = "0x0000F90827F1C53a10cb7A02335B175320002935".parse().unwrap(); -//! evm.transact_system_call(history_contract, block_hash)?; +//! evm.system_call(history_contract, block_hash)?; //! ``` //! //! See the book section on [External State Transitions](../../book/src/external_state_transitions.md) for more details. @@ -79,69 +79,128 @@ pub trait SystemCallEvm: ExecuteEvm { /// given values. /// /// Block values are taken into account and will determent how system call will be executed. - fn transact_system_call_with_caller( + fn system_call_one( &mut self, caller: Address, system_contract_address: Address, data: Bytes, ) -> Result; - /// Calls [`SystemCallEvm::transact_system_call_with_caller`] with [`SYSTEM_ADDRESS`] as a caller. + /// System call is a special transaction call that is used to call a system contract. + /// + /// Transaction fields are reset and set in [`SystemCallTx`] and data and target are set to + /// given values. + /// + /// Block values are taken into account and will determent how system call will be executed. + #[deprecated(since = "0.1.0", note = "Use `system_call_one` instead")] + fn transact_system_call_with_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result { + self.system_call_one(caller, system_contract_address, data) + } + + /// Calls [`SystemCallEvm::system_call_one`] with [`SYSTEM_ADDRESS`] as a caller. + #[deprecated( + since = "0.1.0", + note = "Use `system_call_one` with SYSTEM_ADDRESS instead" + )] fn transact_system_call( &mut self, system_contract_address: Address, data: Bytes, ) -> Result { - self.transact_system_call_with_caller(SYSTEM_ADDRESS, system_contract_address, data) + self.system_call_one(SYSTEM_ADDRESS, system_contract_address, data) + } + + /// Transact the system call and finalize. + /// + /// Internally calls combo of `system_call_one` and `finalize` functions. + fn system_call( + &mut self, + system_contract_address: Address, + data: Bytes, + ) -> Result, Self::Error> { + self.system_call_with_caller(SYSTEM_ADDRESS, system_contract_address, data) } /// Transact the system call and finalize. /// /// Internally calls combo of `transact_system_call` and `finalize` functions. + #[deprecated(since = "0.1.0", note = "Use `system_call` instead")] fn transact_system_call_finalize( &mut self, system_contract_address: Address, data: Bytes, ) -> Result, Self::Error> { - self.transact_system_call_with_caller_finalize( - SYSTEM_ADDRESS, - system_contract_address, - data, - ) + self.system_call(system_contract_address, data) } - /// Calls [`SystemCallEvm::transact_system_call_with_caller`] and `finalize` functions. - fn transact_system_call_with_caller_finalize( + /// Calls [`SystemCallEvm::system_call_one`] and `finalize` functions. + fn system_call_with_caller( &mut self, caller: Address, system_contract_address: Address, data: Bytes, ) -> Result, Self::Error> { - let result = - self.transact_system_call_with_caller(caller, system_contract_address, data)?; + let result = self.system_call_one(caller, system_contract_address, data)?; let state = self.finalize(); Ok(ExecResultAndState::new(result, state)) } + + /// Calls [`SystemCallEvm::system_call_one`] and `finalize` functions. + #[deprecated(since = "0.1.0", note = "Use `system_call_with_caller` instead")] + fn transact_system_call_with_caller_finalize( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result, Self::Error> { + self.system_call_with_caller(caller, system_contract_address, data) + } } /// Extension of the [`SystemCallEvm`] trait that adds a method that commits the state after execution. pub trait SystemCallCommitEvm: SystemCallEvm + ExecuteCommitEvm { /// Transact the system call and commit to the state. + fn system_call_commit( + &mut self, + system_contract_address: Address, + data: Bytes, + ) -> Result { + self.system_call_with_caller_commit(SYSTEM_ADDRESS, system_contract_address, data) + } + + /// Transact the system call and commit to the state. + #[deprecated(since = "0.1.0", note = "Use `system_call_commit` instead")] fn transact_system_call_commit( &mut self, system_contract_address: Address, data: Bytes, ) -> Result { - self.transact_system_call_with_caller_commit(SYSTEM_ADDRESS, system_contract_address, data) + self.system_call_commit(system_contract_address, data) } - /// Calls [`SystemCallCommitEvm::transact_system_call_commit`] with [`SYSTEM_ADDRESS`] as a caller. - fn transact_system_call_with_caller_commit( + /// Calls [`SystemCallCommitEvm::system_call_commit`] with a custom caller. + fn system_call_with_caller_commit( &mut self, caller: Address, system_contract_address: Address, data: Bytes, ) -> Result; + + /// Calls [`SystemCallCommitEvm::system_call_commit`] with a custom caller. + #[deprecated(since = "0.1.0", note = "Use `system_call_with_caller_commit` instead")] + fn transact_system_call_with_caller_commit( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result { + self.system_call_with_caller_commit(caller, system_contract_address, data) + } } impl SystemCallEvm @@ -151,7 +210,7 @@ where INST: InstructionProvider, PRECOMPILES: PrecompileProvider, { - fn transact_system_call_with_caller( + fn system_call_one( &mut self, caller: Address, system_contract_address: Address, @@ -176,13 +235,13 @@ where INST: InstructionProvider, PRECOMPILES: PrecompileProvider, { - fn transact_system_call_with_caller_commit( + fn system_call_with_caller_commit( &mut self, caller: Address, system_contract_address: Address, data: Bytes, ) -> Result { - self.transact_system_call_with_caller_finalize(caller, system_contract_address, data) + self.system_call_with_caller(caller, system_contract_address, data) .map(|output| { self.db_mut().commit(output.state); output.result @@ -223,7 +282,7 @@ mod tests { .modify_block_chained(|b| b.number = U256::ONE) .build_mainnet(); let output = evm - .transact_system_call_finalize(HISTORY_STORAGE_ADDRESS, block_hash.0.into()) + .system_call(HISTORY_STORAGE_ADDRESS, block_hash.0.into()) .unwrap(); // system call gas limit is 30M diff --git a/crates/op-revm/src/api/exec.rs b/crates/op-revm/src/api/exec.rs index a5ddec95b6..2e8f24b232 100644 --- a/crates/op-revm/src/api/exec.rs +++ b/crates/op-revm/src/api/exec.rs @@ -127,7 +127,7 @@ where CTX: OpContextTr + ContextSetters, PRECOMPILE: PrecompileProvider, { - fn transact_system_call_with_caller( + fn system_call_one( &mut self, caller: Address, system_contract_address: Address, diff --git a/crates/op-revm/tests/integration.rs b/crates/op-revm/tests/integration.rs index c20993daff..088bf5a8cc 100644 --- a/crates/op-revm/tests/integration.rs +++ b/crates/op-revm/tests/integration.rs @@ -7,7 +7,6 @@ use op_revm::{ precompiles::bn254_pair::GRANITE_MAX_INPUT_SIZE, DefaultOp, L1BlockInfo, OpBuilder, OpHaltReason, OpSpecId, OpTransaction, }; -use revm::SystemCallEvm; use revm::{ bytecode::opcode, context::{ @@ -25,6 +24,7 @@ use revm::{ state::Bytecode, Context, ExecuteEvm, InspectEvm, Inspector, Journal, }; +use revm::{handler::system_call::SYSTEM_ADDRESS, SystemCallEvm}; use std::vec::Vec; #[test] @@ -1081,7 +1081,7 @@ fn test_system_call() { let mut evm = ctx.build_op(); - evm.transact_system_call(BENCH_TARGET, bytes!("0x0001")) + evm.system_call_one(SYSTEM_ADDRESS, BENCH_TARGET, bytes!("0x0001")) .unwrap(); // Run evm. diff --git a/examples/my_evm/README.md b/examples/my_evm/README.md index cc80132fc4..7b0a852968 100644 --- a/examples/my_evm/README.md +++ b/examples/my_evm/README.md @@ -76,5 +76,5 @@ System calls are needed for inserting of fetching data on pre or post block stat ```rust,ignore let mut my_evm = MyEvm::new(Context::mainnet(), revm::inspector::NoOpInspector); // System call with given input to system contract address. -let _res = my_evm.transact_system_call(bytes!("0x0001"), address!("f529c70db0800449ebd81fbc6e4221523a989f05")); +let _res = my_evm.system_call_one(SYSTEM_ADDRESS, address!("f529c70db0800449ebd81fbc6e4221523a989f05"), bytes!("0x0001")); ``` From 3c7d8b99357fde88c6112e59e7fe849e9ad5ead4 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Mon, 28 Jul 2025 17:11:19 +0200 Subject: [PATCH 20/78] Update test data for renamed tests (#2817) --- ... test_halted_tx_call_bn254_pair_fjord.json} | 18 +++++++++--------- ...est_halted_tx_call_bn254_pair_granite.json} | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) rename crates/op-revm/tests/testdata/{test_halted_tx_call_bn128_pair_fjord.json => test_halted_tx_call_bn254_pair_fjord.json} (100%) rename crates/op-revm/tests/testdata/{test_halted_tx_call_bn128_pair_granite.json => test_halted_tx_call_bn254_pair_granite.json} (100%) diff --git a/crates/op-revm/tests/testdata/test_halted_tx_call_bn128_pair_fjord.json b/crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_fjord.json similarity index 100% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bn128_pair_fjord.json rename to crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_fjord.json index eae5c631fa..03f0c8e0fc 100644 --- a/crates/op-revm/tests/testdata/test_halted_tx_call_bn128_pair_fjord.json +++ b/crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_fjord.json @@ -10,10 +10,10 @@ } }, "state": { - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, + "nonce": 1, "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { @@ -35,7 +35,7 @@ "storage": {}, "status": "Touched | LoadedAsNotExisting" }, - "0x420000000000000000000000000000000000001b": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", "nonce": 0, @@ -60,10 +60,10 @@ "storage": {}, "status": "Touched | LoadedAsNotExisting" }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 1, + "nonce": 0, "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { @@ -85,7 +85,7 @@ "storage": {}, "status": "Touched | LoadedAsNotExisting" }, - "0x0000000000000000000000000000000000000008": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", "nonce": 0, @@ -108,9 +108,9 @@ }, "transaction_id": 0, "storage": {}, - "status": "LoadedAsNotExisting" + "status": "Touched | LoadedAsNotExisting" }, - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000008": { "info": { "balance": "0x0", "nonce": 0, @@ -133,7 +133,7 @@ }, "transaction_id": 0, "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "status": "LoadedAsNotExisting" } } } \ No newline at end of file diff --git a/crates/op-revm/tests/testdata/test_halted_tx_call_bn128_pair_granite.json b/crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_granite.json similarity index 100% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bn128_pair_granite.json rename to crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_granite.json index ce92b11014..f05d9a8269 100644 --- a/crates/op-revm/tests/testdata/test_halted_tx_call_bn128_pair_granite.json +++ b/crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_granite.json @@ -8,7 +8,7 @@ } }, "state": { - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", "nonce": 0, @@ -33,7 +33,7 @@ "storage": {}, "status": "Touched | LoadedAsNotExisting" }, - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000008": { "info": { "balance": "0x0", "nonce": 0, @@ -56,12 +56,12 @@ }, "transaction_id": 0, "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "status": "LoadedAsNotExisting" }, - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, + "nonce": 1, "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { @@ -83,10 +83,10 @@ "storage": {}, "status": "Touched | LoadedAsNotExisting" }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 1, + "nonce": 0, "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { @@ -108,7 +108,7 @@ "storage": {}, "status": "Touched | LoadedAsNotExisting" }, - "0x0000000000000000000000000000000000000008": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", "nonce": 0, @@ -131,7 +131,7 @@ }, "transaction_id": 0, "storage": {}, - "status": "LoadedAsNotExisting" + "status": "Touched | LoadedAsNotExisting" } } } \ No newline at end of file From c2c4b3f168b6f038b86b008fe214229c1a4e8d91 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Mon, 28 Jul 2025 17:12:00 +0200 Subject: [PATCH 21/78] test(op-revm): Full test coverage `OpTransactionError` (#2818) * Fix typos * Cover OpTransactionError::Base in test display * fixup! Fix typos --- crates/op-revm/src/transaction/error.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/crates/op-revm/src/transaction/error.rs b/crates/op-revm/src/transaction/error.rs index 76169a3dd8..ba13cab90e 100644 --- a/crates/op-revm/src/transaction/error.rs +++ b/crates/op-revm/src/transaction/error.rs @@ -18,7 +18,7 @@ pub enum OpTransactionError { /// was deprecated in the Regolith hardfork, and this error is thrown if a `Deposit` transaction /// is found with this field set to `true` after the hardfork activation. /// - /// In addition, this error is internal, and bubbles up into a [OpHaltReason::FailedDeposit][crate::OpHaltReason::FailedDeposit] error + /// In addition, this error is internal, and bubbles up into an [OpHaltReason::FailedDeposit][crate::OpHaltReason::FailedDeposit] error /// in the `revm` handler for the consumer to easily handle. This is due to a state transition /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and @@ -26,14 +26,14 @@ 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. DepositSystemTxPostRegolith, - /// Deposit transaction haults bubble up to the global main return handler, wiping state and + /// Deposit transaction halts bubble up to the global main return handler, wiping state and /// only increasing the nonce + persisting the mint value. /// - /// This is a catch-all error for any deposit transaction that is results in a [OpHaltReason][crate::OpHaltReason] error + /// This is a catch-all error for any deposit transaction that results in an [OpHaltReason][crate::OpHaltReason] error /// post-regolith hardfork. This allows for a consumer to easily handle special cases where /// a deposit transaction fails during validation, but must still be included in the block. /// - /// In addition, this error is internal, and bubbles up into a [OpHaltReason::FailedDeposit][crate::OpHaltReason::FailedDeposit] error + /// In addition, this error is internal, and bubbles up into an [OpHaltReason::FailedDeposit][crate::OpHaltReason::FailedDeposit] error /// in the `revm` handler for the consumer to easily handle. This is due to a state transition /// rule on OP Stack chains where, if for any reason a deposit transaction fails, the transaction /// must still be included in the block, the sender nonce is bumped, the `mint` value persists, and @@ -86,6 +86,11 @@ mod test { #[test] fn test_display_op_errors() { + assert_eq!( + OpTransactionError::Base(InvalidTransaction::NonceTooHigh { tx: 2, state: 1 }) + .to_string(), + "nonce 2 too high, expected 1" + ); assert_eq!( OpTransactionError::DepositSystemTxPostRegolith.to_string(), "deposit system transactions post regolith hardfork are not supported" From 9008e93f21ead68382a4fe2b7183746c0fd77272 Mon Sep 17 00:00:00 2001 From: Rez Date: Tue, 29 Jul 2025 20:01:42 +1000 Subject: [PATCH 22/78] feat: add system transaction inspection support (#2808) * att1 * cargo fmt * reduce test bloat * remove InspectSystemCallCommitEvm * fix: rename system call inspection methods to match inspect_one_tx pattern - inspect_system_call_one -> inspect_one_system_call - inspect_system_call_with_caller_one -> inspect_one_system_call_with_caller - inspect_system_call_with_inspector_one -> inspect_one_system_call_with_inspector * feat: add system call inspection support to op-revm - Implement InspectSystemCallEvm trait for OpEvm - Add inspect_one_system_call_with_caller method - Add comprehensive test for system call inspection functionality * fix: simplify system call inspection test - Remove unnecessary custom bytecode setup - Use default context for cleaner test * style: fix code formatting for CI - Format import statements in exec.rs - Fix whitespace formatting in test functions - Ensure consistent code style across files * trigger ci * Revert "trigger ci" This reverts commit fba9ceb361ea25c0564b92ed1bef992de7f6a7a3. --- crates/inspector/src/handler.rs | 24 +++++++ crates/inspector/src/inspect.rs | 88 ++++++++++++++++++++++++- crates/inspector/src/inspector_tests.rs | 71 +++++++++++++++++++- crates/inspector/src/lib.rs | 2 +- crates/inspector/src/mainnet_inspect.rs | 34 +++++++++- crates/op-revm/src/api/exec.rs | 27 +++++++- crates/op-revm/tests/integration.rs | 38 +++++++++++ crates/revm/src/lib.rs | 2 +- 8 files changed, 278 insertions(+), 8 deletions(-) diff --git a/crates/inspector/src/handler.rs b/crates/inspector/src/handler.rs index 10b07570ac..aad34460cc 100644 --- a/crates/inspector/src/handler.rs +++ b/crates/inspector/src/handler.rs @@ -13,6 +13,8 @@ use state::bytecode::opcode; /// /// Similar how [`Handler::run`] method serves as the entry point, /// [`InspectorHandler::inspect_run`] method serves as the entry point for inspection. +/// For system calls, [`InspectorHandler::inspect_run_system_call`] provides inspection +/// support similar to [`Handler::run_system_call`]. /// /// Notice that when inspection is run it skips few functions from handler, this can be /// a problem if custom EVM is implemented and some of skipped functions have changed logic. @@ -24,6 +26,7 @@ use state::bytecode::opcode; /// * [`Handler::execution`] replaced with [`InspectorHandler::inspect_execution`] /// * [`Handler::run_exec_loop`] replaced with [`InspectorHandler::inspect_run_exec_loop`] /// * `run_exec_loop` calls `inspect_frame_init` and `inspect_frame_run` that call inspector inside. +/// * [`Handler::run_system_call`] replaced with [`InspectorHandler::inspect_run_system_call`] pub trait InspectorHandler: Handler where Self::Evm: @@ -121,6 +124,27 @@ where } } } + + /// Run system call with inspection support. + /// + /// This method acts as [`Handler::run_system_call`] method for inspection. + /// Similar to [`InspectorHandler::inspect_run`] but skips validation and pre-execution phases, + /// going directly to execution with inspection support. + fn inspect_run_system_call( + &mut self, + evm: &mut Self::Evm, + ) -> Result, Self::Error> { + // dummy values that are not used. + let init_and_floor_gas = InitialAndFloorGas::new(0, 0); + // call execution with inspection and then output. + match self + .inspect_execution(evm, &init_and_floor_gas) + .and_then(|exec_result| self.execution_result(evm, exec_result)) + { + out @ Ok(_) => out, + Err(e) => self.catch_error(evm, e), + } + } } /// Handles the start of a frame by calling the appropriate inspector method. diff --git a/crates/inspector/src/inspect.rs b/crates/inspector/src/inspect.rs index 5ac1ada4a6..79beb2c6b8 100644 --- a/crates/inspector/src/inspect.rs +++ b/crates/inspector/src/inspect.rs @@ -1,5 +1,6 @@ use context::result::ExecResultAndState; -use handler::{ExecuteCommitEvm, ExecuteEvm}; +use handler::{system_call::SYSTEM_ADDRESS, ExecuteCommitEvm, ExecuteEvm, SystemCallEvm}; +use primitives::{Address, Bytes}; /// InspectEvm is a API that allows inspecting the EVM. /// @@ -76,3 +77,88 @@ pub trait InspectCommitEvm: InspectEvm + ExecuteCommitEvm { Ok(output) } } + +/// InspectSystemCallEvm is an API that allows inspecting system calls in the EVM. +/// +/// It extends [`InspectEvm`] and [`SystemCallEvm`] traits to provide inspection +/// capabilities for system transactions, enabling tracing and debugging of +/// system calls similar to regular transactions. +pub trait InspectSystemCallEvm: InspectEvm + SystemCallEvm { + /// Inspect a system call with the current inspector. + /// + /// Similar to [`InspectEvm::inspect_one_tx`] but for system calls. + /// Uses [`SYSTEM_ADDRESS`] as the caller. + fn inspect_one_system_call( + &mut self, + system_contract_address: Address, + data: Bytes, + ) -> Result { + self.inspect_one_system_call_with_caller(SYSTEM_ADDRESS, system_contract_address, data) + } + + /// Inspect a system call with the current inspector and a custom caller. + /// + /// Similar to [`InspectEvm::inspect_one_tx`] but for system calls with a custom caller. + fn inspect_one_system_call_with_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result; + + /// Inspect a system call and finalize the state. + /// + /// Similar to [`InspectEvm::inspect_tx`] but for system calls. + fn inspect_system_call( + &mut self, + system_contract_address: Address, + data: Bytes, + ) -> Result, Self::Error> { + let output = self.inspect_one_system_call(system_contract_address, data)?; + let state = self.finalize(); + Ok(ExecResultAndState::new(output, state)) + } + + /// Inspect a system call with a custom caller and finalize the state. + /// + /// Similar to [`InspectEvm::inspect_tx`] but for system calls with a custom caller. + fn inspect_system_call_with_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result, Self::Error> { + let output = + self.inspect_one_system_call_with_caller(caller, system_contract_address, data)?; + let state = self.finalize(); + Ok(ExecResultAndState::new(output, state)) + } + + /// Inspect a system call with a given inspector. + /// + /// Similar to [`InspectEvm::inspect_one`] but for system calls. + fn inspect_one_system_call_with_inspector( + &mut self, + system_contract_address: Address, + data: Bytes, + inspector: Self::Inspector, + ) -> Result { + self.set_inspector(inspector); + self.inspect_one_system_call(system_contract_address, data) + } + + /// Inspect a system call with a given inspector and finalize the state. + /// + /// Similar to [`InspectEvm::inspect`] but for system calls. + fn inspect_system_call_with_inspector( + &mut self, + system_contract_address: Address, + data: Bytes, + inspector: Self::Inspector, + ) -> Result, Self::Error> { + let output = + self.inspect_one_system_call_with_inspector(system_contract_address, data, inspector)?; + let state = self.finalize(); + Ok(ExecResultAndState::new(output, state)) + } +} diff --git a/crates/inspector/src/inspector_tests.rs b/crates/inspector/src/inspector_tests.rs index 29cfa54c94..5916a75c86 100644 --- a/crates/inspector/src/inspector_tests.rs +++ b/crates/inspector/src/inspector_tests.rs @@ -1,6 +1,6 @@ #[cfg(test)] mod tests { - use crate::{InspectEvm, Inspector}; + use crate::{InspectEvm, InspectSystemCallEvm, Inspector}; use context::{Context, TxEnv}; use database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}; use handler::{MainBuilder, MainContext}; @@ -731,4 +731,73 @@ mod tests { "Should have jumped to JUMPDEST" ); } + + #[test] + fn test_system_call_inspection_basic() { + // PUSH1 0x42, SSTORE, STOP + let code = Bytes::from(vec![ + opcode::PUSH1, + 0x42, + opcode::PUSH1, + 0x00, + opcode::SSTORE, + opcode::STOP, + ]); + + let bytecode = Bytecode::new_raw(code); + let ctx = Context::mainnet().with_db(BenchmarkDB::new_bytecode(bytecode)); + let mut evm = ctx.build_mainnet_with_inspector(TestInspector::new()); + + let result = evm + .inspect_system_call(BENCH_TARGET, Bytes::default()) + .unwrap(); + + assert!(result.result.is_success()); + assert!(evm.inspector.get_step_count() > 0); + assert!(!result.state.is_empty()); + } + + #[test] + fn test_system_call_inspection_api_variants() { + let code = vec![ + opcode::CALLER, + opcode::PUSH1, + 0x00, + opcode::MSTORE, + opcode::PUSH1, + 0x20, + opcode::PUSH1, + 0x00, + opcode::RETURN, + ]; + + let bytecode = Bytecode::new_raw(Bytes::from(code)); + let ctx = Context::mainnet().with_db(BenchmarkDB::new_bytecode(bytecode)); + let mut evm = ctx.build_mainnet_with_inspector(TestInspector::new()); + + // Test inspect_one_system_call + let result = evm + .inspect_one_system_call(BENCH_TARGET, Bytes::default()) + .unwrap(); + assert!(result.is_success()); + + // Test inspect_one_system_call_with_caller + let custom_caller = address!("0x1234567890123456789012345678901234567890"); + let result = evm + .inspect_one_system_call_with_caller(custom_caller, BENCH_TARGET, Bytes::default()) + .unwrap(); + assert!(result.is_success()); + + // Test inspect_one_system_call_with_inspector + let result = evm + .inspect_one_system_call_with_inspector( + BENCH_TARGET, + Bytes::default(), + TestInspector::new(), + ) + .unwrap(); + assert!(result.is_success()); + + assert!(evm.inspector.get_step_count() > 0); + } } diff --git a/crates/inspector/src/lib.rs b/crates/inspector/src/lib.rs index 26998967f6..93072de4bd 100644 --- a/crates/inspector/src/lib.rs +++ b/crates/inspector/src/lib.rs @@ -30,7 +30,7 @@ pub mod inspectors { pub use count_inspector::CountInspector; pub use handler::{inspect_instructions, InspectorHandler}; -pub use inspect::{InspectCommitEvm, InspectEvm}; +pub use inspect::{InspectCommitEvm, InspectEvm, InspectSystemCallEvm}; pub use inspector::*; pub use noop::NoOpInspector; pub use traits::*; diff --git a/crates/inspector/src/mainnet_inspect.rs b/crates/inspector/src/mainnet_inspect.rs index 33afea5512..6b78bf7440 100644 --- a/crates/inspector/src/mainnet_inspect.rs +++ b/crates/inspector/src/mainnet_inspect.rs @@ -1,14 +1,15 @@ use crate::{ - inspect::{InspectCommitEvm, InspectEvm}, + inspect::{InspectCommitEvm, InspectEvm, InspectSystemCallEvm}, Inspector, InspectorEvmTr, InspectorHandler, JournalExt, }; use context::{ContextSetters, ContextTr, Evm, JournalTr}; use database_interface::DatabaseCommit; use handler::{ - instructions::InstructionProvider, EthFrame, EvmTr, EvmTrError, Handler, MainnetHandler, - PrecompileProvider, + instructions::InstructionProvider, system_call::SystemCallTx, EthFrame, EvmTr, EvmTrError, + Handler, MainnetHandler, PrecompileProvider, }; use interpreter::{interpreter::EthInterpreter, InterpreterResult}; +use primitives::{Address, Bytes}; use state::EvmState; // Implementing InspectorHandler for MainnetHandler. @@ -57,6 +58,33 @@ where { } +// Implementing InspectSystemCallEvm for Evm +impl InspectSystemCallEvm + for Evm> +where + CTX: ContextSetters + + ContextTr + JournalExt, Tx: SystemCallTx>, + INSP: Inspector, + INST: InstructionProvider, + PRECOMPILES: PrecompileProvider, +{ + fn inspect_one_system_call_with_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result { + // Set system call transaction fields similar to transact_system_call_with_caller + self.set_tx(CTX::Tx::new_system_tx_with_caller( + caller, + system_contract_address, + data, + )); + // Use inspect_run_system_call instead of run_system_call for inspection + MainnetHandler::default().inspect_run_system_call(self) + } +} + // Implementing InspectorEvmTr for Evm impl InspectorEvmTr for Evm> where diff --git a/crates/op-revm/src/api/exec.rs b/crates/op-revm/src/api/exec.rs index 2e8f24b232..204973509e 100644 --- a/crates/op-revm/src/api/exec.rs +++ b/crates/op-revm/src/api/exec.rs @@ -13,7 +13,9 @@ use revm::{ instructions::EthInstructions, system_call::SystemCallEvm, EthFrame, Handler, PrecompileProvider, SystemCallTx, }, - inspector::{InspectCommitEvm, InspectEvm, Inspector, InspectorHandler, JournalExt}, + inspector::{ + InspectCommitEvm, InspectEvm, InspectSystemCallEvm, Inspector, InspectorHandler, JournalExt, + }, interpreter::{interpreter::EthInterpreter, InterpreterResult}, primitives::{Address, Bytes}, state::EvmState, @@ -142,3 +144,26 @@ where h.run_system_call(self) } } + +impl InspectSystemCallEvm + for OpEvm, PRECOMPILE> +where + CTX: OpContextTr + ContextSetters, + INSP: Inspector, + PRECOMPILE: PrecompileProvider, +{ + fn inspect_one_system_call_with_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + ) -> Result { + self.0.ctx.set_tx(CTX::Tx::new_system_tx_with_caller( + caller, + system_contract_address, + data, + )); + let mut h = OpHandler::<_, _, EthFrame>::new(); + h.inspect_run_system_call(self) + } +} diff --git a/crates/op-revm/tests/integration.rs b/crates/op-revm/tests/integration.rs index 088bf5a8cc..52bd9a976a 100644 --- a/crates/op-revm/tests/integration.rs +++ b/crates/op-revm/tests/integration.rs @@ -1075,6 +1075,44 @@ fn test_log_inspector() { compare_or_save_testdata("test_log_inspector.json", &output); } +#[test] +fn test_system_call_inspection() { + use revm::InspectSystemCallEvm; + + let ctx = Context::op(); + + let mut evm = ctx.build_op_with_inspector(LogInspector::default()); + + // Test system call inspection + let result = evm + .inspect_one_system_call(BENCH_TARGET, Bytes::default()) + .unwrap(); + + // Should succeed + assert!(result.is_success()); + + // Test system call inspection with caller + let custom_caller = Address::from([0x12; 20]); + let result = evm + .inspect_one_system_call_with_caller(custom_caller, BENCH_TARGET, Bytes::default()) + .unwrap(); + + // Should also succeed + assert!(result.is_success()); + + // Test system call inspection with inspector + let result = evm + .inspect_one_system_call_with_inspector( + BENCH_TARGET, + Bytes::default(), + LogInspector::default(), + ) + .unwrap(); + + // Should succeed + assert!(result.is_success()); +} + #[test] fn test_system_call() { let ctx = Context::op(); diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 6f4df789fc..759af925ae 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -35,5 +35,5 @@ pub use handler::{ ExecuteCommitEvm, ExecuteEvm, MainBuilder, MainContext, MainnetEvm, SystemCallCommitEvm, SystemCallEvm, }; -pub use inspector::{InspectCommitEvm, InspectEvm, Inspector}; +pub use inspector::{InspectCommitEvm, InspectEvm, InspectSystemCallEvm, Inspector}; pub use precompile::install_crypto; From f2d73c4bc01ada4825b4ac03432a33ea20d7eb97 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 29 Jul 2025 12:36:35 +0200 Subject: [PATCH 23/78] feat: refactor test utils (#2813) * feat: refactor test utils * fix compilation * feat: add ee-test to unify ee tests * sort all json test fixtures * fmt * typo --- Cargo.lock | 16 ++ Cargo.toml | 6 +- crates/ee-tests/Cargo.toml | 25 +++ crates/ee-tests/src/lib.rs | 137 +++++++++++++ .../src/op_revm_tests.rs} | 77 +++++--- .../src/revm_tests.rs} | 47 +++-- .../op_revm_testdata}/test_deposit_tx.json | 30 +-- .../test_halted_deposit_tx.json | 54 +++--- ...all_bls12_381_g1_add_input_wrong_size.json | 132 ++++++------- ...d_tx_call_bls12_381_g1_add_out_of_gas.json | 128 ++++++------ ...all_bls12_381_g1_msm_input_wrong_size.json | 130 ++++++------- ...d_tx_call_bls12_381_g1_msm_out_of_gas.json | 132 ++++++------- ...l_bls12_381_g1_msm_wrong_input_layout.json | 132 ++++++------- ...all_bls12_381_g2_add_input_wrong_size.json | 132 ++++++------- ...d_tx_call_bls12_381_g2_add_out_of_gas.json | 134 ++++++------- ...all_bls12_381_g2_msm_input_wrong_size.json | 128 ++++++------ ...d_tx_call_bls12_381_g2_msm_out_of_gas.json | 134 ++++++------- ...l_bls12_381_g2_msm_wrong_input_layout.json | 132 ++++++------- ...12_381_map_fp2_to_g2_input_wrong_size.json | 130 ++++++------- ...ll_bls12_381_map_fp2_to_g2_out_of_gas.json | 130 ++++++------- ...s12_381_map_fp_to_g1_input_wrong_size.json | 132 ++++++------- ...all_bls12_381_map_fp_to_g1_out_of_gas.json | 130 ++++++------- ...ll_bls12_381_pairing_input_wrong_size.json | 130 ++++++------- ..._tx_call_bls12_381_pairing_out_of_gas.json | 130 ++++++------- ..._bls12_381_pairing_wrong_input_layout.json | 134 ++++++------- .../test_halted_tx_call_bn254_pair_fjord.json | 132 ++++++------- ...est_halted_tx_call_bn254_pair_granite.json | 132 ++++++------- .../test_halted_tx_call_p256verify.json | 130 ++++++------- .../op_revm_testdata}/test_log_inspector.json | 182 +++++++++--------- .../op_revm_testdata}/test_system_call.json | 160 +++++++-------- .../test_tx_call_p256verify.json | 136 ++++++------- .../test_frame_stack_index.json | 6 +- .../revm_testdata}/test_multi_tx_create.json | 132 ++++++------- .../test_selfdestruct_multi_tx.json | 124 ++++++------ crates/ee-tests/tests/testdata/test_data.json | 4 + crates/op-revm/Cargo.toml | 3 +- crates/op-revm/tests/common.rs | 111 ----------- .../op-revm/tests/testdata/template_test.json | 14 -- crates/revm/Cargo.toml | 1 + crates/revm/tests/common.rs | 108 ----------- crates/revm/tests/testdata/template_test.json | 14 -- examples/README.md | 2 +- 42 files changed, 1990 insertions(+), 2023 deletions(-) create mode 100644 crates/ee-tests/Cargo.toml create mode 100644 crates/ee-tests/src/lib.rs rename crates/{op-revm/tests/integration.rs => ee-tests/src/op_revm_tests.rs} (94%) rename crates/{revm/tests/integration.rs => ee-tests/src/revm_tests.rs} (86%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_deposit_tx.json (65%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_deposit_tx.json (62%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_pairing_out_of_gas.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bn254_pair_fjord.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_bn254_pair_granite.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_halted_tx_call_p256verify.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_log_inspector.json (62%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_system_call.json (60%) rename crates/{op-revm/tests/testdata => ee-tests/tests/op_revm_testdata}/test_tx_call_p256verify.json (60%) rename crates/{revm/tests/testdata => ee-tests/tests/revm_testdata}/test_frame_stack_index.json (80%) rename crates/{revm/tests/testdata => ee-tests/tests/revm_testdata}/test_multi_tx_create.json (67%) rename crates/{revm/tests/testdata => ee-tests/tests/revm_testdata}/test_selfdestruct_multi_tx.json (62%) create mode 100644 crates/ee-tests/tests/testdata/test_data.json delete mode 100644 crates/op-revm/tests/common.rs delete mode 100644 crates/op-revm/tests/testdata/template_test.json delete mode 100644 crates/revm/tests/common.rs delete mode 100644 crates/revm/tests/testdata/template_test.json diff --git a/Cargo.lock b/Cargo.lock index 78488c542c..6fb4278897 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3040,6 +3040,7 @@ dependencies = [ "alloy-sol-types", "auto_impl", "revm", + "revm-ee-tests", "rstest", "serde", "serde_json", @@ -3779,6 +3780,7 @@ dependencies = [ "revm-context-interface", "revm-database", "revm-database-interface", + "revm-ee-tests", "revm-handler", "revm-inspector", "revm-interpreter", @@ -3861,6 +3863,20 @@ dependencies = [ "tokio", ] +[[package]] +name = "revm-ee-tests" +version = "0.1.0" +dependencies = [ + "alloy-primitives", + "alloy-sol-types", + "op-revm", + "revm", + "rstest", + "serde", + "serde_json", + "sha2 0.10.9", +] + [[package]] name = "revm-handler" version = "8.1.0" diff --git a/Cargo.toml b/Cargo.toml index 6238be62ec..91b5e3b83e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,6 +22,7 @@ members = [ # utility "crates/statetest-types", + "crates/ee-tests", # examples "examples/block_traces", @@ -54,6 +55,7 @@ context = { path = "crates/context", package = "revm-context", version = "8.0.4" context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "9.0.0", default-features = false } handler = { path = "crates/handler", package = "revm-handler", version = "8.1.0", default-features = false } op-revm = { path = "crates/op-revm", package = "op-revm", version = "8.1.0", default-features = false } +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 } @@ -165,7 +167,9 @@ strip = false # Make sure debug symbols are in the bench profile [profile.bench] -inherits = "profiling" +debug = 2 +inherits = "release" +strip = false [profile.ethtests] inherits = "test" diff --git a/crates/ee-tests/Cargo.toml b/crates/ee-tests/Cargo.toml new file mode 100644 index 0000000000..ad256d1627 --- /dev/null +++ b/crates/ee-tests/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "revm-ee-tests" +version = "0.1.0" +authors = ["revm"] +edition = "2021" +rust-version = "1.80.1" +license = "MIT" +description = "Common test utilities for REVM crates" +repository = "https://github.com/bluealloy/revm" + +[dependencies] +serde = { version = "1.0", features = ["derive"] } +serde_json = { version = "1.0", features = ["preserve_order"] } +revm = { workspace = true, features = ["serde"] } +op-revm = { workspace = true, features = ["serde"] } + +[dev-dependencies] +rstest = { workspace = true } +alloy-sol-types = { workspace = true } +sha2 = { workspace = true } +alloy-primitives = { workspace = true } + +[features] +default = [] +optional_balance_check = ["revm/optional_balance_check", "op-revm/optional_balance_check"] diff --git a/crates/ee-tests/src/lib.rs b/crates/ee-tests/src/lib.rs new file mode 100644 index 0000000000..db3d469d0d --- /dev/null +++ b/crates/ee-tests/src/lib.rs @@ -0,0 +1,137 @@ +//! Common test utilities for REVM crates. +//! +//! This crate provides shared test utilities that are used across different REVM crates. + +use std::path::PathBuf; + +use serde_json::Value; + +/// Configuration for the test data comparison utility. +pub struct TestdataConfig { + /// The directory where test data files are stored. + pub testdata_dir: PathBuf, +} + +impl Default for TestdataConfig { + fn default() -> Self { + Self { + testdata_dir: PathBuf::from("tests/testdata"), + } + } +} + +/// Compares or saves the execution output to a testdata file. +/// +/// This utility helps maintain consistent test behavior by comparing +/// execution results against known-good outputs stored in JSON files. +/// +/// # Arguments +/// +/// * `filename` - The name of the testdata file, relative to tests/testdata/ +/// * `output` - The execution output to compare or save +/// +/// # Panics +/// +/// This function panics if: +/// - The output doesn't match the expected testdata (when testdata file exists) +/// - There's an error reading/writing files +/// - JSON serialization/deserialization fails +/// +/// # Note +/// +/// Tests using this function require the `serde` feature to be enabled: +/// ```bash +/// cargo test --features serde +/// ``` +pub fn compare_or_save_testdata(filename: &str, output: &T) +where + T: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq + std::fmt::Debug, +{ + compare_or_save_testdata_with_config(filename, output, TestdataConfig::default()); +} + +/// Compares or saves the execution output to a testdata file with custom configuration. +/// +/// This is a more flexible version of [`compare_or_save_testdata`] that allows +/// specifying a custom testdata directory. +/// +/// # Arguments +/// +/// * `filename` - The name of the testdata file, relative to the testdata directory +/// * `output` - The execution output to compare or save +/// * `config` - Configuration for the test data comparison +pub fn compare_or_save_testdata_with_config(filename: &str, output: &T, config: TestdataConfig) +where + T: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq + std::fmt::Debug, +{ + use std::fs; + + let testdata_file = config.testdata_dir.join(filename); + + // Create directory if it doesn't exist + if !config.testdata_dir.exists() { + fs::create_dir_all(&config.testdata_dir).unwrap(); + } + + // Serialize the output to serde Value. + let output_json = serde_json::to_string(&output).unwrap(); + + // convert to Value and sort all objects. + let mut temp: Value = serde_json::from_str(&output_json).unwrap(); + temp.sort_all_objects(); + + // serialize to pretty string + let output_json = serde_json::to_string_pretty(&temp).unwrap(); + + // If the testdata file doesn't exist, save the output + if !testdata_file.exists() { + fs::write(&testdata_file, &output_json).unwrap(); + println!("Saved testdata to {}", testdata_file.display()); + return; + } + + // Read the expected output from the testdata file + let expected_json = fs::read_to_string(&testdata_file).unwrap(); + + // Deserialize to actual object for proper comparison + let expected: T = serde_json::from_str(&expected_json).unwrap(); + + // Compare the output objects directly + if *output != expected { + // If they don't match, generate a nicer error by pretty-printing both as JSON + // This helps with debugging by showing the exact differences + let expected_pretty = serde_json::to_string_pretty(&expected).unwrap(); + + panic!( + "Value does not match testdata.\nExpected:\n{expected_pretty}\n\nActual:\n{output_json}" + ); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)] + struct TestData { + value: u32, + message: String, + } + + #[test] + fn test_compare_or_save_testdata() { + let test_data = TestData { + value: 42, + message: "test message".to_string(), + }; + + // This will save the test data on first run, then compare on subsequent runs + compare_or_save_testdata("test_data.json", &test_data); + } +} + +#[cfg(test)] +mod op_revm_tests; + +#[cfg(test)] +mod revm_tests; diff --git a/crates/op-revm/tests/integration.rs b/crates/ee-tests/src/op_revm_tests.rs similarity index 94% rename from crates/op-revm/tests/integration.rs rename to crates/ee-tests/src/op_revm_tests.rs index 52bd9a976a..fa0c6b1244 100644 --- a/crates/op-revm/tests/integration.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -1,8 +1,6 @@ //! Integration tests for the `op-revm` crate. -mod common; -use alloy_primitives::bytes; -use common::compare_or_save_testdata; +use crate::TestdataConfig; use op_revm::{ precompiles::bn254_pair::GRANITE_MAX_INPUT_SIZE, DefaultOp, L1BlockInfo, OpBuilder, OpHaltReason, OpSpecId, OpTransaction, @@ -15,18 +13,35 @@ use revm::{ }, context_interface::result::HaltReason, database::{BenchmarkDB, EmptyDB, 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::{eip7825, Address, Bytes, Log, TxKind, U256}, + primitives::{bytes, eip7825, Address, Bytes, Log, TxKind, U256}, state::Bytecode, - Context, ExecuteEvm, InspectEvm, Inspector, Journal, + Context, ExecuteEvm, InspectEvm, Inspector, Journal, SystemCallEvm, }; -use revm::{handler::system_call::SYSTEM_ADDRESS, SystemCallEvm}; +use std::path::PathBuf; use std::vec::Vec; +// Re-export the constant for testdata directory path +const TESTS_TESTDATA: &str = "tests/op_revm_testdata"; + +fn op_revm_testdata_config() -> TestdataConfig { + TestdataConfig { + testdata_dir: PathBuf::from(TESTS_TESTDATA), + } +} + +fn compare_or_save_op_testdata(filename: &str, output: &T) +where + T: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq + std::fmt::Debug, +{ + crate::compare_or_save_testdata_with_config(filename, output, op_revm_testdata_config()); +} + #[test] fn test_deposit_tx() { let ctx = Context::op() @@ -51,7 +66,7 @@ fn test_deposit_tx() { .map(|a| a.info.balance), Some(U256::from(100)) ); - compare_or_save_testdata("test_deposit_tx.json", &output); + compare_or_save_op_testdata("test_deposit_tx.json", &output); } #[test] @@ -92,7 +107,7 @@ fn test_halted_deposit_tx() { Some(U256::from(100) + BENCH_CALLER_BALANCE) ); - compare_or_save_testdata("test_halted_deposit_tx.json", &output); + compare_or_save_op_testdata("test_halted_deposit_tx.json", &output); } fn p256verify_test_tx( @@ -126,7 +141,7 @@ fn test_tx_call_p256verify() { // assert successful call to P256VERIFY assert!(output.result.is_success()); - compare_or_save_testdata("test_tx_call_p256verify.json", &output); + compare_or_save_op_testdata("test_tx_call_p256verify.json", &output); } #[test] @@ -160,7 +175,7 @@ fn test_halted_tx_call_p256verify() { } )); - compare_or_save_testdata("test_halted_tx_call_p256verify.json", &output); + compare_or_save_op_testdata("test_halted_tx_call_p256verify.json", &output); } fn bn254_pair_test_tx( @@ -201,7 +216,7 @@ fn test_halted_tx_call_bn254_pair_fjord() { } )); - compare_or_save_testdata("test_halted_tx_call_bn254_pair_fjord.json", &output); + compare_or_save_op_testdata("test_halted_tx_call_bn254_pair_fjord.json", &output); } #[test] @@ -220,7 +235,7 @@ fn test_halted_tx_call_bn254_pair_granite() { } )); - compare_or_save_testdata("test_halted_tx_call_bn254_pair_granite.json", &output); + compare_or_save_op_testdata("test_halted_tx_call_bn254_pair_granite.json", &output); } #[test] @@ -254,7 +269,7 @@ fn test_halted_tx_call_bls12_381_g1_add_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g1_add_out_of_gas.json", &output, ); @@ -290,7 +305,7 @@ fn test_halted_tx_call_bls12_381_g1_add_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json", &output, ); @@ -369,7 +384,7 @@ fn test_halted_tx_call_bls12_381_g1_msm_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json", &output, ); @@ -416,7 +431,7 @@ fn test_halted_tx_call_bls12_381_g1_msm_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json", &output, ); @@ -438,7 +453,7 @@ fn test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json", &output, ); @@ -475,7 +490,7 @@ fn test_halted_tx_call_bls12_381_g2_add_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g2_add_out_of_gas.json", &output, ); @@ -512,7 +527,7 @@ fn test_halted_tx_call_bls12_381_g2_add_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json", &output, ); @@ -591,7 +606,7 @@ fn test_halted_tx_call_bls12_381_g2_msm_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json", &output, ); @@ -638,7 +653,7 @@ fn test_halted_tx_call_bls12_381_g2_msm_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json", &output, ); @@ -660,7 +675,7 @@ fn test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json", &output, ); @@ -734,7 +749,7 @@ fn test_halted_tx_call_bls12_381_pairing_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_pairing_input_wrong_size.json", &output, ); @@ -778,7 +793,7 @@ fn test_halted_tx_call_bls12_381_pairing_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_pairing_out_of_gas.json", &output, ); @@ -800,7 +815,7 @@ fn test_tx_call_bls12_381_pairing_wrong_input_layout() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json", &output, ); @@ -842,7 +857,7 @@ fn test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json", &output, ); @@ -884,7 +899,7 @@ fn test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json", &output, ); @@ -926,7 +941,7 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json", &output, ); @@ -968,7 +983,7 @@ fn test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size() { } )); - compare_or_save_testdata( + compare_or_save_op_testdata( "test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json", &output, ); @@ -1072,7 +1087,7 @@ fn test_log_inspector() { let inspector = &evm.0.inspector; assert!(!inspector.logs.is_empty()); - compare_or_save_testdata("test_log_inspector.json", &output); + compare_or_save_op_testdata("test_log_inspector.json", &output); } #[test] @@ -1125,5 +1140,5 @@ fn test_system_call() { // Run evm. let output = evm.replay().unwrap(); - compare_or_save_testdata("test_system_call.json", &output); + compare_or_save_op_testdata("test_system_call.json", &output); } diff --git a/crates/revm/tests/integration.rs b/crates/ee-tests/src/revm_tests.rs similarity index 86% rename from crates/revm/tests/integration.rs rename to crates/ee-tests/src/revm_tests.rs index 4aa41ce0c2..8758052a36 100644 --- a/crates/revm/tests/integration.rs +++ b/crates/ee-tests/src/revm_tests.rs @@ -1,19 +1,31 @@ -//! Integration tests for the `op-revm` crate. -mod common; +//! Integration tests for the `revm` crate. -use common::compare_or_save_testdata; -use context::ContextTr; -use database::BENCH_CALLER; -use primitives::{address, b256, hardfork::SpecId, Bytes, TxKind, KECCAK_EMPTY}; +use crate::TestdataConfig; use revm::{ bytecode::opcode, - context::TxEnv, - database::{BenchmarkDB, BENCH_TARGET}, - primitives::U256, - state::Bytecode, + context::{ContextTr, TxEnv}, + database::{BenchmarkDB, BENCH_CALLER, BENCH_TARGET}, + primitives::{address, b256, hardfork::SpecId, Bytes, TxKind, KECCAK_EMPTY, U256}, + state::{AccountStatus, Bytecode}, Context, ExecuteEvm, MainBuilder, MainContext, }; -use state::AccountStatus; +use std::path::PathBuf; + +// Re-export the constant for testdata directory path +const TESTS_TESTDATA: &str = "tests/revm_testdata"; + +fn revm_testdata_config() -> TestdataConfig { + TestdataConfig { + testdata_dir: PathBuf::from(TESTS_TESTDATA), + } +} + +fn compare_or_save_revm_testdata(filename: &str, output: &T) +where + T: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq + std::fmt::Debug, +{ + crate::compare_or_save_testdata_with_config(filename, output, revm_testdata_config()); +} const SELFDESTRUCT_BYTECODE: &[u8] = &[ opcode::PUSH2, @@ -60,9 +72,9 @@ fn test_selfdestruct_multi_tx() { let output = evm.finalize(); - compare_or_save_testdata( + compare_or_save_revm_testdata( "test_selfdestruct_multi_tx.json", - (result1, result2, output), + &(result1, result2, output), ); } @@ -171,9 +183,9 @@ pub fn test_multi_tx_create() { ); let output = evm.finalize(); - compare_or_save_testdata( + compare_or_save_revm_testdata( "test_multi_tx_create.json", - (result1, result2, result3, output), + &(result1, result2, result3, output), ); } @@ -221,14 +233,13 @@ fn test_frame_stack_index() { .unwrap(); assert_eq!(evm.frame_stack.index(), None); - compare_or_save_testdata("test_frame_stack_index.json", result1); + compare_or_save_revm_testdata("test_frame_stack_index.json", &result1); } #[test] #[cfg(feature = "optional_balance_check")] fn test_disable_balance_check() { - use database::BENCH_CALLER_BALANCE; - + use revm::database::BENCH_CALLER_BALANCE; const RETURN_CALLER_BALANCE_BYTECODE: &[u8] = &[ opcode::CALLER, opcode::BALANCE, diff --git a/crates/op-revm/tests/testdata/test_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json similarity index 65% rename from crates/op-revm/tests/testdata/test_deposit_tx.json rename to crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json index c187d50833..ce989e10db 100644 --- a/crates/op-revm/tests/testdata/test_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_deposit_tx.json @@ -1,40 +1,40 @@ { "result": { "Success": { - "reason": "Stop", - "gas_used": 21000, "gas_refunded": 0, + "gas_used": 21000, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "Stop" } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x64", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/testdata/test_halted_deposit_tx.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json similarity index 62% rename from crates/op-revm/tests/testdata/test_halted_deposit_tx.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json index 8aac2ceb88..0769dd9c2f 100644 --- a/crates/op-revm/tests/testdata/test_halted_deposit_tx.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_deposit_tx.json @@ -1,62 +1,62 @@ { "result": { "Halt": { - "reason": "FailedDeposit", - "gas_used": 16777216 + "gas_used": 16777216, + "reason": "FailedDeposit" } }, "state": { "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { "info": { "balance": "0x2386f26fc10064", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched", "storage": {}, - "status": "Touched" + "transaction_id": 0 }, "0xffffffffffffffffffffffffffffffffffffffff": { "info": { "balance": "0x2386f26fc10000", - "nonce": 1, - "code_hash": "0x7b2ab94bb7d45041581aa3757ae020084674ccad6f75dc3750eb2ea8a92c4e9a", "code": { "LegacyAnalyzed": { "bytecode": "0x5000", - "original_len": 1, "jump_table": { - "order": "bitvec::order::Lsb0", - "head": { - "width": 8, - "index": 0 - }, "bits": 1, "data": [ 0 - ] - } + ], + "head": { + "index": 0, + "width": 8 + }, + "order": "bitvec::order::Lsb0" + }, + "original_len": 1 } - } + }, + "code_hash": "0x7b2ab94bb7d45041581aa3757ae020084674ccad6f75dc3750eb2ea8a92c4e9a", + "nonce": 1 }, - "transaction_id": 0, + "status": "Cold", "storage": {}, - "status": "Cold" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_input_wrong_size.json index 5b5fc6861b..91cea8ca54 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 21375, "reason": { "Base": "PrecompileError" - }, - "gas_used": 21375 + } } }, "state": { - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x000000000000000000000000000000000000000b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x000000000000000000000000000000000000000b": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_add_out_of_gas.json index 5690b09303..4d1f78ca80 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 21374, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 21374 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x000000000000000000000000000000000000000b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_input_wrong_size.json index 109343782b..5fdee80453 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 35560, "reason": { "Base": "PrecompileError" - }, - "gas_used": 35560 + } } }, "state": { - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x000000000000000000000000000000000000000c": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_out_of_gas.json index 38d133784c..d2a41cfed6 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 35559, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 35559 + } } }, "state": { - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x000000000000000000000000000000000000000c": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x000000000000000000000000000000000000000c": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g1_msm_wrong_input_layout.json index 83fd20ba23..5fdee80453 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 35560, "reason": { "Base": "PrecompileError" - }, - "gas_used": 35560 + } } }, "state": { - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x000000000000000000000000000000000000000c": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_input_wrong_size.json index 9b58339aba..b2970ea9cb 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 21600, "reason": { "Base": "PrecompileError" - }, - "gas_used": 21600 + } } }, "state": { - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x000000000000000000000000000000000000000d": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_add_out_of_gas.json index 31d7f31de0..c050e75ec1 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 21599, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 21599 + } } }, "state": { - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x000000000000000000000000000000000000000d": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x000000000000000000000000000000000000000d": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_input_wrong_size.json index d22cb09181..4ef0718ec2 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 48108, "reason": { "Base": "PrecompileError" - }, - "gas_used": 48108 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x000000000000000000000000000000000000000e": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x000000000000000000000000000000000000000e": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_out_of_gas.json index 60ab39f58c..59b81d7b5e 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 48107, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 48107 + } } }, "state": { - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x000000000000000000000000000000000000000e": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x000000000000000000000000000000000000000e": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_g2_msm_wrong_input_layout.json index 48c1006554..4ef0718ec2 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 48108, "reason": { "Base": "PrecompileError" - }, - "gas_used": 48108 + } } }, "state": { - "0x000000000000000000000000000000000000000e": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x000000000000000000000000000000000000000e": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_input_wrong_size.json index 3e00f925e8..311e0b6a77 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 46848, "reason": { "Base": "PrecompileError" - }, - "gas_used": 46848 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000011": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000011": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp2_to_g2_out_of_gas.json index 9152806db6..4e12839026 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 46847, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 46847 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000011": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000011": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_input_wrong_size.json index db93c13ab6..1b768b6653 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 27524, "reason": { "Base": "PrecompileError" - }, - "gas_used": 27524 + } } }, "state": { - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x0000000000000000000000000000000000000010": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000010": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_map_fp_to_g1_out_of_gas.json index 11a64278d3..cc66059ecf 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 27523, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 27523 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000010": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000010": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_input_wrong_size.json index 001577b3a3..b650e8b8f1 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 97444, "reason": { "Base": "PrecompileError" - }, - "gas_used": 97444 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x000000000000000000000000000000000000000f": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_out_of_gas.json index 628f248bd2..e3ecc1304f 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 97443, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 97443 + } } }, "state": { - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x000000000000000000000000000000000000000f": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bls12_381_pairing_wrong_input_layout.json index a7245cc245..b650e8b8f1 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 97444, "reason": { "Base": "PrecompileError" - }, - "gas_used": 97444 + } } }, "state": { - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x000000000000000000000000000000000000000f": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x000000000000000000000000000000000000000f": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_fjord.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_fjord.json index 03f0c8e0fc..4f98b9d9ad 100644 --- a/crates/op-revm/tests/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 @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 1824024, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 1824024 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000008": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000008": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/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 similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_bn254_pair_granite.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_bn254_pair_granite.json index f05d9a8269..85591e9afa 100644 --- a/crates/op-revm/tests/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 @@ -1,137 +1,137 @@ { "result": { "Halt": { + "gas_used": 1824024, "reason": { "Base": "PrecompileError" - }, - "gas_used": 1824024 + } } }, "state": { - "0x420000000000000000000000000000000000001a": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x0000000000000000000000000000000000000008": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/testdata/test_halted_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json similarity index 60% rename from crates/op-revm/tests/testdata/test_halted_tx_call_p256verify.json rename to crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json index 98a205f483..a21e7ce5e3 100644 --- a/crates/op-revm/tests/testdata/test_halted_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_halted_tx_call_p256verify.json @@ -1,139 +1,139 @@ { "result": { "Halt": { + "gas_used": 24449, "reason": { "Base": { "OutOfGas": "Precompile" } - }, - "gas_used": 24449 + } } }, "state": { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, "0x0000000000000000000000000000000000000100": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "LoadedAsNotExisting", "storage": {}, - "status": "LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/testdata/test_log_inspector.json b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json similarity index 62% rename from crates/op-revm/tests/testdata/test_log_inspector.json rename to crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json index 04fbaf3a18..145505a365 100644 --- a/crates/op-revm/tests/testdata/test_log_inspector.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_log_inspector.json @@ -1,173 +1,173 @@ { "result": { "Success": { - "reason": "Stop", - "gas_used": 21381, "gas_refunded": 0, + "gas_used": 21381, "logs": [ { "address": "0xffffffffffffffffffffffffffffffffffffffff", - "topics": [], - "data": "0x" + "data": "0x", + "topics": [] } ], "output": { "Call": "0x" - } + }, + "reason": "Stop" } }, "state": { - "0xffffffffffffffffffffffffffffffffffffffff": { + "0x0000000000000000000000000000000000000000": { "info": { - "balance": "0x2386f26fc10000", - "nonce": 1, - "code_hash": "0x8013c386d5a03c3fa0a6ccbfefcf7d91471dedba2bb94eefef57f916e5929a8d", + "balance": "0x0", "code": { "LegacyAnalyzed": { - "bytecode": "0x600080a000", - "original_len": 5, + "bytecode": "0x00", "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 5, - "data": [ - 0 - ] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched" + "transaction_id": 0 }, - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { + "0x4200000000000000000000000000000000000019": { "info": { - "balance": "0x2386f26fc10000", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x0", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001b": { + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { "info": { - "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x2386f26fc10000", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0xffffffffffffffffffffffffffffffffffffffff": { "info": { - "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x2386f26fc10000", "code": { "LegacyAnalyzed": { - "bytecode": "0x00", - "original_len": 0, + "bytecode": "0x600080a000", "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 5, + "data": [ + 0 + ], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 5 } - } + }, + "code_hash": "0x8013c386d5a03c3fa0a6ccbfefcf7d91471dedba2bb94eefef57f916e5929a8d", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/testdata/test_system_call.json b/crates/ee-tests/tests/op_revm_testdata/test_system_call.json similarity index 60% rename from crates/op-revm/tests/testdata/test_system_call.json rename to crates/ee-tests/tests/op_revm_testdata/test_system_call.json index c45ac37cc0..eb8f4e1a10 100644 --- a/crates/op-revm/tests/testdata/test_system_call.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_system_call.json @@ -1,165 +1,165 @@ { "result": { "Success": { - "reason": "Stop", - "gas_used": 21020, "gas_refunded": 0, + "gas_used": 21020, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "Stop" } }, "state": { - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 }, "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 }, - "0xfffffffffffffffffffffffffffffffffffffffe": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 }, - "0xffffffffffffffffffffffffffffffffffffffff": { + "0xfffffffffffffffffffffffffffffffffffffffe": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 }, - "0x420000000000000000000000000000000000001a": { + "0xffffffffffffffffffffffffffffffffffffffff": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 } } } \ No newline at end of file diff --git a/crates/op-revm/tests/testdata/test_tx_call_p256verify.json b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json similarity index 60% rename from crates/op-revm/tests/testdata/test_tx_call_p256verify.json rename to crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json index edca703816..87cdf23853 100644 --- a/crates/op-revm/tests/testdata/test_tx_call_p256verify.json +++ b/crates/ee-tests/tests/op_revm_testdata/test_tx_call_p256verify.json @@ -1,140 +1,140 @@ { "result": { "Success": { - "reason": "Return", - "gas_used": 24450, "gas_refunded": 0, + "gas_used": 24450, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "Return" } }, "state": { - "0x420000000000000000000000000000000000001b": { + "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x4200000000000000000000000000000000000019": { + "0x0000000000000000000000000000000000000100": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x420000000000000000000000000000000000001a": { + "0x4200000000000000000000000000000000000019": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0x420000000000000000000000000000000000001a": { "info": { "balance": "0x0", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000100": { + "0x420000000000000000000000000000000000001b": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 0 } } } \ No newline at end of file diff --git a/crates/revm/tests/testdata/test_frame_stack_index.json b/crates/ee-tests/tests/revm_testdata/test_frame_stack_index.json similarity index 80% rename from crates/revm/tests/testdata/test_frame_stack_index.json rename to crates/ee-tests/tests/revm_testdata/test_frame_stack_index.json index c5981e4b93..5d69c4ffbb 100644 --- a/crates/revm/tests/testdata/test_frame_stack_index.json +++ b/crates/ee-tests/tests/revm_testdata/test_frame_stack_index.json @@ -1,11 +1,11 @@ { "Success": { - "reason": "Stop", - "gas_used": 21000, "gas_refunded": 0, + "gas_used": 21000, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "Stop" } } \ No newline at end of file diff --git a/crates/revm/tests/testdata/test_multi_tx_create.json b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json similarity index 67% rename from crates/revm/tests/testdata/test_multi_tx_create.json rename to crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json index 10d184d7de..60cff1e58f 100644 --- a/crates/revm/tests/testdata/test_multi_tx_create.json +++ b/crates/ee-tests/tests/revm_testdata/test_multi_tx_create.json @@ -1,145 +1,145 @@ [ { "Success": { - "reason": "Return", - "gas_used": 54260, "gas_refunded": 0, + "gas_used": 54260, "logs": [], "output": { "Create": [ "0x61ffffff00", "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2" ] - } + }, + "reason": "Return" } }, { "Success": { - "reason": "SelfDestruct", - "gas_used": 14302, "gas_refunded": 14301, + "gas_used": 14302, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "SelfDestruct" } }, { "Success": { - "reason": "Return", - "gas_used": 54260, "gas_refunded": 0, + "gas_used": 54260, "logs": [], "output": { "Create": [ "0x61ffffff00", "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2" ] - } + }, + "reason": "Return" } }, { "0x0000000000000000000000000000000000000000": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 2, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 2 }, - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { + "0x000000000000000000000000000000000000ffff": { "info": { - "balance": "0x2386f26fc10000", - "nonce": 1, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x0", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 2, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched" + "transaction_id": 1 }, - "0x000000000000000000000000000000000000ffff": { + "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2": { "info": { "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", "code": { "LegacyAnalyzed": { - "bytecode": "0x00", - "original_len": 0, + "bytecode": "0x61ffffff00", "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 5, + "data": [ + 0 + ], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 5 } - } + }, + "code_hash": "0x9125466aa9ef15459d85e7318f6d3bdc5f6978c0565bee37a8e768d7c202a67a", + "nonce": 1 }, - "transaction_id": 1, + "status": "Created | CreatedLocal | SelfDestructed | Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 2 }, - "0x84bcbaa99ae6d1f7f70b37d5f6c27c9631eeb2f2": { + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { "info": { - "balance": "0x0", - "nonce": 1, - "code_hash": "0x9125466aa9ef15459d85e7318f6d3bdc5f6978c0565bee37a8e768d7c202a67a", + "balance": "0x2386f26fc10000", "code": { "LegacyAnalyzed": { - "bytecode": "0x61ffffff00", - "original_len": 5, + "bytecode": "0x00", "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 5, - "data": [ - 0 - ] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 1 }, - "transaction_id": 2, + "status": "Touched", "storage": {}, - "status": "Created | CreatedLocal | SelfDestructed | Touched | LoadedAsNotExisting" + "transaction_id": 2 } } ] \ No newline at end of file diff --git a/crates/revm/tests/testdata/test_selfdestruct_multi_tx.json b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json similarity index 62% rename from crates/revm/tests/testdata/test_selfdestruct_multi_tx.json rename to crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json index 3db1e8eec5..ccc0fe6dd4 100644 --- a/crates/revm/tests/testdata/test_selfdestruct_multi_tx.json +++ b/crates/ee-tests/tests/revm_testdata/test_selfdestruct_multi_tx.json @@ -1,126 +1,126 @@ [ { "Success": { - "reason": "SelfDestruct", - "gas_used": 29603, "gas_refunded": 24000, + "gas_used": 29603, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "SelfDestruct" } }, { "Success": { - "reason": "Stop", - "gas_used": 21000, "gas_refunded": 0, + "gas_used": 21000, "logs": [], "output": { "Call": "0x" - } + }, + "reason": "Stop" } }, { - "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { + "0x0000000000000000000000000000000000000000": { "info": { - "balance": "0x2386f26fc10000", - "nonce": 2, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x0", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "Touched" + "transaction_id": 1 }, - "0xffffffffffffffffffffffffffffffffffffffff": { + "0x000000000000000000000000000000000000ffff": { "info": { - "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x2386f26fc10000", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 1, + "status": "Touched | LoadedAsNotExisting", "storage": {}, - "status": "SelfDestructed | Touched" + "transaction_id": 0 }, - "0x0000000000000000000000000000000000000000": { + "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee": { "info": { - "balance": "0x0", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x2386f26fc10000", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 2 }, - "transaction_id": 1, + "status": "Touched", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 }, - "0x000000000000000000000000000000000000ffff": { + "0xffffffffffffffffffffffffffffffffffffffff": { "info": { - "balance": "0x2386f26fc10000", - "nonce": 0, - "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "balance": "0x0", "code": { "LegacyAnalyzed": { "bytecode": "0x00", - "original_len": 0, "jump_table": { - "order": "bitvec::order::Lsb0", + "bits": 0, + "data": [], "head": { - "width": 8, - "index": 0 + "index": 0, + "width": 8 }, - "bits": 0, - "data": [] - } + "order": "bitvec::order::Lsb0" + }, + "original_len": 0 } - } + }, + "code_hash": "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", + "nonce": 0 }, - "transaction_id": 0, + "status": "SelfDestructed | Touched", "storage": {}, - "status": "Touched | LoadedAsNotExisting" + "transaction_id": 1 } } ] \ No newline at end of file diff --git a/crates/ee-tests/tests/testdata/test_data.json b/crates/ee-tests/tests/testdata/test_data.json new file mode 100644 index 0000000000..7798031b53 --- /dev/null +++ b/crates/ee-tests/tests/testdata/test_data.json @@ -0,0 +1,4 @@ +{ + "message": "test message", + "value": 42 +} \ No newline at end of file diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index cd359e6f6f..5035af78be 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -30,8 +30,9 @@ rstest.workspace = true alloy-sol-types.workspace = true sha2.workspace = true serde_json = { workspace = true, features = ["alloc", "preserve_order"] } -alloy-primitives.workspace = true serde = { workspace = true, features = ["derive"] } +alloy-primitives.workspace = true +ee-tests.workspace = true [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst"] diff --git a/crates/op-revm/tests/common.rs b/crates/op-revm/tests/common.rs deleted file mode 100644 index bca6e97ec5..0000000000 --- a/crates/op-revm/tests/common.rs +++ /dev/null @@ -1,111 +0,0 @@ -//! Common test utilities used to compare execution results against testdata. -#![allow(dead_code)] - -use revm::{ - context::result::ResultAndState, - context_interface::result::{ExecutionResult, HaltReason, Output, SuccessReason}, - primitives::Bytes, - state::EvmState, -}; - -// Constant for testdata directory path -pub(crate) const TESTS_TESTDATA: &str = "tests/testdata"; - -#[cfg(not(feature = "serde"))] -pub(crate) fn compare_or_save_testdata( - _filename: &str, - _output: &ResultAndState, -) { - // serde needs to be enabled to use this function -} - -/// Compares or saves the execution output to a testdata file. -/// -/// This utility helps maintain consistent test behavior by comparing -/// execution results against known-good outputs stored in JSON files. -/// -/// # Arguments -/// -/// * `filename` - The name of the testdata file, relative to tests/testdata/ -/// * `output` - The execution output to compare or save -/// -/// # Returns -/// -/// `Ok(())` if the comparison or save was successful -/// `Err(anyhow::Error)` if there was an error -/// -/// # Note -/// -/// Tests using this function require the `serde` feature to be enabled: -/// ```bash -/// cargo test --features serde -/// ``` -#[cfg(feature = "serde")] -pub(crate) fn compare_or_save_testdata( - filename: &str, - output: &ResultAndState, -) where - HaltReasonTy: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq, -{ - use std::{fs, path::PathBuf}; - - let tests_dir = PathBuf::from(TESTS_TESTDATA); - let testdata_file = tests_dir.join(filename); - - // Create directory if it doesn't exist - if !tests_dir.exists() { - fs::create_dir_all(&tests_dir).unwrap(); - } - - // Serialize the output to JSON for saving - let output_json = serde_json::to_string_pretty(output).unwrap(); - - // If the testdata file doesn't exist, save the output - if !testdata_file.exists() { - fs::write(&testdata_file, &output_json).unwrap(); - println!("Saved testdata to {}", testdata_file.display()); - return; - } - - // Read the expected output from the testdata file - let expected_json = fs::read_to_string(&testdata_file).unwrap(); - - // Deserialize to actual ResultAndState object for proper comparison - let expected = serde_json::from_str(&expected_json).unwrap(); - - // Compare the output objects directly - if output != &expected { - // If they don't match, generate a nicer error by pretty-printing both as JSON - // This helps with debugging by showing the exact differences - let expected_pretty = serde_json::to_string_pretty(&expected).unwrap(); - - panic!( - "Value does not match testdata.\nExpected:\n{expected_pretty}\n\nActual:\n{output_json}", - ); - } -} - -/// Example showing how to migrate an existing test to use the testdata comparison. -/// -/// This example consists of: -/// 1. The "original" test with standard assertions -/// 2. The migration approach - running assertions and saving testdata -/// 3. The final migrated test that only uses testdata comparison -#[test] -fn template_test() { - // Create a minimal result and state - let result = ResultAndState::new( - ExecutionResult::Success { - reason: SuccessReason::Stop, - gas_used: 1000, - gas_refunded: 0, - logs: vec![], - output: Output::Call(Bytes::from(vec![4, 5, 6])), - }, - EvmState::default(), - ); - - // Simply use the testdata comparison utility - // No assertions needed - full validation is done by comparing with testdata - compare_or_save_testdata::("template_test.json", &result); -} diff --git a/crates/op-revm/tests/testdata/template_test.json b/crates/op-revm/tests/testdata/template_test.json deleted file mode 100644 index 5c35711ddd..0000000000 --- a/crates/op-revm/tests/testdata/template_test.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "result": { - "Success": { - "reason": "Stop", - "gas_used": 1000, - "gas_refunded": 0, - "logs": [], - "output": { - "Call": "0x040506" - } - } - }, - "state": {} -} \ No newline at end of file diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 6849bbf4d0..4ae1f7aff1 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -34,6 +34,7 @@ state.workspace = true [dev-dependencies] serde_json = { workspace = true, features = ["alloc", "preserve_order"] } serde = { workspace = true, features = ["derive"] } +ee-tests.workspace = true [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst", "tracer"] diff --git a/crates/revm/tests/common.rs b/crates/revm/tests/common.rs deleted file mode 100644 index c3a909de08..0000000000 --- a/crates/revm/tests/common.rs +++ /dev/null @@ -1,108 +0,0 @@ -//! Common test utilities used to compare execution results against testdata. -#![allow(dead_code)] - -use revm::{ - context::result::ResultAndState, - context_interface::result::{ExecutionResult, HaltReason, Output, SuccessReason}, - primitives::Bytes, - state::EvmState, -}; - -// Constant for testdata directory path -pub(crate) const TESTS_TESTDATA: &str = "tests/testdata"; - -#[cfg(not(feature = "serde"))] -pub(crate) fn compare_or_save_testdata(_filename: &str, _output: I) { - // serde needs to be enabled to use this function -} - -/// Compares or saves the execution output to a testdata file. -/// -/// This utility helps maintain consistent test behavior by comparing -/// execution results against known-good outputs stored in JSON files. -/// -/// # Arguments -/// -/// * `filename` - The name of the testdata file, relative to tests/testdata/ -/// * `output` - The execution output to compare or save -/// -/// # Returns -/// -/// `Ok(())` if the comparison or save was successful -/// `Err(anyhow::Error)` if there was an error -/// -/// # Note -/// -/// Tests using this function require the `serde` feature to be enabled: -/// ```bash -/// cargo test --features serde -/// ``` -#[cfg(feature = "serde")] -pub(crate) fn compare_or_save_testdata< - I: serde::Serialize + for<'a> serde::Deserialize<'a> + PartialEq, ->( - filename: &str, - output: I, -) { - use std::{fs, path::PathBuf}; - - let tests_dir = PathBuf::from(TESTS_TESTDATA); - let testdata_file = tests_dir.join(filename); - - // Create directory if it doesn't exist - if !tests_dir.exists() { - fs::create_dir_all(&tests_dir).unwrap(); - } - - // Serialize the output to JSON for saving - let output_json = serde_json::to_string_pretty(&output).unwrap(); - - // If the testdata file doesn't exist, save the output - if !testdata_file.exists() { - fs::write(&testdata_file, &output_json).unwrap(); - println!("Saved testdata to {}", testdata_file.display()); - return; - } - - // Read the expected output from the testdata file - let expected_json = fs::read_to_string(&testdata_file).unwrap(); - - // Deserialize to actual ResultAndState object for proper comparison - let expected = serde_json::from_str(&expected_json).unwrap(); - - // Compare the output objects directly - if output != expected { - // If they don't match, generate a nicer error by pretty-printing both as JSON - // This helps with debugging by showing the exact differences - let expected_pretty = serde_json::to_string_pretty(&expected).unwrap(); - - panic!( - "Value does not match testdata.\nExpected:\n{expected_pretty}\n\nActual:\n{output_json}" - ); - } -} - -/// Example showing how to migrate an existing test to use the testdata comparison. -/// -/// This example consists of: -/// 1. The "original" test with standard assertions -/// 2. The migration approach - running assertions and saving testdata -/// 3. The final migrated test that only uses testdata comparison -#[test] -fn template_test() { - // Create a minimal result and state - let result = ResultAndState::new( - ExecutionResult::::Success { - reason: SuccessReason::Stop, - gas_used: 1000, - gas_refunded: 0, - logs: vec![], - output: Output::Call(Bytes::from(vec![4, 5, 6])), - }, - EvmState::default(), - ); - - // Simply use the testdata comparison utility - // No assertions needed - full validation is done by comparing with testdata - compare_or_save_testdata("template_test.json", result); -} diff --git a/crates/revm/tests/testdata/template_test.json b/crates/revm/tests/testdata/template_test.json deleted file mode 100644 index 5c35711ddd..0000000000 --- a/crates/revm/tests/testdata/template_test.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "result": { - "Success": { - "reason": "Stop", - "gas_used": 1000, - "gas_refunded": 0, - "logs": [], - "output": { - "Call": "0x040506" - } - } - }, - "state": {} -} \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index d33d5093e3..ade2b456ed 100644 --- a/examples/README.md +++ b/examples/README.md @@ -6,4 +6,4 @@ * `uniswap_v2_usdc_swap`: Similar to `uniswap_get_reserves` with more examples of usage. * `block_traces`: Uses Alloy to fetch blocks transaction and state from provider to execute full block. It uses Eip3155 opcode tracer and saves output to the file. * `custom_opcodes`: Example of introducing a custom instruction to the mainnet Evm. -* `database_components`: Example of decouples Database in `State` and `BlockHash` and how to use it inside Revm. \ No newline at end of file +* `database_components`: Example of decoupled Database in `State` and `BlockHash` and how to use it inside Revm. \ No newline at end of file From df467931c4b1b8b620ff2cb9f62501c7abc3ea03 Mon Sep 17 00:00:00 2001 From: Emilia Hane Date: Tue, 29 Jul 2025 17:44:23 +0200 Subject: [PATCH 24/78] test(op-revm): Adds caller nonce assertion to op-revm intergation tests (#2815) * Adds handler test for verifying unchanged nonce on balance too low revert * Fix system call test * fixup! Fix merge conflicts --- crates/ee-tests/src/op_revm_tests.rs | 10 ++++----- crates/op-revm/src/handler.rs | 33 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index fa0c6b1244..a48dd2aedb 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -1134,11 +1134,9 @@ fn test_system_call() { let mut evm = ctx.build_op(); - evm.system_call_one(SYSTEM_ADDRESS, BENCH_TARGET, bytes!("0x0001")) - .unwrap(); - - // Run evm. - let output = evm.replay().unwrap(); + let _ = evm.system_call_one(SYSTEM_ADDRESS, BENCH_TARGET, bytes!("0x0001")); + let state = evm.finalize(); - compare_or_save_op_testdata("test_system_call.json", &output); + assert!(state.get(&SYSTEM_ADDRESS).is_none()); + assert!(state.get(&BENCH_TARGET).unwrap().is_touched()); } diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index 4d4a6d00ec..f00414ec50 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -1109,4 +1109,37 @@ mod tests { let account = evm.ctx().journal_mut().load_account(SENDER).unwrap(); assert_eq!(account.info.balance, expected_refund); } + + #[test] + fn test_tx_low_balance_nonce_unchanged() { + let ctx = Context::op().with_tx( + OpTransaction::builder() + .base(TxEnv::builder().value(U256::from(1000))) + .build_fill(), + ); + + let mut evm = ctx.build_op(); + + let handler = + OpHandler::<_, EVMError<_, OpTransactionError>, EthFrame>::new(); + + let result = handler.validate_against_state_and_deduct_caller(&mut evm); + + assert!(matches!( + result.err().unwrap(), + EVMError::Transaction(OpTransactionError::Base( + InvalidTransaction::LackOfFundForMaxFee { .. } + )) + )); + assert_eq!( + evm.0 + .ctx + .journal_mut() + .load_account(Address::ZERO) + .unwrap() + .info + .nonce, + 0 + ); + } } From ee6e7cd58a373b6b1591a29a4309daa3b0824ca7 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 30 Jul 2025 13:46:37 +0200 Subject: [PATCH 25/78] feat: fix renamed functions for system_call (#2824) --- MIGRATION_GUIDE.md | 6 +++ crates/ee-tests/src/op_revm_tests.rs | 2 +- crates/handler/src/system_call.rs | 76 ++++++++++++++++------------ crates/inspector/src/inspect.rs | 34 +++++++++++++ crates/op-revm/src/api/exec.rs | 2 +- 5 files changed, 87 insertions(+), 33 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index d1bb31cd23..0b4d7184db 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,3 +1,9 @@ +# v83 tag (revm v28.0.0) from v82 tag (revm v27.1.0) + +* `SystemCallEvm` functions got renamed and old ones are deprecated. Renaming is done to align it with other API calls. + * `transact_system_call_finalize` is now `system_call`. + * `transact_system_call` is now `system_call_one`. + # v82 tag (revm v27.1.0) from v81 tag (revm v27.0.3) * `ContextTr` gained `Host` supertrait. diff --git a/crates/ee-tests/src/op_revm_tests.rs b/crates/ee-tests/src/op_revm_tests.rs index a48dd2aedb..45d566dd3d 100644 --- a/crates/ee-tests/src/op_revm_tests.rs +++ b/crates/ee-tests/src/op_revm_tests.rs @@ -1134,7 +1134,7 @@ fn test_system_call() { let mut evm = ctx.build_op(); - let _ = evm.system_call_one(SYSTEM_ADDRESS, BENCH_TARGET, bytes!("0x0001")); + let _ = evm.system_call_one(BENCH_TARGET, bytes!("0x0001")); let state = evm.finalize(); assert!(state.get(&SYSTEM_ADDRESS).is_none()); diff --git a/crates/handler/src/system_call.rs b/crates/handler/src/system_call.rs index dc7a01b5fa..d4ce748ee5 100644 --- a/crates/handler/src/system_call.rs +++ b/crates/handler/src/system_call.rs @@ -72,6 +72,11 @@ impl SystemCallTx for TxEnv { /// beneficiary. They are used before and after block execution to insert or obtain blockchain state. /// /// It act similar to `transact` function and sets default Tx with data and system contract as a target. +/// +/// # Note +/// +/// Only one function needs implementation [`SystemCallEvm::system_call_one_with_caller`], other functions +/// are derived from it. pub trait SystemCallEvm: ExecuteEvm { /// System call is a special transaction call that is used to call a system contract. /// @@ -79,7 +84,7 @@ pub trait SystemCallEvm: ExecuteEvm { /// given values. /// /// Block values are taken into account and will determent how system call will be executed. - fn system_call_one( + fn system_call_one_with_caller( &mut self, caller: Address, system_contract_address: Address, @@ -92,62 +97,71 @@ pub trait SystemCallEvm: ExecuteEvm { /// given values. /// /// Block values are taken into account and will determent how system call will be executed. - #[deprecated(since = "0.1.0", note = "Use `system_call_one` instead")] - fn transact_system_call_with_caller( + fn system_call_one( &mut self, - caller: Address, system_contract_address: Address, data: Bytes, ) -> Result { - self.system_call_one(caller, system_contract_address, data) + self.system_call_one_with_caller(SYSTEM_ADDRESS, system_contract_address, data) } - /// Calls [`SystemCallEvm::system_call_one`] with [`SYSTEM_ADDRESS`] as a caller. - #[deprecated( - since = "0.1.0", - note = "Use `system_call_one` with SYSTEM_ADDRESS instead" - )] - fn transact_system_call( + /// Internally calls [`SystemCallEvm::system_call_with_caller`]. + fn system_call( &mut self, system_contract_address: Address, data: Bytes, - ) -> Result { - self.system_call_one(SYSTEM_ADDRESS, system_contract_address, data) + ) -> Result, Self::Error> { + self.system_call_with_caller(SYSTEM_ADDRESS, system_contract_address, data) } - /// Transact the system call and finalize. - /// - /// Internally calls combo of `system_call_one` and `finalize` functions. - fn system_call( + /// Internally calls [`SystemCallEvm::system_call_one`] and [`ExecuteEvm::finalize`] functions to obtain the changed state. + fn system_call_with_caller( &mut self, + caller: Address, system_contract_address: Address, data: Bytes, ) -> Result, Self::Error> { - self.system_call_with_caller(SYSTEM_ADDRESS, system_contract_address, data) + let result = self.system_call_one_with_caller(caller, system_contract_address, data)?; + let state = self.finalize(); + Ok(ExecResultAndState::new(result, state)) } - /// Transact the system call and finalize. + /// System call is a special transaction call that is used to call a system contract. /// - /// Internally calls combo of `transact_system_call` and `finalize` functions. - #[deprecated(since = "0.1.0", note = "Use `system_call` instead")] - fn transact_system_call_finalize( + /// Transaction fields are reset and set in [`SystemCallTx`] and data and target are set to + /// given values. + /// + /// Block values are taken into account and will determent how system call will be executed. + #[deprecated(since = "0.1.0", note = "Use `system_call_one_with_caller` instead")] + fn transact_system_call_with_caller( &mut self, + caller: Address, system_contract_address: Address, data: Bytes, - ) -> Result, Self::Error> { - self.system_call(system_contract_address, data) + ) -> Result { + self.system_call_one_with_caller(caller, system_contract_address, data) } - /// Calls [`SystemCallEvm::system_call_one`] and `finalize` functions. - fn system_call_with_caller( + /// Calls [`SystemCallEvm::system_call_one`] with [`SYSTEM_ADDRESS`] as a caller. + #[deprecated(since = "0.1.0", note = "Use `system_call_one` instead")] + fn transact_system_call( + &mut self, + system_contract_address: Address, + data: Bytes, + ) -> Result { + self.system_call_one(system_contract_address, data) + } + + /// Transact the system call and finalize. + /// + /// Internally calls combo of `transact_system_call` and `finalize` functions. + #[deprecated(since = "0.1.0", note = "Use `system_call` instead")] + fn transact_system_call_finalize( &mut self, - caller: Address, system_contract_address: Address, data: Bytes, ) -> Result, Self::Error> { - let result = self.system_call_one(caller, system_contract_address, data)?; - let state = self.finalize(); - Ok(ExecResultAndState::new(result, state)) + self.system_call(system_contract_address, data) } /// Calls [`SystemCallEvm::system_call_one`] and `finalize` functions. @@ -210,7 +224,7 @@ where INST: InstructionProvider, PRECOMPILES: PrecompileProvider, { - fn system_call_one( + fn system_call_one_with_caller( &mut self, caller: Address, system_contract_address: Address, diff --git a/crates/inspector/src/inspect.rs b/crates/inspector/src/inspect.rs index 79beb2c6b8..2036108b9c 100644 --- a/crates/inspector/src/inspect.rs +++ b/crates/inspector/src/inspect.rs @@ -161,4 +161,38 @@ pub trait InspectSystemCallEvm: InspectEvm + SystemCallEvm { let state = self.finalize(); Ok(ExecResultAndState::new(output, state)) } + + /// Inspect a system call with a given inspector and caller. + /// + /// Similar to [`InspectEvm::inspect_one`] but for system calls. + fn inspect_one_system_call_with_inspector_and_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + inspector: Self::Inspector, + ) -> Result { + self.set_inspector(inspector); + self.inspect_one_system_call_with_caller(caller, system_contract_address, data) + } + + /// Inspect a system call with a given inspector and finalize the state. + /// + /// Similar to [`InspectEvm::inspect`] but for system calls. + fn inspect_system_call_with_inspector_and_caller( + &mut self, + caller: Address, + system_contract_address: Address, + data: Bytes, + inspector: Self::Inspector, + ) -> Result, Self::Error> { + let output = self.inspect_one_system_call_with_inspector_and_caller( + caller, + system_contract_address, + data, + inspector, + )?; + let state = self.finalize(); + Ok(ExecResultAndState::new(output, state)) + } } diff --git a/crates/op-revm/src/api/exec.rs b/crates/op-revm/src/api/exec.rs index 204973509e..9c460bdcac 100644 --- a/crates/op-revm/src/api/exec.rs +++ b/crates/op-revm/src/api/exec.rs @@ -129,7 +129,7 @@ where CTX: OpContextTr + ContextSetters, PRECOMPILE: PrecompileProvider, { - fn system_call_one( + fn system_call_one_with_caller( &mut self, caller: Address, system_contract_address: Address, From 5f67c14ab9402ef896a725c348187c34afde5201 Mon Sep 17 00:00:00 2001 From: Pratham Agarwal <32198580+Pratham1812@users.noreply.github.com> Date: Wed, 30 Jul 2025 17:18:34 +0530 Subject: [PATCH 26/78] feat: removed padding in case last opcode is terminating or unknown (#2816) * feat: removed padding in case last opcode is terminating or unknown * fix: clippy lint error * fix: fmt error * feat: refactored the functions * feat: added assert statement to check for terminating opcodes * feat: added test to check last bytecode byte is terminating --- crates/bytecode/src/legacy/analysis.rs | 27 ++++++++++++++++++++++- crates/bytecode/src/legacy/analyzed.rs | 30 +++++++++++++++----------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/crates/bytecode/src/legacy/analysis.rs b/crates/bytecode/src/legacy/analysis.rs index 193b188642..1ead1c478a 100644 --- a/crates/bytecode/src/legacy/analysis.rs +++ b/crates/bytecode/src/legacy/analysis.rs @@ -39,7 +39,14 @@ pub fn analyze_legacy(bytecode: Bytes) -> (JumpTable, Bytes) { } } - let padding = (iterator as usize) - (end as usize) + (opcode != opcode::STOP) as usize; + let overflow_padding = (iterator as usize) - (end as usize); + + let stop_padding = opcode::OpCode::info_by_op(opcode) + .map(|o| !o.is_terminating() as usize) + .unwrap_or(1); + + let padding = overflow_padding + stop_padding; + let bytecode = if padding > 0 { let mut padded = Vec::with_capacity(bytecode.len() + padding); padded.extend_from_slice(&bytecode); @@ -173,4 +180,22 @@ mod tests { let (jump_table, _) = analyze_legacy(bytecode.clone().into()); assert!(!jump_table.is_valid(1)); // JUMPDEST in push data should not be valid } + + #[test] + fn test_terminating_opcodes_behavior() { + // Test all known terminating opcodes + let terminating_opcodes = [ + opcode::STOP, + opcode::RETURN, + opcode::REVERT, + opcode::INVALID, + opcode::SELFDESTRUCT, + ]; + + for &terminating_opcode in &terminating_opcodes { + let bytecode = vec![opcode::PUSH1, 0x01, terminating_opcode]; + let (_, padded_bytecode) = analyze_legacy(bytecode.clone().into()); + assert_eq!(padded_bytecode.len(), bytecode.len()); + } + } } diff --git a/crates/bytecode/src/legacy/analyzed.rs b/crates/bytecode/src/legacy/analyzed.rs index 295ec20baf..7c29214b8d 100644 --- a/crates/bytecode/src/legacy/analyzed.rs +++ b/crates/bytecode/src/legacy/analyzed.rs @@ -77,10 +77,16 @@ impl LegacyAnalyzedBytecode { "jump table length is less than original length" ); assert!(!bytecode.is_empty(), "bytecode cannot be empty"); - assert!( - bytecode.last() == Some(&opcode::STOP), - "last bytecode byte should be STOP (0x00)" - ); + + if let Some(&last_opcode) = bytecode.last() { + assert!( + opcode::OpCode::info_by_op(last_opcode) + .map(|o| o.is_terminating()) + .unwrap_or(false), + "last bytecode byte should be terminating" + ); + } + Self { bytecode, original_len, @@ -150,14 +156,6 @@ mod tests { let _ = LegacyAnalyzedBytecode::new(bytecode.bytecode, bytecode.original_len, jump_table); } - #[test] - #[should_panic(expected = "last bytecode byte should be STOP (0x00)")] - fn test_panic_on_non_stop_bytecode() { - let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]); - let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 2]); - let _ = LegacyAnalyzedBytecode::new(bytecode, 2, jump_table); - } - #[test] #[should_panic(expected = "bytecode cannot be empty")] fn test_panic_on_empty_bytecode() { @@ -165,4 +163,12 @@ mod tests { let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 0]); let _ = LegacyAnalyzedBytecode::new(bytecode, 0, jump_table); } + + #[test] + #[should_panic(expected = "last bytecode byte should be terminating")] + fn test_panic_on_non_stop_bytecode() { + let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]); + let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 2]); + let _ = LegacyAnalyzedBytecode::new(bytecode, 2, jump_table); + } } From 6e1e3f458a980e3e21c991ce0d02f67780b13437 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 30 Jul 2025 22:00:07 +0200 Subject: [PATCH 27/78] chore: improve ExtBytecode hash handling (#2826) - Currently in foundry we check for None OR hash==zero to check if it's unset. Use `None` in all cases. - Provide a helper for `get_or_insert_with()` that calculates the hash if unset. --- crates/bytecode/src/bytecode.rs | 4 ++ crates/handler/src/frame.rs | 8 ++-- .../src/interpreter/ext_bytecode.rs | 44 +++++++++++++++---- .../src/interpreter/ext_bytecode/serde.rs | 23 +++++----- 4 files changed, 54 insertions(+), 25 deletions(-) diff --git a/crates/bytecode/src/bytecode.rs b/crates/bytecode/src/bytecode.rs index b9e8a697c2..b3095d3678 100644 --- a/crates/bytecode/src/bytecode.rs +++ b/crates/bytecode/src/bytecode.rs @@ -45,6 +45,7 @@ impl Bytecode { } /// Calculates hash of the bytecode. + #[inline] pub fn hash_slow(&self) -> B256 { if self.is_empty() { KECCAK_EMPTY @@ -54,6 +55,7 @@ impl Bytecode { } /// Returns `true` if bytecode is EIP-7702. + #[inline] pub const fn is_eip7702(&self) -> bool { matches!(self, Self::Eip7702(_)) } @@ -100,6 +102,7 @@ impl Bytecode { /// # Panics /// /// For possible panics see [`LegacyAnalyzedBytecode::new`]. + #[inline] pub fn new_analyzed(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self { Self::LegacyAnalyzed(LegacyAnalyzedBytecode::new( bytecode, @@ -118,6 +121,7 @@ impl Bytecode { } /// Pointer to the executable bytecode. + #[inline] pub fn bytecode_ptr(&self) -> *const u8 { self.bytecode().as_ptr() } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index c645811dbc..56416f08d0 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -25,7 +25,7 @@ use primitives::{ constants::CALL_STACK_LIMIT, hardfork::SpecId::{self, HOMESTEAD, LONDON, SPURIOUS_DRAGON}, }; -use primitives::{keccak256, Address, Bytes, B256, U256}; +use primitives::{keccak256, Address, Bytes, U256}; use state::Bytecode; use std::borrow::ToOwned; use std::boxed::Box; @@ -308,11 +308,11 @@ impl EthFrame { .nonce_bump_journal_entry(inputs.caller); // Create address - let mut init_code_hash = B256::ZERO; + let mut init_code_hash = None; let created_address = match inputs.scheme { CreateScheme::Create => inputs.caller.create(old_nonce), CreateScheme::Create2 { salt } => { - init_code_hash = keccak256(&inputs.init_code); + 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, @@ -332,7 +332,7 @@ impl EthFrame { Err(e) => return return_error(e.into()), }; - let bytecode = ExtBytecode::new_with_hash( + let bytecode = ExtBytecode::new_with_optional_hash( Bytecode::new_legacy(inputs.init_code.clone()), init_code_hash, ); diff --git a/crates/interpreter/src/interpreter/ext_bytecode.rs b/crates/interpreter/src/interpreter/ext_bytecode.rs index 2a0be8f1f9..f3e4faf962 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode.rs @@ -10,6 +10,9 @@ mod serde; /// Extended bytecode structure that wraps base bytecode with additional execution metadata. #[derive(Debug)] pub struct ExtBytecode { + /// Bytecode Keccak-256 hash. + /// This is `None` if it hasn't been calculated yet. + /// Since it's not necessary for execution, it's not calculated by default. bytecode_hash: Option, /// Actions that the EVM should do. It contains return value of the Interpreter or inputs for `CALL` or `CREATE` instructions. /// For `RETURN` or `REVERT` instructions it contains the result of the instruction. @@ -38,41 +41,64 @@ impl Default for ExtBytecode { impl ExtBytecode { /// Create new extended bytecode and set the instruction pointer to the start of the bytecode. + /// + /// The bytecode hash will not be calculated. #[inline] pub fn new(base: Bytecode) -> Self { - let instruction_pointer = base.bytecode_ptr(); - Self { - base, - instruction_pointer, - bytecode_hash: None, - action: None, - has_set_action: false, - } + Self::new_with_optional_hash(base, None) } /// Creates new `ExtBytecode` with the given hash. + #[inline] pub fn new_with_hash(base: Bytecode, hash: B256) -> Self { + Self::new_with_optional_hash(base, Some(hash)) + } + + /// Creates new `ExtBytecode` with the given hash. + #[inline] + pub fn new_with_optional_hash(base: Bytecode, hash: Option) -> Self { let instruction_pointer = base.bytecode_ptr(); Self { base, instruction_pointer, - bytecode_hash: Some(hash), + bytecode_hash: hash, action: None, has_set_action: false, } } /// Regenerates the bytecode hash. + #[inline] + #[deprecated(note = "use `get_or_calculate_hash` or `calculate_hash` instead")] + #[doc(hidden)] pub fn regenerate_hash(&mut self) -> B256 { + self.calculate_hash() + } + + /// Re-calculates the bytecode hash. + /// + /// Prefer [`get_or_calculate_hash`](Self::get_or_calculate_hash) if you just need to get the hash. + #[inline] + pub fn calculate_hash(&mut self) -> B256 { let hash = self.base.hash_slow(); self.bytecode_hash = Some(hash); hash } /// Returns the bytecode hash. + #[inline] pub fn hash(&mut self) -> Option { self.bytecode_hash } + + /// Returns the bytecode hash or calculates it if it is not set. + #[inline] + pub fn get_or_calculate_hash(&mut self) -> B256 { + *self.bytecode_hash.get_or_insert_with( + #[cold] + || self.base.hash_slow(), + ) + } } impl LoopControl for ExtBytecode { diff --git a/crates/interpreter/src/interpreter/ext_bytecode/serde.rs b/crates/interpreter/src/interpreter/ext_bytecode/serde.rs index c627200912..8c5457e361 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode/serde.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode/serde.rs @@ -2,10 +2,12 @@ use super::ExtBytecode; use crate::interpreter::Jumps; use primitives::B256; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::borrow::Cow; +use std::format; #[derive(Serialize, Deserialize)] -struct ExtBytecodeSerde { - base: bytecode::Bytecode, +struct ExtBytecodeSerde<'a> { + base: Cow<'a, bytecode::Bytecode>, program_counter: usize, bytecode_hash: Option, } @@ -16,7 +18,7 @@ impl Serialize for ExtBytecode { S: Serializer, { ExtBytecodeSerde { - base: self.base.clone(), + base: Cow::Borrowed(&self.base), program_counter: self.pc(), bytecode_hash: self.bytecode_hash, } @@ -34,15 +36,12 @@ impl<'de> Deserialize<'de> for ExtBytecode { program_counter, bytecode_hash, } = ExtBytecodeSerde::deserialize(deserializer)?; - - let mut bytecode = if let Some(hash) = bytecode_hash { - Self::new_with_hash(base, hash) - } else { - Self::new(base) - }; - - if program_counter >= bytecode.base.bytecode().len() { - panic!("serde pc: {program_counter} is greater than or equal to bytecode len"); + let mut bytecode = Self::new_with_optional_hash(base.into_owned(), bytecode_hash); + let len = bytecode.base.bytecode().len(); + if program_counter >= len { + return Err(serde::de::Error::custom(format!( + "program counter ({program_counter}) exceeds bytecode length ({len})" + ))); } bytecode.absolute_jump(program_counter); Ok(bytecode) From 3ad31163f9fcbcc194db3ed9ac4fc28b822f5848 Mon Sep 17 00:00:00 2001 From: kevaundray Date: Thu, 31 Jul 2025 23:09:30 +0100 Subject: [PATCH 28/78] feat: Reuse bls12-381 codepaths to implement kzg point evaluation precompile (#2809) * initial code * fix: cfg * add blst * one function for pairing * make arkworks look like blst * cleanup, reuse fn from blst/arkwork, fix kzg blst scalar check. Enable kzg * doc links * nit cleanup --- bins/revme/Cargo.toml | 2 +- crates/precompile/Cargo.toml | 5 +- crates/precompile/src/bls12_381.rs | 4 +- crates/precompile/src/bls12_381/arkworks.rs | 25 ++- crates/precompile/src/bls12_381/blst.rs | 18 +- crates/precompile/src/bls12_381_const.rs | 8 +- crates/precompile/src/bn254.rs | 4 +- crates/precompile/src/bn254/arkworks.rs | 1 + crates/precompile/src/interface.rs | 1 - crates/precompile/src/kzg_point_evaluation.rs | 71 ++++--- .../src/kzg_point_evaluation/arkworks.rs | 135 +++++++++++++ .../src/kzg_point_evaluation/blst.rs | 181 ++++++++++++++++++ crates/precompile/src/lib.rs | 17 +- crates/revm/Cargo.toml | 6 +- 14 files changed, 405 insertions(+), 73 deletions(-) create mode 100644 crates/precompile/src/kzg_point_evaluation/arkworks.rs create mode 100644 crates/precompile/src/kzg_point_evaluation/blst.rs diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index d35a1bc3d2..fa17cd696b 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -11,7 +11,7 @@ rust-version.workspace = true [dependencies] # revm -revm = { workspace = true, features = ["std", "c-kzg", "blst", "hashbrown"] } +revm = { workspace = true, features = ["std", "hashbrown", "c-kzg", "blst"] } primitives.workspace = true database.workspace = true database-interface.workspace = true diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index e84b8f53fd..9b87997d90 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -79,7 +79,7 @@ ark-std = { workspace = true } rstest.workspace = true [features] -default = ["std", "c-kzg", "secp256k1", "portable", "blst"] +default = ["std", "secp256k1", "blst", "c-kzg", "portable"] std = [ "primitives/std", "k256/std", @@ -102,9 +102,8 @@ hashbrown = ["primitives/hashbrown"] asm-keccak = ["primitives/asm-keccak"] asm-sha2 = ["sha2/asm"] -# These libraries may not work on all no_std platforms as they depend on C. -# Enables the KZG point evaluation precompile. +# Enables the c-kzg point evaluation precompile. Enabled by default as most stable/used implementation. c-kzg = ["dep:c-kzg"] # `kzg-rs` is not audited but useful for `no_std` environment, use it with causing and default to `c-kzg` if possible. kzg-rs = ["dep:kzg-rs"] diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs index 5695c8cb77..8e04a6c05b 100644 --- a/crates/precompile/src/bls12_381.rs +++ b/crates/precompile/src/bls12_381.rs @@ -2,12 +2,14 @@ //! For more details check modules for each precompile. use crate::PrecompileWithAddress; +#[allow(dead_code)] +pub(crate) mod arkworks; + cfg_if::cfg_if! { if #[cfg(feature = "blst")]{ pub(crate) mod blst; pub(crate) use blst as crypto_backend; } else { - pub(crate) mod arkworks; pub(crate) use arkworks as crypto_backend; } } diff --git a/crates/precompile/src/bls12_381/arkworks.rs b/crates/precompile/src/bls12_381/arkworks.rs index f557457b7c..4ca5573cbd 100644 --- a/crates/precompile/src/bls12_381/arkworks.rs +++ b/crates/precompile/src/bls12_381/arkworks.rs @@ -1,3 +1,4 @@ +//! BLS12-381 precompile using Arkworks BLS12-381 implementation. use super::{G1Point, G2Point, PairingPair}; use crate::{ bls12_381_const::{FP_LENGTH, G1_LENGTH, G2_LENGTH, SCALAR_LENGTH}, @@ -347,7 +348,7 @@ fn map_fp2_to_g2(fp2: &Fq2) -> G2Affine { /// pairing_check performs a pairing check on a list of G1 and G2 point pairs and /// returns true if the result is equal to the identity element. #[inline] -fn pairing_check(pairs: &[(G1Affine, G2Affine)]) -> bool { +pub(crate) fn pairing_check(pairs: &[(G1Affine, G2Affine)]) -> bool { if pairs.is_empty() { return true; } @@ -360,7 +361,7 @@ 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 fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { +pub(crate) fn pairing_check_bytes(pairs: &[PairingPair]) -> Result { if pairs.is_empty() { return Ok(true); } @@ -405,7 +406,10 @@ pub fn pairing_check_bytes(pairs: &[PairingPair]) -> Result Result<[u8; G1_LENGTH], PrecompileError> { +pub(crate) fn p1_add_affine_bytes( + a: G1Point, + b: G1Point, +) -> Result<[u8; G1_LENGTH], PrecompileError> { let (a_x, a_y) = a; let (b_x, b_y) = b; // Parse first point @@ -423,7 +427,10 @@ pub fn p1_add_affine_bytes(a: G1Point, b: G1Point) -> Result<[u8; G1_LENGTH], Pr /// Performs point addition on two G2 points taking byte coordinates. #[inline] -pub fn p2_add_affine_bytes(a: G2Point, b: G2Point) -> Result<[u8; G2_LENGTH], PrecompileError> { +pub(crate) fn p2_add_affine_bytes( + a: G2Point, + b: G2Point, +) -> Result<[u8; G2_LENGTH], PrecompileError> { let (a_x_0, a_x_1, a_y_0, a_y_1) = a; let (b_x_0, b_x_1, b_y_0, b_y_1) = b; // Parse first point @@ -441,7 +448,9 @@ pub fn p2_add_affine_bytes(a: G2Point, b: G2Point) -> Result<[u8; G2_LENGTH], Pr /// Maps a field element to a G1 point from bytes #[inline] -pub fn map_fp_to_g1_bytes(fp_bytes: &[u8; FP_LENGTH]) -> Result<[u8; G1_LENGTH], PrecompileError> { +pub(crate) fn map_fp_to_g1_bytes( + fp_bytes: &[u8; FP_LENGTH], +) -> Result<[u8; G1_LENGTH], PrecompileError> { let fp = read_fp(fp_bytes)?; let result = map_fp_to_g1(&fp); Ok(encode_g1_point(&result)) @@ -449,7 +458,7 @@ pub fn map_fp_to_g1_bytes(fp_bytes: &[u8; FP_LENGTH]) -> Result<[u8; G1_LENGTH], /// Maps field elements to a G2 point from bytes #[inline] -pub fn map_fp2_to_g2_bytes( +pub(crate) fn map_fp2_to_g2_bytes( fp2_x: &[u8; FP_LENGTH], fp2_y: &[u8; FP_LENGTH], ) -> Result<[u8; G2_LENGTH], PrecompileError> { @@ -460,7 +469,7 @@ pub fn map_fp2_to_g2_bytes( /// Performs multi-scalar multiplication (MSM) for G1 points taking byte inputs. #[inline] -pub fn p1_msm_bytes( +pub(crate) fn p1_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G1_LENGTH], PrecompileError> { let mut g1_points = Vec::new(); @@ -497,7 +506,7 @@ pub fn p1_msm_bytes( /// Performs multi-scalar multiplication (MSM) for G2 points taking byte inputs. #[inline] -pub fn p2_msm_bytes( +pub(crate) fn p2_msm_bytes( point_scalar_pairs: impl Iterator>, ) -> Result<[u8; G2_LENGTH], PrecompileError> { let mut g2_points = Vec::new(); diff --git a/crates/precompile/src/bls12_381/blst.rs b/crates/precompile/src/bls12_381/blst.rs index 83dfb282f6..747c695f4a 100644 --- a/crates/precompile/src/bls12_381/blst.rs +++ b/crates/precompile/src/bls12_381/blst.rs @@ -25,7 +25,7 @@ const MODULUS_REPR: [u8; 48] = [ ]; #[inline] -fn p1_to_affine(p: &blst_p1) -> blst_p1_affine { +pub(crate) fn p1_to_affine(p: &blst_p1) -> blst_p1_affine { let mut p_affine = blst_p1_affine::default(); // SAFETY: both inputs are valid blst types unsafe { blst_p1_to_affine(&mut p_affine, p) }; @@ -33,7 +33,7 @@ fn p1_to_affine(p: &blst_p1) -> blst_p1_affine { } #[inline] -fn p1_from_affine(p_affine: &blst_p1_affine) -> blst_p1 { +pub(crate) fn p1_from_affine(p_affine: &blst_p1_affine) -> blst_p1 { let mut p = blst_p1::default(); // SAFETY: both inputs are valid blst types unsafe { blst_p1_from_affine(&mut p, p_affine) }; @@ -41,7 +41,7 @@ fn p1_from_affine(p_affine: &blst_p1_affine) -> blst_p1 { } #[inline] -fn p1_add_or_double(p: &blst_p1, p_affine: &blst_p1_affine) -> blst_p1 { +pub(crate) fn p1_add_or_double(p: &blst_p1, p_affine: &blst_p1_affine) -> blst_p1 { let mut result = blst_p1::default(); // SAFETY: all inputs are valid blst types unsafe { blst_p1_add_or_double_affine(&mut result, p, p_affine) }; @@ -49,7 +49,7 @@ fn p1_add_or_double(p: &blst_p1, p_affine: &blst_p1_affine) -> blst_p1 { } #[inline] -fn p2_to_affine(p: &blst_p2) -> blst_p2_affine { +pub(crate) fn p2_to_affine(p: &blst_p2) -> blst_p2_affine { let mut p_affine = blst_p2_affine::default(); // SAFETY: both inputs are valid blst types unsafe { blst_p2_to_affine(&mut p_affine, p) }; @@ -57,7 +57,7 @@ fn p2_to_affine(p: &blst_p2) -> blst_p2_affine { } #[inline] -fn p2_from_affine(p_affine: &blst_p2_affine) -> blst_p2 { +pub(crate) fn p2_from_affine(p_affine: &blst_p2_affine) -> blst_p2 { let mut p = blst_p2::default(); // SAFETY: both inputs are valid blst types unsafe { blst_p2_from_affine(&mut p, p_affine) }; @@ -65,7 +65,7 @@ fn p2_from_affine(p_affine: &blst_p2_affine) -> blst_p2 { } #[inline] -fn p2_add_or_double(p: &blst_p2, p_affine: &blst_p2_affine) -> blst_p2 { +pub(crate) fn p2_add_or_double(p: &blst_p2, p_affine: &blst_p2_affine) -> blst_p2 { let mut result = blst_p2::default(); // SAFETY: all inputs are valid blst types unsafe { blst_p2_add_or_double_affine(&mut result, p, p_affine) }; @@ -108,7 +108,7 @@ fn p2_add_affine(a: &blst_p2_affine, b: &blst_p2_affine) -> blst_p2_affine { /// /// Note: The scalar is expected to be in Big Endian format. #[inline] -fn p1_scalar_mul(p: &blst_p1_affine, scalar: &blst_scalar) -> blst_p1_affine { +pub(crate) fn p1_scalar_mul(p: &blst_p1_affine, scalar: &blst_scalar) -> blst_p1_affine { // Convert point to Jacobian coordinates let p_jacobian = p1_from_affine(p); @@ -135,7 +135,7 @@ fn p1_scalar_mul(p: &blst_p1_affine, scalar: &blst_scalar) -> blst_p1_affine { /// /// Note: The scalar is expected to be in Big Endian format. #[inline] -fn p2_scalar_mul(p: &blst_p2_affine, scalar: &blst_scalar) -> blst_p2_affine { +pub(crate) fn p2_scalar_mul(p: &blst_p2_affine, scalar: &blst_scalar) -> blst_p2_affine { // Convert point to Jacobian coordinates let p_jacobian = p2_from_affine(p); @@ -308,7 +308,7 @@ fn is_fp12_one(f: &blst_fp12) -> bool { /// pairing_check performs a pairing check on a list of G1 and G2 point pairs and /// returns true if the result is equal to the identity element. #[inline] -fn pairing_check(pairs: &[(blst_p1_affine, blst_p2_affine)]) -> bool { +pub(crate) fn pairing_check(pairs: &[(blst_p1_affine, blst_p2_affine)]) -> bool { // When no inputs are given, we return true // This case can only trigger, if the initial pairing components // all had, either the G1 element as the point at infinity diff --git a/crates/precompile/src/bls12_381_const.rs b/crates/precompile/src/bls12_381_const.rs index 9898aac258..8fc92bcb1a 100644 --- a/crates/precompile/src/bls12_381_const.rs +++ b/crates/precompile/src/bls12_381_const.rs @@ -1,7 +1,7 @@ //! Constants specifying the precompile addresses for each precompile in EIP-2537 use crate::u64_to_address; -use primitives::Address; +use primitives::{hex, Address}; /// G1 add precompile address pub const G1_ADD_ADDRESS: Address = u64_to_address(0x0b); @@ -182,6 +182,12 @@ pub const PAIRING_INPUT_LENGTH: usize = PADDED_G1_LENGTH + PADDED_G2_LENGTH; /// Note: This should be equal to PADDED_FP_LENGTH - FP_LENGTH. pub const FP_PAD_BY: usize = 16; +/// The trusted setup G2 point `[τ]₂` from the Ethereum KZG ceremony (compressed format) +/// Taken from: +pub const TRUSTED_SETUP_TAU_G2_BYTES: [u8; 96] = hex!( + "b5bfd7dd8cdeb128843bc287230af38926187075cbfbefa81009a2ce615ac53d2914e5870cb452d2afaaab24f3499f72185cbfee53492714734429b7b38608e23926c911cceceac9a36851477ba4c60b087041de621000edc98edada20c1def2" + ); + #[test] fn check_discount_table_invariant_holds() { // Currently EIP-2537 specifies the cost for a G1/G2 scalar multiplication in two places diff --git a/crates/precompile/src/bn254.rs b/crates/precompile/src/bn254.rs index 035b25caf3..5663c9b917 100644 --- a/crates/precompile/src/bn254.rs +++ b/crates/precompile/src/bn254.rs @@ -6,12 +6,14 @@ use crate::{ }; use std::vec::Vec; +#[allow(dead_code)] +pub mod arkworks; + cfg_if::cfg_if! { if #[cfg(feature = "bn")]{ pub(crate) mod substrate; pub(crate) use substrate as crypto_backend; } else { - pub(crate) mod arkworks; pub(crate) use arkworks as crypto_backend; } } diff --git a/crates/precompile/src/bn254/arkworks.rs b/crates/precompile/src/bn254/arkworks.rs index 1572ad3786..676968d6af 100644 --- a/crates/precompile/src/bn254/arkworks.rs +++ b/crates/precompile/src/bn254/arkworks.rs @@ -1,3 +1,4 @@ +//! BN128 precompile using Arkworks BLS12-381 implementation. use super::{FQ2_LEN, FQ_LEN, G1_LEN, SCALAR_LEN}; use crate::PrecompileError; use std::vec::Vec; diff --git a/crates/precompile/src/interface.rs b/crates/precompile/src/interface.rs index f9a5b77163..cac543fffd 100644 --- a/crates/precompile/src/interface.rs +++ b/crates/precompile/src/interface.rs @@ -137,7 +137,6 @@ pub trait Crypto: Send + Sync + Debug { } /// KZG point evaluation. - #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] #[inline] fn verify_kzg_proof( &self, diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index b0a656e40f..bc78dd932d 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -3,13 +3,11 @@ use crate::{ crypto, Address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, }; -cfg_if::cfg_if! { - if #[cfg(feature = "c-kzg")] { - use c_kzg::{Bytes32, Bytes48}; - } else if #[cfg(feature = "kzg-rs")] { - use kzg_rs::{Bytes32, Bytes48, KzgProof}; - } -} +pub mod arkworks; + +#[cfg(feature = "blst")] +pub mod blst; + use primitives::hex_literal::hex; /// KZG point evaluation precompile, containing address and function to run. @@ -84,39 +82,28 @@ pub fn verify_kzg_proof( ) -> bool { cfg_if::cfg_if! { if #[cfg(feature = "c-kzg")] { + use c_kzg::{Bytes48, Bytes32}; + + let as_bytes48 = |bytes: &[u8; 48]| -> &Bytes48 { unsafe { &*bytes.as_ptr().cast() } }; + let as_bytes32 = |bytes: &[u8; 32]| -> &Bytes32 { unsafe { &*bytes.as_ptr().cast() } }; + let kzg_settings = c_kzg::ethereum_kzg_settings(8); kzg_settings.verify_kzg_proof(as_bytes48(commitment), as_bytes32(z), as_bytes32(y), as_bytes48(proof)).unwrap_or(false) } else if #[cfg(feature = "kzg-rs")] { + use kzg_rs::{Bytes48, Bytes32, KzgProof}; let env = kzg_rs::EnvKzgSettings::default(); + let as_bytes48 = |bytes: &[u8; 48]| -> &Bytes48 { unsafe { &*bytes.as_ptr().cast() } }; + let as_bytes32 = |bytes: &[u8; 32]| -> &Bytes32 { unsafe { &*bytes.as_ptr().cast() } }; + let kzg_settings = env.get(); KzgProof::verify_kzg_proof(as_bytes48(commitment), as_bytes32(z), as_bytes32(y), as_bytes48(proof), kzg_settings).unwrap_or(false) + } else if #[cfg(feature = "blst")] { + blst::verify_kzg_proof(commitment, z, y, proof) + } else { + arkworks::verify_kzg_proof(commitment, z, y, proof) } } } - -/// Convert a slice to an array of a specific size. -#[inline] -#[track_caller] -fn as_array(bytes: &[u8]) -> &[u8; N] { - bytes.try_into().expect("slice with incorrect length") -} - -/// Convert a slice to a 32 byte big endian array. -#[inline] -#[track_caller] -fn as_bytes32(bytes: &[u8]) -> &Bytes32 { - // SAFETY: `#[repr(C)] Bytes32([u8; 32])` - unsafe { &*as_array::<32>(bytes).as_ptr().cast() } -} - -/// Convert a slice to a 48 byte big endian array. -#[inline] -#[track_caller] -fn as_bytes48(bytes: &[u8]) -> &Bytes48 { - // SAFETY: `#[repr(C)] Bytes48([u8; 48])` - unsafe { &*as_array::<48>(bytes).as_ptr().cast() } -} - #[cfg(test)] mod tests { use super::*; @@ -141,4 +128,26 @@ mod tests { assert_eq!(output.gas_used, gas); assert_eq!(output.bytes[..], expected_output); } + + #[test] + fn test_invalid_input() { + let commitment = hex!("c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let z = hex!("0000000000000000000000000000000000000000000000000000000000000000"); + let y = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); + let proof = hex!("c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + + let t = verify_kzg_proof(&commitment, &z, &y, &proof); + assert!(!t); + } + + #[test] + fn test_valid_input() { + let commitment = hex!("c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + let z = hex!("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000000"); + let y = hex!("0000000000000000000000000000000000000000000000000000000000000000"); + let proof = hex!("c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + + let t = verify_kzg_proof(&commitment, &z, &y, &proof); + assert!(t); + } } diff --git a/crates/precompile/src/kzg_point_evaluation/arkworks.rs b/crates/precompile/src/kzg_point_evaluation/arkworks.rs new file mode 100644 index 0000000000..2f23d2481e --- /dev/null +++ b/crates/precompile/src/kzg_point_evaluation/arkworks.rs @@ -0,0 +1,135 @@ +//! 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 ark_bls12_381::{Fr, G1Affine, G2Affine}; +use ark_ec::{AffineRepr, CurveGroup}; +use ark_ff::{BigInteger, PrimeField}; +use ark_serialize::CanonicalDeserialize; +use core::ops::Neg; +use std::string::ToString; + +/// Verify KZG proof using BLS12-381 implementation. +/// +/// +/// +#[inline] +pub fn verify_kzg_proof( + commitment: &[u8; 48], + z: &[u8; 32], + y: &[u8; 32], + proof: &[u8; 48], +) -> bool { + // Parse the commitment (G1 point) + let Ok(commitment_point) = parse_g1_compressed(commitment) else { + return false; + }; + + // Parse the proof (G1 point) + let Ok(proof_point) = parse_g1_compressed(proof) else { + return false; + }; + + // Parse z and y as field elements (Fr, scalar field) + // We expect 32-byte big-endian scalars that must be canonical + let Ok(z_fr) = read_scalar_canonical(z) else { + return false; + }; + let Ok(y_fr) = read_scalar_canonical(y) else { + return false; + }; + + // Get the trusted setup G2 point [τ]₂ + let tau_g2 = get_trusted_setup_g2(); + + // Get generators + let g1 = get_g1_generator(); + let g2 = get_g2_generator(); + + // Compute P_minus_y = commitment - [y]G₁ + let y_g1 = p1_scalar_mul(&g1, &y_fr); + let p_minus_y = p1_sub_affine(&commitment_point, &y_g1); + + // Compute X_minus_z = [τ]G₂ - [z]G₂ + let z_g2 = p2_scalar_mul(&g2, &z_fr); + let x_minus_z = p2_sub_affine(&tau_g2, &z_g2); + + // Verify: P - y = Q * (X - z) + // Using pairing check: e(P - y, -G₂) * e(proof, X - z) == 1 + let neg_g2 = p2_neg(&g2); + + pairing_check(&[(p_minus_y, neg_g2), (proof_point, x_minus_z)]) +} + +/// Get the trusted setup G2 point `[τ]₂` from the Ethereum KZG ceremony. +/// This is g2_monomial_1 from trusted_setup_4096.json +fn get_trusted_setup_g2() -> G2Affine { + // Parse the compressed G2 point using unchecked deserialization since we trust this point + // This should never fail since we're using a known valid point from the trusted setup + G2Affine::deserialize_compressed_unchecked(&TRUSTED_SETUP_TAU_G2_BYTES[..]) + .expect("Failed to parse trusted setup G2 point") +} + +/// Parse a G1 point from compressed format (48 bytes) +fn parse_g1_compressed(bytes: &[u8; 48]) -> Result { + G1Affine::deserialize_compressed(&bytes[..]) + .map_err(|_| PrecompileError::Other("Invalid compressed G1 point".to_string())) +} + +/// Read a scalar field element from bytes and verify it's canonical +fn read_scalar_canonical(bytes: &[u8; 32]) -> Result { + let fr = Fr::from_be_bytes_mod_order(bytes); + + // Check if the field element is canonical by serializing back and comparing + let bytes_roundtrip = fr.into_bigint().to_bytes_be(); + + if bytes_roundtrip.as_slice() != bytes { + return Err(PrecompileError::Other( + "Non-canonical scalar field element".to_string(), + )); + } + + Ok(fr) +} + +/// Get G1 generator point +#[inline] +fn get_g1_generator() -> G1Affine { + G1Affine::generator() +} + +/// Get G2 generator point +#[inline] +fn get_g2_generator() -> G2Affine { + G2Affine::generator() +} + +/// Scalar multiplication for G1 points +#[inline] +fn p1_scalar_mul(point: &G1Affine, scalar: &Fr) -> G1Affine { + point.mul_bigint(scalar.into_bigint()).into_affine() +} + +/// Scalar multiplication for G2 points +#[inline] +fn p2_scalar_mul(point: &G2Affine, scalar: &Fr) -> G2Affine { + point.mul_bigint(scalar.into_bigint()).into_affine() +} + +/// Subtract two G1 points in affine form +#[inline] +fn p1_sub_affine(a: &G1Affine, b: &G1Affine) -> G1Affine { + (a.into_group() - b.into_group()).into_affine() +} + +/// Subtract two G2 points in affine form +#[inline] +fn p2_sub_affine(a: &G2Affine, b: &G2Affine) -> G2Affine { + (a.into_group() - b.into_group()).into_affine() +} + +/// Negate a G2 point +#[inline] +fn p2_neg(p: &G2Affine) -> G2Affine { + p.neg() +} diff --git a/crates/precompile/src/kzg_point_evaluation/blst.rs b/crates/precompile/src/kzg_point_evaluation/blst.rs new file mode 100644 index 0000000000..fc13973e3d --- /dev/null +++ b/crates/precompile/src/kzg_point_evaluation/blst.rs @@ -0,0 +1,181 @@ +//! 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_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, +}; +use std::string::ToString; + +/// Verify KZG proof using BLST BLS12-381 implementation. +/// +/// +/// +#[inline] +pub fn verify_kzg_proof( + commitment: &[u8; 48], + z: &[u8; 32], + y: &[u8; 32], + proof: &[u8; 48], +) -> bool { + // Parse the commitment (G1 point) + let Ok(commitment_point) = parse_g1_compressed(commitment) else { + return false; + }; + + // Parse the proof (G1 point) + let Ok(proof_point) = parse_g1_compressed(proof) else { + return false; + }; + + // Parse z and y as field elements (Fr, scalar field) + let Ok(z_scalar) = read_scalar_canonical(z) else { + return false; + }; + let Ok(y_scalar) = read_scalar_canonical(y) else { + return false; + }; + + // Get the trusted setup G2 point [τ]₂ + let tau_g2 = get_trusted_setup_g2(); + + // Get generators + let g1 = get_g1_generator(); + let g2 = get_g2_generator(); + + // Compute P_minus_y = commitment - [y]G₁ + let y_g1 = p1_scalar_mul(&g1, &y_scalar); + let p_minus_y = p1_sub_affine(&commitment_point, &y_g1); + + // Compute X_minus_z = [τ]G₂ - [z]G₂ + let z_g2 = p2_scalar_mul(&g2, &z_scalar); + let x_minus_z = p2_sub_affine(&tau_g2, &z_g2); + + // Verify: P - y = Q * (X - z) + // Using pairing check: e(P - y, -G₂) * e(proof, X - z) == 1 + let neg_g2 = p2_neg(&g2); + + pairing_check(&[(p_minus_y, neg_g2), (proof_point, x_minus_z)]) +} + +/// Get the trusted setup G2 point `[τ]₂` from the Ethereum KZG ceremony. +/// This is g2_monomial_1 from trusted_setup_4096.json +fn get_trusted_setup_g2() -> blst_p2_affine { + // For compressed G2, we need to decompress + let mut g2_affine = blst_p2_affine::default(); + unsafe { + // The compressed format has x coordinate and a flag bit for y + // We use deserialize_compressed which handles this automatically + let result = blst::blst_p2_deserialize(&mut g2_affine, TRUSTED_SETUP_TAU_G2_BYTES.as_ptr()); + if result != blst::BLST_ERROR::BLST_SUCCESS { + panic!("Failed to deserialize trusted setup G2 point"); + } + } + g2_affine +} + +/// Get G1 generator point +fn get_g1_generator() -> blst_p1_affine { + unsafe { ::blst::BLS12_381_G1 } +} + +/// Get G2 generator point +fn get_g2_generator() -> blst_p2_affine { + unsafe { ::blst::BLS12_381_G2 } +} + +/// Parse a G1 point from compressed format (48 bytes) +fn parse_g1_compressed(bytes: &[u8; 48]) -> Result { + let mut point = blst_p1_affine::default(); + unsafe { + let result = blst::blst_p1_deserialize(&mut point, bytes.as_ptr()); + if result != blst::BLST_ERROR::BLST_SUCCESS { + return Err(PrecompileError::Other( + "Invalid compressed G1 point".to_string(), + )); + } + + // Verify the point is on curve + if !blst_p1_affine_on_curve(&point) { + return Err(PrecompileError::Other("G1 point not on curve".to_string())); + } + + // Verify the point is in the correct subgroup + if !blst_p1_affine_in_g1(&point) { + return Err(PrecompileError::Other( + "G1 point not in correct subgroup".to_string(), + )); + } + } + Ok(point) +} + +/// Read a scalar field element from bytes and verify it's canonical +fn read_scalar_canonical(bytes: &[u8; 32]) -> Result { + let mut scalar = blst_scalar::default(); + + // Read scalar from big endian bytes + unsafe { + blst_scalar_from_bendian(&mut scalar, bytes.as_ptr()); + } + + if unsafe { !blst_scalar_fr_check(&scalar) } { + return Err(PrecompileError::Other( + "Non-canonical scalar field element".to_string(), + )); + } + + Ok(scalar) +} + +/// Subtract two G1 points in affine form +fn p1_sub_affine(a: &blst_p1_affine, b: &blst_p1_affine) -> blst_p1_affine { + // Convert first point to Jacobian + let a_jacobian = p1_from_affine(a); + + // Negate second point + let neg_b = p1_neg(b); + + // Add a + (-b) + let result = p1_add_or_double(&a_jacobian, &neg_b); + + p1_to_affine(&result) +} + +/// Subtract two G2 points in affine form +fn p2_sub_affine(a: &blst_p2_affine, b: &blst_p2_affine) -> blst_p2_affine { + // Convert first point to Jacobian + let a_jacobian = p2_from_affine(a); + + // Negate second point + let neg_b = p2_neg(b); + + // Add a + (-b) + let result = p2_add_or_double(&a_jacobian, &neg_b); + + p2_to_affine(&result) +} + +/// Negate a G1 point +fn p1_neg(p: &blst_p1_affine) -> blst_p1_affine { + // Convert to Jacobian, negate, convert back + let mut p_jacobian = p1_from_affine(p); + unsafe { + ::blst::blst_p1_cneg(&mut p_jacobian, true); + } + p1_to_affine(&p_jacobian) +} + +/// Negate a G2 point +fn p2_neg(p: &blst_p2_affine) -> blst_p2_affine { + // Convert to Jacobian, negate, convert back + let mut p_jacobian = p2_from_affine(p); + unsafe { + ::blst::blst_p2_cneg(&mut p_jacobian, true); + } + p2_to_affine(&p_jacobian) +} diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 4968f74556..03aad2c4f1 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -16,7 +16,6 @@ pub mod bn254; pub mod hash; pub mod identity; pub mod interface; -#[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] pub mod kzg_point_evaluation; pub mod modexp; pub mod secp256k1; @@ -55,7 +54,6 @@ cfg_if::cfg_if! { #[cfg(feature = "gmp")] use aurora_engine_modexp as _; -use cfg_if::cfg_if; use core::hash::Hash; use primitives::{hardfork::SpecId, Address, HashMap, HashSet, OnceLock}; use std::vec::Vec; @@ -164,21 +162,10 @@ impl Precompiles { static INSTANCE: OnceLock = OnceLock::new(); INSTANCE.get_or_init(|| { let mut precompiles = Self::berlin().clone(); - - // EIP-4844: Shard Blob Transactions - cfg_if! { - if #[cfg(any(feature = "c-kzg", feature = "kzg-rs"))] { - let precompile = kzg_point_evaluation::POINT_EVALUATION.clone(); - } else { - let precompile = PrecompileWithAddress(u64_to_address(0x0A), |_,_| Err(PrecompileError::Fatal("c-kzg feature is not enabled".into()))); - } - } - - precompiles.extend([ - precompile, + // EIP-4844: Shard Blob Transactions + kzg_point_evaluation::POINT_EVALUATION, ]); - precompiles }) } diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 4ae1f7aff1..7bd144584b 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -37,7 +37,7 @@ serde = { workspace = true, features = ["derive"] } ee-tests.workspace = true [features] -default = ["std", "c-kzg", "secp256k1", "portable", "blst", "tracer"] +default = ["std", "secp256k1", "portable", "tracer", "c-kzg", "blst"] std = [ "interpreter/std", "precompile/std", @@ -94,13 +94,15 @@ optional_eip3541 = ["context/optional_eip3541"] optional_eip3607 = ["context/optional_eip3607"] optional_no_base_fee = ["context/optional_no_base_fee"] -# Precompiles features +# Precompiles features: Please look at the comments in `precompile` crate for more information. secp256k1 = ["precompile/secp256k1"] # See comments in `precompile` c-kzg = [ "precompile/c-kzg", ] # `kzg-rs` is not audited but useful for `no_std` environment, use it with causing and default to `c-kzg` if possible. kzg-rs = ["precompile/kzg-rs"] + +# blst will enabled both for bls precompiles and for kzg precompile. blst = ["precompile/blst"] bn = ["precompile/bn"] asm-sha2 = ["precompile/asm-sha2"] From 428ad974f7473384cb568c941a0dd3064d8f19fe Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:13:31 +0200 Subject: [PATCH 29/78] chore: add debug assertions to set_action (#2832) Calling `set_action` when an action is already set usually means that a previous `halt` or similar was not returned. --- crates/interpreter/src/interpreter/ext_bytecode.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/crates/interpreter/src/interpreter/ext_bytecode.rs b/crates/interpreter/src/interpreter/ext_bytecode.rs index f3e4faf962..53852803cc 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode.rs @@ -114,6 +114,16 @@ impl LoopControl for ExtBytecode { #[inline] fn set_action(&mut self, action: InterpreterAction) { + debug_assert_eq!( + self.has_set_action, + self.action.is_some(), + "has_set_action out of sync" + ); + debug_assert!( + !self.has_set_action, + "action already set;\nold: {:#?}\nnew: {:#?}", + self.action, action, + ); self.has_set_action = true; self.action = Some(action); } From 158356c0ce3e9889966533d2d10149c742116f17 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:15:48 +0200 Subject: [PATCH 30/78] chore(benches): clean up criterion callsites (#2833) --- bins/revme/src/cmd/bench/analysis.rs | 9 ++---- bins/revme/src/cmd/bench/burntpix.rs | 9 ++---- bins/revme/src/cmd/bench/evm_build.rs | 4 +-- .../revme/src/cmd/bench/gas_cost_estimator.rs | 9 ++---- bins/revme/src/cmd/bench/snailtracer.rs | 18 +++-------- bins/revme/src/cmd/bench/transfer.rs | 13 ++------ bins/revme/src/cmd/bench/transfer_multi.rs | 10 ++---- bins/revme/src/cmd/evmrunner.rs | 24 +++++++------- bins/revme/src/main.rs | 31 ++++++++----------- crates/bytecode/src/iter.rs | 20 ++++++------ crates/handler/src/instructions.rs | 6 ++-- 11 files changed, 54 insertions(+), 99 deletions(-) diff --git a/bins/revme/src/cmd/bench/analysis.rs b/bins/revme/src/cmd/bench/analysis.rs index e8fdb3704f..e12bc97e96 100644 --- a/bins/revme/src/cmd/bench/analysis.rs +++ b/bins/revme/src/cmd/bench/analysis.rs @@ -24,13 +24,8 @@ pub fn run(criterion: &mut Criterion) { let mut evm = context.build_mainnet(); criterion.bench_function("analysis", |b| { b.iter_batched( - || { - // create a transaction input - tx.clone() - }, - |input| { - let _ = evm.transact_one(input); - }, + || tx.clone(), + |input| evm.transact_one(input).unwrap(), criterion::BatchSize::SmallInput, ); }); diff --git a/bins/revme/src/cmd/bench/burntpix.rs b/bins/revme/src/cmd/bench/burntpix.rs index 1e65627fe4..ba7a14f85f 100644 --- a/bins/revme/src/cmd/bench/burntpix.rs +++ b/bins/revme/src/cmd/bench/burntpix.rs @@ -51,13 +51,8 @@ pub fn run(criterion: &mut Criterion) { criterion.bench_function("burntpix", |b| { b.iter_batched( - || { - // create a transaction input - tx.clone() - }, - |input| { - evm.transact_one(input).unwrap(); - }, + || tx.clone(), + |input| evm.transact_one(input).unwrap(), criterion::BatchSize::SmallInput, ); }); diff --git a/bins/revme/src/cmd/bench/evm_build.rs b/bins/revme/src/cmd/bench/evm_build.rs index a7e2ea7b51..e54b473c82 100644 --- a/bins/revme/src/cmd/bench/evm_build.rs +++ b/bins/revme/src/cmd/bench/evm_build.rs @@ -3,8 +3,6 @@ use revm::{Context, MainBuilder, MainContext}; pub fn run(criterion: &mut Criterion) { criterion.bench_function("evm-build", |b| { - b.iter(|| { - let _ = Context::mainnet().build_mainnet(); - }); + b.iter(|| Context::mainnet().build_mainnet()); }); } diff --git a/bins/revme/src/cmd/bench/gas_cost_estimator.rs b/bins/revme/src/cmd/bench/gas_cost_estimator.rs index d596ac1dab..06db3292a5 100644 --- a/bins/revme/src/cmd/bench/gas_cost_estimator.rs +++ b/bins/revme/src/cmd/bench/gas_cost_estimator.rs @@ -35,13 +35,8 @@ pub fn run(criterion: &mut Criterion) { criterion.bench_function(name, |b| { b.iter_batched( - || { - // create a transaction input - tx.clone() - }, - |input| { - let _ = evm.transact_one(input).unwrap(); - }, + || tx.clone(), + |input| evm.transact_one(input).unwrap(), criterion::BatchSize::SmallInput, ); }); diff --git a/bins/revme/src/cmd/bench/snailtracer.rs b/bins/revme/src/cmd/bench/snailtracer.rs index 0228b3df4c..0e26d279bd 100644 --- a/bins/revme/src/cmd/bench/snailtracer.rs +++ b/bins/revme/src/cmd/bench/snailtracer.rs @@ -27,26 +27,16 @@ pub fn run(criterion: &mut Criterion) { criterion.bench_function("snailtracer", |b| { b.iter_batched( - || { - // create a transaction input - tx.clone() - }, - |input| { - let _ = evm.transact_one(input).unwrap(); - }, + || tx.clone(), + |input| evm.transact_one(input).unwrap(), criterion::BatchSize::SmallInput, ); }); criterion.bench_function("analysis-inspector", |b| { b.iter_batched( - || { - // create a transaction input - tx.clone() - }, - |input| { - let _ = evm.inspect_one_tx(input); - }, + || tx.clone(), + |input| evm.inspect_one_tx(input), criterion::BatchSize::SmallInput, ); }); diff --git a/bins/revme/src/cmd/bench/transfer.rs b/bins/revme/src/cmd/bench/transfer.rs index 0914eff60d..ac196dfe97 100644 --- a/bins/revme/src/cmd/bench/transfer.rs +++ b/bins/revme/src/cmd/bench/transfer.rs @@ -28,13 +28,10 @@ pub fn run(criterion: &mut Criterion) { let mut i = 0; criterion.bench_function("transfer", |b| { b.iter_batched( - || { - // create a transfer input - tx.clone() - }, + || tx.clone(), |input| { i += 1; - evm.transact_one(input).unwrap(); + evm.transact_one(input).unwrap() }, criterion::BatchSize::SmallInput, ); @@ -57,9 +54,5 @@ pub fn run(criterion: &mut Criterion) { evm.modify_cfg(|cfg| cfg.disable_nonce_check = false); - criterion.bench_function("transfer_finalize", |b| { - b.iter(|| { - let _ = evm.replay().unwrap(); - }) - }); + criterion.bench_function("transfer_finalize", |b| b.iter(|| evm.replay().unwrap())); } diff --git a/bins/revme/src/cmd/bench/transfer_multi.rs b/bins/revme/src/cmd/bench/transfer_multi.rs index a6e0bcd639..d22c467677 100644 --- a/bins/revme/src/cmd/bench/transfer_multi.rs +++ b/bins/revme/src/cmd/bench/transfer_multi.rs @@ -51,10 +51,7 @@ pub fn run(criterion: &mut Criterion) { criterion.bench_function("transact_commit_1000txs", |b| { b.iter_batched( - || { - // create transaction inputs - txs.clone() - }, + || txs.clone(), |inputs| { for tx in inputs { let _ = evm.transact_commit(tx).unwrap(); @@ -66,10 +63,7 @@ pub fn run(criterion: &mut Criterion) { criterion.bench_function("transact_1000tx_commit_inner_every_40", |b| { b.iter_batched( - || { - // create transaction inputs - txs.clone() - }, + || txs.clone(), |inputs| { for (i, tx) in inputs.into_iter().enumerate() { let _ = evm.transact_one(tx).unwrap(); diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 87ca3c7cc2..4e54833cb9 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -109,9 +109,11 @@ impl Cmd { .without_plots(); let mut criterion_group = criterion.benchmark_group("revme"); criterion_group.bench_function("evm", |b| { - b.iter(|| { - let _ = evm.transact(tx.clone()).unwrap(); - }) + b.iter_batched( + || tx.clone(), + |input| evm.transact(input).unwrap(), + criterion::BatchSize::SmallInput, + ); }); criterion_group.finish(); @@ -119,19 +121,17 @@ impl Cmd { } let time = Instant::now(); - let state = if self.trace { - evm.inspect_tx(tx.clone()) - .map_err(|_| Errors::EVMError)? - .state + let r = if self.trace { + evm.inspect_tx(tx) } else { - let out = evm.transact(tx.clone()).map_err(|_| Errors::EVMError)?; - println!("Result: {:#?}", out.result); - out.state - }; + evm.transact(tx) + } + .map_err(|_| Errors::EVMError)?; let time = time.elapsed(); + println!("Result: {:#?}", r.result); if self.state { - println!("State: {state:#?}"); + println!("State: {:#?}", r.state); } println!("Elapsed: {time:?}"); diff --git a/bins/revme/src/main.rs b/bins/revme/src/main.rs index a509243c22..d53929cb21 100644 --- a/bins/revme/src/main.rs +++ b/bins/revme/src/main.rs @@ -1,22 +1,17 @@ use clap::Parser; -use revme::cmd::{Error, MainCmd}; +use revme::cmd::MainCmd; +use std::process::ExitCode; -fn main() -> Result<(), Error> { - set_thread_panic_hook(); - MainCmd::parse().run().inspect_err(|e| println!("{e:?}")) -} +fn main() -> ExitCode { + if std::env::var_os("RUST_BACKTRACE").is_none() { + unsafe { std::env::set_var("RUST_BACKTRACE", "1") }; + } -/// Sets thread panic hook, useful for having tests that panic. -fn set_thread_panic_hook() { - use std::{ - backtrace::Backtrace, - panic::{set_hook, take_hook}, - process::exit, - }; - let orig_hook = take_hook(); - set_hook(Box::new(move |panic_info| { - println!("Custom backtrace: {}", Backtrace::capture()); - orig_hook(panic_info); - exit(1); - })); + match MainCmd::parse().run() { + Ok(()) => ExitCode::SUCCESS, + Err(e) => { + eprintln!("error:\n- {e}\n- {e:#?}"); + ExitCode::FAILURE + } + } } diff --git a/crates/bytecode/src/iter.rs b/crates/bytecode/src/iter.rs index 30aff63c83..7abc25cc0f 100644 --- a/crates/bytecode/src/iter.rs +++ b/crates/bytecode/src/iter.rs @@ -6,10 +6,10 @@ use crate::{opcode, Bytecode, OpCode}; /// without dealing with the immediate values that follow instructions. #[derive(Debug, Clone)] pub struct BytecodeIterator<'a> { - /// Start pointer of the bytecode. Only used to calculate [`position`](Self::position). - start: *const u8, /// Iterator over the bytecode bytes. bytes: core::slice::Iter<'a, u8>, + /// Start pointer of the bytecode. Only used to calculate [`position`](Self::position). + start: *const u8, } impl<'a> BytecodeIterator<'a> { @@ -21,8 +21,8 @@ impl<'a> BytecodeIterator<'a> { Bytecode::Eip7702(_) => &[], }; Self { - start: bytes.as_ptr(), bytes: bytes.iter(), + start: bytes.as_ptr(), } } @@ -40,15 +40,13 @@ impl<'a> BytecodeIterator<'a> { /// Returns the current position in the bytecode. #[inline] pub fn position(&self) -> usize { - (self.bytes.as_slice().as_ptr() as usize) - (self.start as usize) - // TODO: Use the following on 1.87 // SAFETY: `start` always points to the start of the bytecode. - // unsafe { - // self.bytes - // .as_slice() - // .as_ptr() - // .offset_from_unsigned(self.start) - // } + unsafe { + self.bytes + .as_slice() + .as_ptr() + .offset_from_unsigned(self.start) + } } #[inline] diff --git a/crates/handler/src/instructions.rs b/crates/handler/src/instructions.rs index a7006be15f..c6d8008882 100644 --- a/crates/handler/src/instructions.rs +++ b/crates/handler/src/instructions.rs @@ -45,14 +45,16 @@ where Self::new(instruction_table::()) } - /// Rerurns new `EthInstructions` with custom instruction table. + /// Returns a new instance of `EthInstructions` with custom instruction table. + #[inline] pub fn new(base_table: InstructionTable) -> Self { Self { instruction_table: Box::new(base_table), } } - /// Inserts a new instruction into the instruction table.s + /// Inserts a new instruction into the instruction table. + #[inline] pub fn insert_instruction(&mut self, opcode: u8, instruction: Instruction) { self.instruction_table[opcode as usize] = instruction; } From 7a18ac3f0ab48596b665045c7aa2dd49e21a1845 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:16:09 +0200 Subject: [PATCH 31/78] chore(benches): rename anaysis-inspector to snailtracer-inspect (#2834) --- bins/revme/src/cmd/bench/snailtracer.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bins/revme/src/cmd/bench/snailtracer.rs b/bins/revme/src/cmd/bench/snailtracer.rs index 0e26d279bd..5445d2fee9 100644 --- a/bins/revme/src/cmd/bench/snailtracer.rs +++ b/bins/revme/src/cmd/bench/snailtracer.rs @@ -33,7 +33,7 @@ pub fn run(criterion: &mut Criterion) { ); }); - criterion.bench_function("analysis-inspector", |b| { + criterion.bench_function("snailtracer-inspect", |b| { b.iter_batched( || tx.clone(), |input| evm.inspect_one_tx(input), From 2abd7a788d3b7674572dbd4f7ba45f73aa51024b Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Mon, 4 Aug 2025 17:26:12 +0800 Subject: [PATCH 32/78] chore: simplify the ecrecover test (#2836) * chore: simplify the ecrecover test like alloy-core signature * fmt --- crates/precompile/bench/ecrecover.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/precompile/bench/ecrecover.rs b/crates/precompile/bench/ecrecover.rs index dd2ff2fa5c..d5b62ffc83 100644 --- a/crates/precompile/bench/ecrecover.rs +++ b/crates/precompile/bench/ecrecover.rs @@ -1,6 +1,6 @@ //! Benchmarks for the ecrecover precompile use criterion::{measurement::Measurement, BenchmarkGroup}; -use primitives::{hex, keccak256, Bytes, U256}; +use primitives::{hex, keccak256, Bytes}; use revm_precompile::secp256k1::ec_recover_run; use secp256k1::{Message, SecretKey, SECP256K1}; @@ -20,8 +20,7 @@ pub fn add_benches(group: &mut BenchmarkGroup<'_, M>) { message_and_signature[0..32].copy_from_slice(&hash[..]); // Fit signature into format the precompile expects - let rec_id = U256::from(rec_id as u64); - message_and_signature[32..64].copy_from_slice(&rec_id.to_be_bytes::<32>()); + message_and_signature[63] = rec_id; message_and_signature[64..128].copy_from_slice(&data); let message_and_signature = Bytes::from(message_and_signature); From d4e48932dab36a1826622d2ba29db8921ec9f941 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Mon, 4 Aug 2025 17:53:47 +0800 Subject: [PATCH 33/78] fix: manally implementation PartialOrd and Ord for AccountInfo (#2835) * fix(revm-state): manally implementation PartialOrd and Ord * fix test * fmt --- crates/state/src/account_info.rs | 75 +++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) diff --git a/crates/state/src/account_info.rs b/crates/state/src/account_info.rs index 53b27cf6b0..11e39a0e09 100644 --- a/crates/state/src/account_info.rs +++ b/crates/state/src/account_info.rs @@ -1,11 +1,14 @@ use bytecode::Bytecode; -use core::hash::{Hash, Hasher}; +use core::{ + cmp::Ordering, + hash::{Hash, Hasher}, +}; use primitives::{B256, KECCAK_EMPTY, U256}; /// Account information that contains balance, nonce, code hash and code /// /// Code is set as optional. -#[derive(Clone, Debug, Eq, Ord, PartialOrd)] +#[derive(Clone, Debug, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccountInfo { /// Account balance. @@ -50,6 +53,21 @@ impl Hash for AccountInfo { } } +impl PartialOrd for AccountInfo { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for AccountInfo { + fn cmp(&self, other: &Self) -> Ordering { + self.balance + .cmp(&other.balance) + .then_with(|| self.nonce.cmp(&other.nonce)) + .then_with(|| self.code_hash.cmp(&other.code_hash)) + } +} + impl AccountInfo { /// Creates a new [`AccountInfo`] with the given fields. #[inline] @@ -274,3 +292,56 @@ impl AccountInfo { } } } + +#[cfg(test)] +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()), + }; + + let account2 = AccountInfo { + balance: U256::ZERO, + nonce: 0, + code_hash: KECCAK_EMPTY, + code: None, + }; + + assert_eq!(account1, account2, "Accounts should be equal ignoring code"); + + assert_eq!( + account1.cmp(&account2), + Ordering::Equal, + "Ordering should be equal after ignoring code in Ord" + ); + + let mut set = BTreeSet::new(); + assert!(set.insert(account1.clone()), "Inserted account1"); + assert!( + !set.insert(account2.clone()), + "account2 not inserted (treated as duplicate)" + ); + + assert_eq!(set.len(), 1, "Set should have only one unique account"); + assert!(set.contains(&account1), "Set contains account1"); + assert!( + set.contains(&account2), + "Set contains account2 (since equal)" + ); + + let mut accounts = vec![account2.clone(), account1.clone()]; + accounts.sort(); + assert_eq!(accounts[0], accounts[1], "Sorted vec treats them as equal"); + } +} From a0b7fe9e88235f02d277883d5d72f9cbc8860c79 Mon Sep 17 00:00:00 2001 From: Jack Drogon Date: Mon, 4 Aug 2025 18:03:07 +0800 Subject: [PATCH 34/78] docs: improve primitives crate documentation and consistency (#2829) - Expand lib.rs crate-level documentation with detailed feature overview - Enhance type alias documentation for StorageKey and StorageValue - Standardize EIP file documentation headers with consistent format - Fix TODO comment in eip7907.rs with proper EIP description - Unify all EIP modules with descriptive titles and brief explanations Signed-off-by: Jack Drogon --- crates/primitives/src/eip170.rs | 4 +++- crates/primitives/src/eip3860.rs | 4 +++- crates/primitives/src/eip4844.rs | 3 ++- crates/primitives/src/eip7702.rs | 4 +++- crates/primitives/src/eip7823.rs | 7 +++---- crates/primitives/src/eip7825.rs | 5 +++-- crates/primitives/src/eip7907.rs | 4 +++- crates/primitives/src/eip7918.rs | 3 ++- crates/primitives/src/lib.rs | 17 ++++++++++++++--- 9 files changed, 36 insertions(+), 15 deletions(-) diff --git a/crates/primitives/src/eip170.rs b/crates/primitives/src/eip170.rs index 486150ec09..7022626e11 100644 --- a/crates/primitives/src/eip170.rs +++ b/crates/primitives/src/eip170.rs @@ -1,4 +1,6 @@ -//! EIP-170: Contract code size limit +//! EIP-170: Contract Code Size Limit +//! +//! Introduces a maximum limit on smart contract code size. /// EIP-170: Contract code size limit /// diff --git a/crates/primitives/src/eip3860.rs b/crates/primitives/src/eip3860.rs index 95b3ad8112..160c4bd09d 100644 --- a/crates/primitives/src/eip3860.rs +++ b/crates/primitives/src/eip3860.rs @@ -1,4 +1,6 @@ -//! EIP-3860: Limit and meter initcode +//! EIP-3860: Limit and Meter Initcode +//! +//! Introduces limits and gas metering for contract creation code. use crate::eip170; diff --git a/crates/primitives/src/eip4844.rs b/crates/primitives/src/eip4844.rs index 61db2aa15c..8a67e8224a 100644 --- a/crates/primitives/src/eip4844.rs +++ b/crates/primitives/src/eip4844.rs @@ -1,5 +1,6 @@ -//! EIP-4844 constants +//! EIP-4844: Shard Blob Transactions //! +//! Constants for blob transaction support in Cancun and Prague hard forks. /// First version of the blob pub const VERSIONED_HASH_VERSION_KZG: u8 = 0x01; diff --git a/crates/primitives/src/eip7702.rs b/crates/primitives/src/eip7702.rs index 248513fb3a..0a958fb905 100644 --- a/crates/primitives/src/eip7702.rs +++ b/crates/primitives/src/eip7702.rs @@ -1,4 +1,6 @@ -//! EIP-7702 constants +//! EIP-7702: Set EOA Account Code +//! +//! Constants for account authorization and delegation functionality. /// Base cost of updating authorized account. pub const PER_AUTH_BASE_COST: u64 = 12500; diff --git a/crates/primitives/src/eip7823.rs b/crates/primitives/src/eip7823.rs index 2a8e5d2a9b..5fa40e6f59 100644 --- a/crates/primitives/src/eip7823.rs +++ b/crates/primitives/src/eip7823.rs @@ -1,8 +1,7 @@ -//! EIP-7823 Set upper bounds for MODEXP +//! EIP-7823: Set Upper Bounds for MODEXP //! -//! Introduce an upper bound on the inputs of the MODEXP precompile. -//! This can reduce the number of potential bugs, because the testing surface is not infinite anymore, -//! and makes it easier to be replaced using EVMMAX. +//! Introduces an upper bound on the inputs of the MODEXP precompile. +//! This reduces the number of potential bugs and makes it easier to replace using EVMMAX. /// Each of the modexp length inputs (length_of_BASE, length_of_EXPONENT and length_of_MODULUS) /// MUST be less than or equal to 8192 bits (1024 bytes). diff --git a/crates/primitives/src/eip7825.rs b/crates/primitives/src/eip7825.rs index b8248f5882..bfde4cfb10 100644 --- a/crates/primitives/src/eip7825.rs +++ b/crates/primitives/src/eip7825.rs @@ -1,5 +1,6 @@ -//! EIP-7825: Transaction Gas Limit Cap -//! Introduce a protocol-level cap on the maximum gas used by a transaction to 16 777 216. +//! EIP-7825: Transaction Gas Limit Cap +//! +//! Introduces a protocol-level cap on the maximum gas used by a transaction. /// Transaction gas limit cap. /// diff --git a/crates/primitives/src/eip7907.rs b/crates/primitives/src/eip7907.rs index ac955e2724..fd9e03f479 100644 --- a/crates/primitives/src/eip7907.rs +++ b/crates/primitives/src/eip7907.rs @@ -1,4 +1,6 @@ -//! TODO dont have specific EIP. It is part of: EIP-7907: Meter Contract Code Size And Increase Limit +//! EIP-7907: Meter Contract Code Size And Increase Limit (Prague) +//! +//! This EIP introduces updated code size limits that apply starting from the Prague hard fork. /// By default the limit is `0xC000` (49_152 bytes). pub const MAX_CODE_SIZE: usize = 0xC000; diff --git a/crates/primitives/src/eip7918.rs b/crates/primitives/src/eip7918.rs index f40e4a0eef..a84d99c902 100644 --- a/crates/primitives/src/eip7918.rs +++ b/crates/primitives/src/eip7918.rs @@ -1,5 +1,6 @@ -//! Constants for EIP-7918: Blob base fee bounded by execution cost +//! EIP-7918: Blob Base Fee Bounded by Execution Cost //! +//! Constants for blob base fee calculation with execution cost bounds. /// Minimum base fee for blobs, if price of the blob is less than this value, this value will be used. pub const BLOB_BASE_COST: u64 = 2_u64.pow(14); diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index b78028d94a..d5ea735c68 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -1,6 +1,14 @@ //! # revm-primitives //! -//! EVM primitive types. +//! Core primitive types and constants for the Ethereum Virtual Machine (EVM) implementation. +//! +//! This crate provides: +//! - EVM constants and limits (gas, stack, code size) +//! - Ethereum hard fork management and version control +//! - EIP-specific constants and configuration values +//! - Cross-platform synchronization primitives +//! - Type aliases for common EVM concepts (storage keys/values) +//! - Re-exports of alloy primitive types for convenience #![cfg_attr(not(test), warn(unused_crate_dependencies))] #![cfg_attr(not(feature = "std"), no_std)] @@ -30,7 +38,10 @@ pub use alloy_primitives::{ Bytes, FixedBytes, Log, LogData, TxKind, B256, I128, I256, U128, U256, }; -/// type alias for storage keys +/// Type alias for EVM storage keys (256-bit unsigned integers). +/// Used to identify storage slots within smart contract storage. pub type StorageKey = U256; -/// type alias for storage values + +/// Type alias for EVM storage values (256-bit unsigned integers). +/// Used to store data values in smart contract storage slots. pub type StorageValue = U256; From 8bdbd70db99bef46c0c7cd286a3c133c4ed02a83 Mon Sep 17 00:00:00 2001 From: anim001k <140460766+anim001k@users.noreply.github.com> Date: Mon, 4 Aug 2025 12:10:40 +0200 Subject: [PATCH 35/78] chore: Update awesome.md (#2827) --- book/src/awesome.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/book/src/awesome.md b/book/src/awesome.md index ad61479a3f..51f759a196 100644 --- a/book/src/awesome.md +++ b/book/src/awesome.md @@ -26,7 +26,7 @@ A curated list of excellent Revm-related resources. Feel free to contribute to t #### Tools - [**Foundry:**](https://github.com/foundry-rs/foundry) A portable and modular toolkit for rapid Ethereum application development in Rust. - [**Hardhat:**](https://github.com/NomicFoundation/hardhat) A comprehensive development environment for compiling, deploying, testing, and debugging Ethereum software. -- [**Arbiter:**](https://github.com/primitivefinance/arbiter) smart-contract simulation. +- [**Arbiter:**](https://github.com/harnesslabs/arbiter) smart-contract simulation. #### Frameworks and Libraries - [**revm-inspectors:**](https://github.com/paradigmxyz/revm-inspectors) Hooks for EVM execution. @@ -40,6 +40,6 @@ A curated list of excellent Revm-related resources. Feel free to contribute to t #### Tutorials - [**MyEvm**](https://github.com/bluealloy/revm/tree/main/examples/my_evm): Custom EVM Implementation Example - [**Revm is All You Need:**](https://medium.com/@solidquant/revm-is-all-you-need-e01b5b0421e4): Guide on building simulated blockchain environments. -- [**Uniswap Swap Example:**](https://github.com/bluealloy/revm/tree/main/examples/uniswap_get_reserves) Demonstrates a USDC swap on Uniswap V2.evm is available in the [awesome-revm](./awesome.md) section o -- [**revm-by-example:**](https://github.com/Cionn3/revm-by-example) Practical examples using the Rust Ethereum Virtual Machine. +- [**Uniswap Swap Example:**](https://github.com/bluealloy/revm/tree/main/examples/uniswap_get_reserves) Demonstrates a USDC swap on Uniswap V2. +- [**revm-by-example:**](https://github.com/greekfetacheese/revm-by-example) Practical examples using the Rust Ethereum Virtual Machine. - [**How to Discover long-tail MEV Strategies using Revm**](https://pawelurbanek.com/long-tail-mev-revm) From 3354dc175e16e0428eb55b5e8e49e0f5d553e250 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 4 Aug 2025 12:58:11 +0200 Subject: [PATCH 36/78] feat: gastable, record static gas in Interpreter loop (#2822) * temp gas table * temp gas calc * simpler gas record * add static gas for push opcodes * check rest of gas values * remove option from opinfo * cleanup and fixes * move opcode cost calc to upper fn * always inline step fn * move static gas inside instruction * revert chaned to bytecode opcode info * cleanup * simplify record_cost * use wrapped_sub and halt_oog * use halt_oog --- crates/ee-tests/src/lib.rs | 6 +- crates/handler/src/frame.rs | 44 -- crates/handler/src/instructions.rs | 4 +- crates/interpreter/src/gas.rs | 22 +- crates/interpreter/src/instruction_context.rs | 23 +- crates/interpreter/src/instructions.rs | 376 ++++++++++-------- .../src/instructions/arithmetic.rs | 20 +- .../interpreter/src/instructions/bitwise.rs | 31 +- .../src/instructions/block_info.rs | 17 +- .../interpreter/src/instructions/control.rs | 13 +- crates/interpreter/src/instructions/host.rs | 8 +- crates/interpreter/src/instructions/macros.rs | 4 +- crates/interpreter/src/instructions/memory.rs | 8 +- crates/interpreter/src/instructions/stack.rs | 11 +- crates/interpreter/src/instructions/system.rs | 16 +- .../interpreter/src/instructions/tx_info.rs | 7 +- crates/interpreter/src/interpreter.rs | 52 ++- .../src/interpreter/ext_bytecode.rs | 21 +- crates/interpreter/src/interpreter_action.rs | 18 + crates/interpreter/src/interpreter_types.rs | 8 +- examples/custom_opcodes/src/main.rs | 13 +- 21 files changed, 374 insertions(+), 348 deletions(-) diff --git a/crates/ee-tests/src/lib.rs b/crates/ee-tests/src/lib.rs index db3d469d0d..42b8d48dbf 100644 --- a/crates/ee-tests/src/lib.rs +++ b/crates/ee-tests/src/lib.rs @@ -98,12 +98,8 @@ where // Compare the output objects directly if *output != expected { - // If they don't match, generate a nicer error by pretty-printing both as JSON - // This helps with debugging by showing the exact differences - let expected_pretty = serde_json::to_string_pretty(&expected).unwrap(); - panic!( - "Value does not match testdata.\nExpected:\n{expected_pretty}\n\nActual:\n{output_json}" + "Value does not match testdata.\nExpected:\n{expected_json}\n\nActual:\n{output_json}" ); } } diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index 56416f08d0..dd2cd5d9e8 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -727,47 +727,3 @@ pub fn return_create( interpreter_result.result = InstructionResult::Return; } - -/* -pub fn return_eofcreate( - journal: &mut JOURNAL, - checkpoint: JournalCheckpoint, - interpreter_result: &mut InterpreterResult, - address: Address, - max_code_size: usize, -) { - // Note we still execute RETURN opcode and return the bytes. - // In EOF those opcodes should abort execution. - // - // In RETURN gas is still protecting us from ddos and in oog, - // behaviour will be same as if it failed on return. - // - // Bytes of RETURN will drained in `insert_eofcreate_outcome`. - if interpreter_result.result != InstructionResult::ReturnContract { - journal.checkpoint_revert(checkpoint); - return; - } - - if interpreter_result.output.len() > max_code_size { - journal.checkpoint_revert(checkpoint); - interpreter_result.result = InstructionResult::CreateContractSizeLimit; - return; - } - - // Deduct gas for code deployment. - let gas_for_code = interpreter_result.output.len() as u64 * gas::CODEDEPOSIT; - if !interpreter_result.gas.record_cost(gas_for_code) { - journal.checkpoint_revert(checkpoint); - interpreter_result.result = InstructionResult::OutOfGas; - return; - } - - journal.checkpoint_commit(); - - // Decode bytecode has a performance hit, but it has reasonable restrains. - let bytecode = Eof::decode(interpreter_result.output.clone()).expect("Eof is already verified"); - - // Eof bytecode is going to be hashed. - journal.set_code(address, Bytecode::Eof(Arc::new(bytecode))); -} - */ diff --git a/crates/handler/src/instructions.rs b/crates/handler/src/instructions.rs index c6d8008882..b45582f0d4 100644 --- a/crates/handler/src/instructions.rs +++ b/crates/handler/src/instructions.rs @@ -19,12 +19,12 @@ pub trait InstructionProvider { /// Ethereum instruction contains list of mainnet instructions that is used for Interpreter execution. #[derive(Debug)] -pub struct EthInstructions { +pub struct EthInstructions { /// Table containing instruction implementations indexed by opcode. pub instruction_table: Box>, } -impl Clone for EthInstructions +impl Clone for EthInstructions where WIRE: InterpreterTypes, { diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index e270224069..37a0421835 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -153,19 +153,15 @@ impl Gas { false } - /// Record memory expansion - #[inline] - #[must_use = "internally uses record_cost that flags out of gas error"] - pub fn record_memory_expansion(&mut self, new_len: usize) -> MemoryExtensionResult { - let Some(additional_cost) = self.memory.record_new_len(new_len) else { - return MemoryExtensionResult::Same; - }; - - if !self.record_cost(additional_cost) { - return MemoryExtensionResult::OutOfGas; - } - - MemoryExtensionResult::Extended + /// Records an explicit cost. In case of underflow the gas will wrap around cost. + /// + /// Returns `true` if the gas limit is exceeded. + #[inline(always)] + #[must_use = "In case of not enough gas, the interpreter should halt with an out-of-gas error"] + pub fn record_cost_unsafe(&mut self, cost: u64) -> bool { + let oog = self.remaining < cost; + self.remaining = self.remaining.wrapping_sub(cost); + oog } } diff --git a/crates/interpreter/src/instruction_context.rs b/crates/interpreter/src/instruction_context.rs index d8aa146829..37e48a6565 100644 --- a/crates/interpreter/src/instruction_context.rs +++ b/crates/interpreter/src/instruction_context.rs @@ -1,6 +1,4 @@ -use crate::{interpreter_types::Jumps, Interpreter, InterpreterTypes}; - -use super::Instruction; +use crate::{Interpreter, InterpreterTypes}; /// Context passed to instruction implementations containing the host and interpreter. /// This struct provides access to both the host interface for external state operations @@ -20,22 +18,3 @@ impl std::fmt::Debug for InstructionContext<'_ .finish() } } - -impl InstructionContext<'_, H, ITy> { - /// Executes the instruction at the current instruction pointer. - /// - /// Internally it will increment instruction pointer by one. - #[inline] - pub(crate) fn step(self, instruction_table: &[Instruction; 256]) { - // Get current opcode. - let opcode = self.interpreter.bytecode.opcode(); - - // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last - // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction - // it will do noop and just stop execution of this contract - self.interpreter.bytecode.relative_jump(1); - - // Execute instruction. - instruction_table[opcode as usize](self) - } -} diff --git a/crates/interpreter/src/instructions.rs b/crates/interpreter/src/instructions.rs index 63ff98f6b6..790a526f77 100644 --- a/crates/interpreter/src/instructions.rs +++ b/crates/interpreter/src/instructions.rs @@ -30,184 +30,222 @@ pub mod utility; use crate::{interpreter_types::InterpreterTypes, Host, InstructionContext}; /// EVM opcode function signature. -pub type Instruction = fn(InstructionContext<'_, H, W>); +#[derive(Debug, PartialEq, Eq)] +pub struct Instruction { + fn_: fn(InstructionContext<'_, H, W>), + static_gas: u64, +} + +impl Instruction { + /// Creates a new instruction with the given function and static gas cost. + #[inline] + pub const fn new(fn_: fn(InstructionContext<'_, H, W>), static_gas: u64) -> Self { + Self { fn_, static_gas } + } + + /// Creates an unknown/invalid instruction. + #[inline] + pub const fn unknown() -> Self { + Self { + fn_: control::unknown, + static_gas: 0, + } + } + + /// Executes the instruction with the given context. + #[inline(always)] + pub fn execute(self, ctx: InstructionContext<'_, H, W>) { + (self.fn_)(ctx) + } + + /// Returns the static gas cost of this instruction. + #[inline(always)] + pub const fn static_gas(&self) -> u64 { + self.static_gas + } +} + +impl Copy for Instruction {} +impl Clone for Instruction { + fn clone(&self) -> Self { + *self + } +} /// Instruction table is list of instruction function pointers mapped to 256 EVM opcodes. pub type InstructionTable = [Instruction; 256]; /// Returns the default instruction table for the given interpreter types and host. #[inline] -pub const fn instruction_table( -) -> [Instruction; 256] { +pub const fn instruction_table() -> [Instruction; 256] { const { instruction_table_impl::() } } -const fn instruction_table_impl( -) -> [Instruction; 256] { +const fn instruction_table_impl() -> [Instruction; 256] { use bytecode::opcode::*; - let mut table = [control::unknown as Instruction; 256]; - - table[STOP as usize] = control::stop; - table[ADD as usize] = arithmetic::add; - table[MUL as usize] = arithmetic::mul; - table[SUB as usize] = arithmetic::sub; - table[DIV as usize] = arithmetic::div; - table[SDIV as usize] = arithmetic::sdiv; - table[MOD as usize] = arithmetic::rem; - table[SMOD as usize] = arithmetic::smod; - table[ADDMOD as usize] = arithmetic::addmod; - table[MULMOD as usize] = arithmetic::mulmod; - table[EXP as usize] = arithmetic::exp; - table[SIGNEXTEND as usize] = arithmetic::signextend; - - table[LT as usize] = bitwise::lt; - table[GT as usize] = bitwise::gt; - table[SLT as usize] = bitwise::slt; - table[SGT as usize] = bitwise::sgt; - table[EQ as usize] = bitwise::eq; - table[ISZERO as usize] = bitwise::iszero; - table[AND as usize] = bitwise::bitand; - table[OR as usize] = bitwise::bitor; - table[XOR as usize] = bitwise::bitxor; - table[NOT as usize] = bitwise::not; - table[BYTE as usize] = bitwise::byte; - table[SHL as usize] = bitwise::shl; - table[SHR as usize] = bitwise::shr; - table[SAR as usize] = bitwise::sar; - table[CLZ as usize] = bitwise::clz; - - table[KECCAK256 as usize] = system::keccak256; - - table[ADDRESS as usize] = system::address; - table[BALANCE as usize] = host::balance; - table[ORIGIN as usize] = tx_info::origin; - table[CALLER as usize] = system::caller; - table[CALLVALUE as usize] = system::callvalue; - table[CALLDATALOAD as usize] = system::calldataload; - table[CALLDATASIZE as usize] = system::calldatasize; - table[CALLDATACOPY as usize] = system::calldatacopy; - table[CODESIZE as usize] = system::codesize; - table[CODECOPY as usize] = system::codecopy; - - table[GASPRICE as usize] = tx_info::gasprice; - table[EXTCODESIZE as usize] = host::extcodesize; - table[EXTCODECOPY as usize] = host::extcodecopy; - table[RETURNDATASIZE as usize] = system::returndatasize; - table[RETURNDATACOPY as usize] = system::returndatacopy; - table[EXTCODEHASH as usize] = host::extcodehash; - table[BLOCKHASH as usize] = host::blockhash; - table[COINBASE as usize] = block_info::coinbase; - table[TIMESTAMP as usize] = block_info::timestamp; - table[NUMBER as usize] = block_info::block_number; - table[DIFFICULTY as usize] = block_info::difficulty; - table[GASLIMIT as usize] = block_info::gaslimit; - table[CHAINID as usize] = block_info::chainid; - table[SELFBALANCE as usize] = host::selfbalance; - table[BASEFEE as usize] = block_info::basefee; - table[BLOBHASH as usize] = tx_info::blob_hash; - table[BLOBBASEFEE as usize] = block_info::blob_basefee; - - table[POP as usize] = stack::pop; - table[MLOAD as usize] = memory::mload; - table[MSTORE as usize] = memory::mstore; - table[MSTORE8 as usize] = memory::mstore8; - table[SLOAD as usize] = host::sload; - table[SSTORE as usize] = host::sstore; - table[JUMP as usize] = control::jump; - table[JUMPI as usize] = control::jumpi; - table[PC as usize] = control::pc; - table[MSIZE as usize] = memory::msize; - table[GAS as usize] = system::gas; - table[JUMPDEST as usize] = control::jumpdest; - table[TLOAD as usize] = host::tload; - table[TSTORE as usize] = host::tstore; - table[MCOPY as usize] = memory::mcopy; - - table[PUSH0 as usize] = stack::push0; - table[PUSH1 as usize] = stack::push::<1, _, _>; - table[PUSH2 as usize] = stack::push::<2, _, _>; - table[PUSH3 as usize] = stack::push::<3, _, _>; - table[PUSH4 as usize] = stack::push::<4, _, _>; - table[PUSH5 as usize] = stack::push::<5, _, _>; - table[PUSH6 as usize] = stack::push::<6, _, _>; - table[PUSH7 as usize] = stack::push::<7, _, _>; - table[PUSH8 as usize] = stack::push::<8, _, _>; - table[PUSH9 as usize] = stack::push::<9, _, _>; - table[PUSH10 as usize] = stack::push::<10, _, _>; - table[PUSH11 as usize] = stack::push::<11, _, _>; - table[PUSH12 as usize] = stack::push::<12, _, _>; - table[PUSH13 as usize] = stack::push::<13, _, _>; - table[PUSH14 as usize] = stack::push::<14, _, _>; - table[PUSH15 as usize] = stack::push::<15, _, _>; - table[PUSH16 as usize] = stack::push::<16, _, _>; - table[PUSH17 as usize] = stack::push::<17, _, _>; - table[PUSH18 as usize] = stack::push::<18, _, _>; - table[PUSH19 as usize] = stack::push::<19, _, _>; - table[PUSH20 as usize] = stack::push::<20, _, _>; - table[PUSH21 as usize] = stack::push::<21, _, _>; - table[PUSH22 as usize] = stack::push::<22, _, _>; - table[PUSH23 as usize] = stack::push::<23, _, _>; - table[PUSH24 as usize] = stack::push::<24, _, _>; - table[PUSH25 as usize] = stack::push::<25, _, _>; - table[PUSH26 as usize] = stack::push::<26, _, _>; - table[PUSH27 as usize] = stack::push::<27, _, _>; - table[PUSH28 as usize] = stack::push::<28, _, _>; - table[PUSH29 as usize] = stack::push::<29, _, _>; - table[PUSH30 as usize] = stack::push::<30, _, _>; - table[PUSH31 as usize] = stack::push::<31, _, _>; - table[PUSH32 as usize] = stack::push::<32, _, _>; - - table[DUP1 as usize] = stack::dup::<1, _, _>; - table[DUP2 as usize] = stack::dup::<2, _, _>; - table[DUP3 as usize] = stack::dup::<3, _, _>; - table[DUP4 as usize] = stack::dup::<4, _, _>; - table[DUP5 as usize] = stack::dup::<5, _, _>; - table[DUP6 as usize] = stack::dup::<6, _, _>; - table[DUP7 as usize] = stack::dup::<7, _, _>; - table[DUP8 as usize] = stack::dup::<8, _, _>; - table[DUP9 as usize] = stack::dup::<9, _, _>; - table[DUP10 as usize] = stack::dup::<10, _, _>; - table[DUP11 as usize] = stack::dup::<11, _, _>; - table[DUP12 as usize] = stack::dup::<12, _, _>; - table[DUP13 as usize] = stack::dup::<13, _, _>; - table[DUP14 as usize] = stack::dup::<14, _, _>; - table[DUP15 as usize] = stack::dup::<15, _, _>; - table[DUP16 as usize] = stack::dup::<16, _, _>; - - table[SWAP1 as usize] = stack::swap::<1, _, _>; - table[SWAP2 as usize] = stack::swap::<2, _, _>; - table[SWAP3 as usize] = stack::swap::<3, _, _>; - table[SWAP4 as usize] = stack::swap::<4, _, _>; - table[SWAP5 as usize] = stack::swap::<5, _, _>; - table[SWAP6 as usize] = stack::swap::<6, _, _>; - table[SWAP7 as usize] = stack::swap::<7, _, _>; - table[SWAP8 as usize] = stack::swap::<8, _, _>; - table[SWAP9 as usize] = stack::swap::<9, _, _>; - table[SWAP10 as usize] = stack::swap::<10, _, _>; - table[SWAP11 as usize] = stack::swap::<11, _, _>; - table[SWAP12 as usize] = stack::swap::<12, _, _>; - table[SWAP13 as usize] = stack::swap::<13, _, _>; - table[SWAP14 as usize] = stack::swap::<14, _, _>; - table[SWAP15 as usize] = stack::swap::<15, _, _>; - table[SWAP16 as usize] = stack::swap::<16, _, _>; - - table[LOG0 as usize] = host::log::<0, _>; - table[LOG1 as usize] = host::log::<1, _>; - table[LOG2 as usize] = host::log::<2, _>; - table[LOG3 as usize] = host::log::<3, _>; - table[LOG4 as usize] = host::log::<4, _>; - - table[CREATE as usize] = contract::create::<_, false, _>; - table[CALL as usize] = contract::call; - table[CALLCODE as usize] = contract::call_code; - table[RETURN as usize] = control::ret; - table[DELEGATECALL as usize] = contract::delegate_call; - table[CREATE2 as usize] = contract::create::<_, true, _>; - - table[STATICCALL as usize] = contract::static_call; - table[REVERT as usize] = control::revert; - table[INVALID as usize] = control::invalid; - table[SELFDESTRUCT as usize] = host::selfdestruct; + let mut table = [Instruction::unknown(); 256]; + + table[STOP as usize] = Instruction::new(control::stop, 0); + table[ADD as usize] = Instruction::new(arithmetic::add, 3); + table[MUL as usize] = Instruction::new(arithmetic::mul, 5); + table[SUB as usize] = Instruction::new(arithmetic::sub, 3); + table[DIV as usize] = Instruction::new(arithmetic::div, 5); + table[SDIV as usize] = Instruction::new(arithmetic::sdiv, 5); + table[MOD as usize] = Instruction::new(arithmetic::rem, 5); + 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[SIGNEXTEND as usize] = Instruction::new(arithmetic::signextend, 5); + + table[LT as usize] = Instruction::new(bitwise::lt, 3); + table[GT as usize] = Instruction::new(bitwise::gt, 3); + table[SLT as usize] = Instruction::new(bitwise::slt, 3); + table[SGT as usize] = Instruction::new(bitwise::sgt, 3); + table[EQ as usize] = Instruction::new(bitwise::eq, 3); + table[ISZERO as usize] = Instruction::new(bitwise::iszero, 3); + table[AND as usize] = Instruction::new(bitwise::bitand, 3); + table[OR as usize] = Instruction::new(bitwise::bitor, 3); + table[XOR as usize] = Instruction::new(bitwise::bitxor, 3); + table[NOT as usize] = Instruction::new(bitwise::not, 3); + table[BYTE as usize] = Instruction::new(bitwise::byte, 3); + table[SHL as usize] = Instruction::new(bitwise::shl, 3); + table[SHR as usize] = Instruction::new(bitwise::shr, 3); + 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[ADDRESS as usize] = Instruction::new(system::address, 2); + table[BALANCE as usize] = Instruction::new(host::balance, 0); // dynamic + 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[CODESIZE as usize] = Instruction::new(system::codesize, 2); + table[CODECOPY as usize] = Instruction::new(system::codecopy, 0); // static 2, mostly dynamic + + 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[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[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); + table[NUMBER as usize] = Instruction::new(block_info::block_number, 2); + table[DIFFICULTY as usize] = Instruction::new(block_info::difficulty, 2); + table[GASLIMIT as usize] = Instruction::new(block_info::gaslimit, 2); + table[CHAINID as usize] = Instruction::new(block_info::chainid, 2); + table[SELFBALANCE as usize] = Instruction::new(host::selfbalance, 5); + table[BASEFEE as usize] = Instruction::new(block_info::basefee, 2); + table[BLOBHASH as usize] = Instruction::new(tx_info::blob_hash, 3); + table[BLOBBASEFEE as usize] = Instruction::new(block_info::blob_basefee, 2); + + table[POP as usize] = Instruction::new(stack::pop, 2); + 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[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); + table[MSIZE as usize] = Instruction::new(memory::msize, 2); + table[GAS as usize] = Instruction::new(system::gas, 2); + 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[PUSH0 as usize] = Instruction::new(stack::push0, 2); + table[PUSH1 as usize] = Instruction::new(stack::push::<1, _, _>, 3); + table[PUSH2 as usize] = Instruction::new(stack::push::<2, _, _>, 3); + table[PUSH3 as usize] = Instruction::new(stack::push::<3, _, _>, 3); + table[PUSH4 as usize] = Instruction::new(stack::push::<4, _, _>, 3); + table[PUSH5 as usize] = Instruction::new(stack::push::<5, _, _>, 3); + table[PUSH6 as usize] = Instruction::new(stack::push::<6, _, _>, 3); + table[PUSH7 as usize] = Instruction::new(stack::push::<7, _, _>, 3); + table[PUSH8 as usize] = Instruction::new(stack::push::<8, _, _>, 3); + table[PUSH9 as usize] = Instruction::new(stack::push::<9, _, _>, 3); + table[PUSH10 as usize] = Instruction::new(stack::push::<10, _, _>, 3); + table[PUSH11 as usize] = Instruction::new(stack::push::<11, _, _>, 3); + table[PUSH12 as usize] = Instruction::new(stack::push::<12, _, _>, 3); + table[PUSH13 as usize] = Instruction::new(stack::push::<13, _, _>, 3); + table[PUSH14 as usize] = Instruction::new(stack::push::<14, _, _>, 3); + table[PUSH15 as usize] = Instruction::new(stack::push::<15, _, _>, 3); + table[PUSH16 as usize] = Instruction::new(stack::push::<16, _, _>, 3); + table[PUSH17 as usize] = Instruction::new(stack::push::<17, _, _>, 3); + table[PUSH18 as usize] = Instruction::new(stack::push::<18, _, _>, 3); + table[PUSH19 as usize] = Instruction::new(stack::push::<19, _, _>, 3); + table[PUSH20 as usize] = Instruction::new(stack::push::<20, _, _>, 3); + table[PUSH21 as usize] = Instruction::new(stack::push::<21, _, _>, 3); + table[PUSH22 as usize] = Instruction::new(stack::push::<22, _, _>, 3); + table[PUSH23 as usize] = Instruction::new(stack::push::<23, _, _>, 3); + table[PUSH24 as usize] = Instruction::new(stack::push::<24, _, _>, 3); + table[PUSH25 as usize] = Instruction::new(stack::push::<25, _, _>, 3); + table[PUSH26 as usize] = Instruction::new(stack::push::<26, _, _>, 3); + table[PUSH27 as usize] = Instruction::new(stack::push::<27, _, _>, 3); + table[PUSH28 as usize] = Instruction::new(stack::push::<28, _, _>, 3); + table[PUSH29 as usize] = Instruction::new(stack::push::<29, _, _>, 3); + table[PUSH30 as usize] = Instruction::new(stack::push::<30, _, _>, 3); + table[PUSH31 as usize] = Instruction::new(stack::push::<31, _, _>, 3); + table[PUSH32 as usize] = Instruction::new(stack::push::<32, _, _>, 3); + + table[DUP1 as usize] = Instruction::new(stack::dup::<1, _, _>, 3); + table[DUP2 as usize] = Instruction::new(stack::dup::<2, _, _>, 3); + table[DUP3 as usize] = Instruction::new(stack::dup::<3, _, _>, 3); + table[DUP4 as usize] = Instruction::new(stack::dup::<4, _, _>, 3); + table[DUP5 as usize] = Instruction::new(stack::dup::<5, _, _>, 3); + table[DUP6 as usize] = Instruction::new(stack::dup::<6, _, _>, 3); + table[DUP7 as usize] = Instruction::new(stack::dup::<7, _, _>, 3); + table[DUP8 as usize] = Instruction::new(stack::dup::<8, _, _>, 3); + table[DUP9 as usize] = Instruction::new(stack::dup::<9, _, _>, 3); + table[DUP10 as usize] = Instruction::new(stack::dup::<10, _, _>, 3); + table[DUP11 as usize] = Instruction::new(stack::dup::<11, _, _>, 3); + table[DUP12 as usize] = Instruction::new(stack::dup::<12, _, _>, 3); + table[DUP13 as usize] = Instruction::new(stack::dup::<13, _, _>, 3); + table[DUP14 as usize] = Instruction::new(stack::dup::<14, _, _>, 3); + table[DUP15 as usize] = Instruction::new(stack::dup::<15, _, _>, 3); + table[DUP16 as usize] = Instruction::new(stack::dup::<16, _, _>, 3); + + table[SWAP1 as usize] = Instruction::new(stack::swap::<1, _, _>, 3); + table[SWAP2 as usize] = Instruction::new(stack::swap::<2, _, _>, 3); + table[SWAP3 as usize] = Instruction::new(stack::swap::<3, _, _>, 3); + table[SWAP4 as usize] = Instruction::new(stack::swap::<4, _, _>, 3); + table[SWAP5 as usize] = Instruction::new(stack::swap::<5, _, _>, 3); + table[SWAP6 as usize] = Instruction::new(stack::swap::<6, _, _>, 3); + table[SWAP7 as usize] = Instruction::new(stack::swap::<7, _, _>, 3); + table[SWAP8 as usize] = Instruction::new(stack::swap::<8, _, _>, 3); + table[SWAP9 as usize] = Instruction::new(stack::swap::<9, _, _>, 3); + table[SWAP10 as usize] = Instruction::new(stack::swap::<10, _, _>, 3); + table[SWAP11 as usize] = Instruction::new(stack::swap::<11, _, _>, 3); + table[SWAP12 as usize] = Instruction::new(stack::swap::<12, _, _>, 3); + table[SWAP13 as usize] = Instruction::new(stack::swap::<13, _, _>, 3); + table[SWAP14 as usize] = Instruction::new(stack::swap::<14, _, _>, 3); + 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[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[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[STATICCALL as usize] = Instruction::new(contract::static_call, 0); // dynamic + 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 } @@ -227,7 +265,7 @@ mod tests { for (i, instr) in instr_table.iter().enumerate() { let is_opcode_unknown = OpCode::new(i as u8).is_none(); // - let is_instr_unknown = std::ptr::fn_addr_eq(*instr, unknown_istr); + let is_instr_unknown = std::ptr::fn_addr_eq(instr.fn_, unknown_istr.fn_); assert_eq!( is_instr_unknown, is_opcode_unknown, "Opcode 0x{i:X?} is not handled", diff --git a/crates/interpreter/src/instructions/arithmetic.rs b/crates/interpreter/src/instructions/arithmetic.rs index 7575cd167d..68333c9385 100644 --- a/crates/interpreter/src/instructions/arithmetic.rs +++ b/crates/interpreter/src/instructions/arithmetic.rs @@ -8,28 +8,28 @@ use primitives::U256; /// Implements the ADD instruction - adds two values from stack. pub fn add(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::VERYLOW); + //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); + //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); + //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); + //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); if !op2.is_zero() { *op2 = op1.wrapping_div(*op2); @@ -40,7 +40,7 @@ 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); + //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); *op2 = i256_div(op1, *op2); } @@ -49,7 +49,7 @@ 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); + //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); if !op2.is_zero() { *op2 = op1.wrapping_rem(*op2); @@ -60,7 +60,7 @@ 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); + //gas!(context.interpreter, gas::LOW); popn_top!([op1], op2, context.interpreter); *op2 = i256_mod(op1, *op2) } @@ -69,7 +69,7 @@ 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); + //gas!(context.interpreter, gas::MID); popn_top!([op1, op2], op3, context.interpreter); *op3 = op1.add_mod(op2, *op3) } @@ -78,7 +78,7 @@ 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); + //gas!(context.interpreter, gas::MID); popn_top!([op1, op2], op3, context.interpreter); *op3 = op1.mul_mod(op2, *op3) } @@ -121,7 +121,7 @@ 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); + //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 18696e7871..d07f7638e1 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -1,6 +1,5 @@ use super::i256::i256_cmp; use crate::{ - gas, interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr}, InstructionContext, }; @@ -9,14 +8,14 @@ use primitives::U256; /// Implements the LT instruction - less than comparison. pub fn lt(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::VERYLOW); + //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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = U256::from(op1 > *op2); @@ -25,7 +24,7 @@ pub fn gt(context: InstructionContext<'_, H, /// Implements the CLZ instruction - count leading zeros. pub fn clz(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, OSAKA); - gas!(context.interpreter, gas::LOW); + //gas!(context.interpreter, gas::LOW); popn_top!([], op1, context.interpreter); let leading_zeros = op1.leading_zeros(); @@ -36,7 +35,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Less); @@ -46,7 +45,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = U256::from(i256_cmp(&op1, op2) == Ordering::Greater); @@ -56,7 +55,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = U256::from(op1 == *op2); @@ -66,7 +65,7 @@ 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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([], op1, context.interpreter); *op1 = U256::from(op1.is_zero()); } @@ -75,7 +74,7 @@ pub fn iszero(context: InstructionContext<'_, /// /// Bitwise AND of two values from stack. pub fn bitand(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::VERYLOW); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = op1 & *op2; } @@ -84,7 +83,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = op1 | *op2; @@ -94,7 +93,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); *op2 = op1 ^ *op2; @@ -104,7 +103,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([], op1, context.interpreter); *op1 = !*op1; @@ -114,7 +113,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); let o1 = as_usize_saturated!(op1); @@ -129,7 +128,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); let shift = as_usize_saturated!(op1); @@ -143,7 +142,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); let shift = as_usize_saturated!(op1); @@ -157,7 +156,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); + //gas!(context.interpreter, gas::VERYLOW); popn_top!([op1], op2, context.interpreter); let shift = as_usize_saturated!(op1); diff --git a/crates/interpreter/src/instructions/block_info.rs b/crates/interpreter/src/instructions/block_info.rs index 2e7b251c4b..0dff4a6ad1 100644 --- a/crates/interpreter/src/instructions/block_info.rs +++ b/crates/interpreter/src/instructions/block_info.rs @@ -1,5 +1,4 @@ use crate::{ - gas, interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr}, Host, }; @@ -10,7 +9,7 @@ use crate::InstructionContext; /// EIP-1344: ChainID opcode pub fn chainid(context: InstructionContext<'_, H, WIRE>) { check!(context.interpreter, ISTANBUL); - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.chain_id()); } @@ -20,7 +19,7 @@ pub fn chainid(context: InstructionCon pub fn coinbase( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context.host.beneficiary().into_word().into() @@ -33,7 +32,7 @@ pub fn coinbase( pub fn timestamp( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.timestamp()); } @@ -43,7 +42,7 @@ pub fn timestamp( pub fn block_number( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, U256::from(context.host.block_number())); } @@ -53,7 +52,7 @@ pub fn block_number( pub fn difficulty( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); if context .interpreter .runtime_flag @@ -73,14 +72,14 @@ pub fn difficulty( pub fn gaslimit( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BASE); + //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); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.basefee()); } @@ -89,6 +88,6 @@ pub fn blob_basefee( context: InstructionContext<'_, H, WIRE>, ) { check!(context.interpreter, CANCUN); - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.host.blob_gasprice()); } diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 58502560ca..66224360c4 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -1,5 +1,4 @@ use crate::{ - gas, interpreter::Interpreter, interpreter_types::{InterpreterTypes, Jumps, LoopControl, MemoryTr, RuntimeFlag, StackTr}, InstructionResult, InterpreterAction, @@ -12,7 +11,7 @@ use crate::InstructionContext; /// /// Unconditional jump to a valid destination. pub fn jump(context: InstructionContext<'_, H, ITy>) { - gas!(context.interpreter, gas::MID); + //gas!(context.interpreter, gas::MID); popn!([target], context.interpreter); jump_inner(context.interpreter, target); } @@ -21,7 +20,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); + //gas!(context.interpreter, gas::HIGH); popn!([target, cond], context.interpreter); if !cond.is_zero() { @@ -46,15 +45,15 @@ 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>) { + //gas!(context.interpreter, gas::JUMPDEST); } /// Implements the PC instruction. /// /// Pushes the current program counter onto the stack. pub fn pc(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); // - 1 because we have already advanced the instruction pointer in `Interpreter::step` push!( context.interpreter, @@ -71,7 +70,7 @@ fn return_inner( instruction_result: InstructionResult, ) { // Zero gas cost - // gas!(interpreter, gas::ZERO) + // //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 diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 70245220e8..4fb362e7a9 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -43,7 +43,7 @@ pub fn selfbalance( context: InstructionContext<'_, H, WIRE>, ) { check!(context.interpreter, ISTANBUL); - gas!(context.interpreter, gas::LOW); + //gas!(context.interpreter, gas::LOW); let Some(balance) = context .host @@ -154,7 +154,7 @@ pub fn extcodecopy( pub fn blockhash( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BLOCKHASH); + //gas!(context.interpreter, gas::BLOCKHASH); popn_top!([], number, context.interpreter); let requested_number = *number; @@ -261,7 +261,7 @@ 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); + //gas!(context.interpreter, gas::WARM_STORAGE_READ_COST); popn!([index, value], context.interpreter); @@ -274,7 +274,7 @@ 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); + //gas!(context.interpreter, gas::WARM_STORAGE_READ_COST); popn_top!([], index, context.interpreter); diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 300a7bfdac..cb62af05df 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -62,7 +62,7 @@ macro_rules! gas { }; ($interpreter:expr, $gas:expr, $ret:expr) => { if !$interpreter.gas.record_cost($gas) { - $interpreter.halt($crate::InstructionResult::OutOfGas); + $interpreter.halt_oog(); return $ret; } }; @@ -79,7 +79,7 @@ macro_rules! gas_or_fail { match $gas { Some(gas_used) => $crate::gas!($interpreter, gas_used, $ret), None => { - $interpreter.halt($crate::InstructionResult::OutOfGas); + $interpreter.halt_oog(); return $ret; } } diff --git a/crates/interpreter/src/instructions/memory.rs b/crates/interpreter/src/instructions/memory.rs index dff34d12c1..9a48d88f3d 100644 --- a/crates/interpreter/src/instructions/memory.rs +++ b/crates/interpreter/src/instructions/memory.rs @@ -11,7 +11,7 @@ use crate::InstructionContext; /// /// Loads a 32-byte word from memory. pub fn mload(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::VERYLOW); + //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 +23,7 @@ pub fn mload(context: InstructionContext<'_, /// /// Stores a 32-byte word to memory. pub fn mstore(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::VERYLOW); + //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 +37,7 @@ pub fn mstore(context: InstructionContext<'_, /// /// Stores a single byte to memory. pub fn mstore8(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::VERYLOW); + //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 +48,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.memory.size()) diff --git a/crates/interpreter/src/instructions/stack.rs b/crates/interpreter/src/instructions/stack.rs index cdfdceccd0..822e6240d7 100644 --- a/crates/interpreter/src/instructions/stack.rs +++ b/crates/interpreter/src/instructions/stack.rs @@ -1,5 +1,4 @@ use crate::{ - gas, interpreter_types::{Immediates, InterpreterTypes, Jumps, RuntimeFlag, StackTr}, InstructionResult, }; @@ -11,7 +10,7 @@ use crate::InstructionContext; /// /// Removes the top item from the stack. pub fn pop(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); // Can ignore return. as relative N jump is safe operation. popn!([_i], context.interpreter); } @@ -21,7 +20,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, U256::ZERO); } @@ -31,7 +30,7 @@ pub fn push0(context: InstructionContext<'_, pub fn push( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::VERYLOW); + //gas!(context.interpreter, gas::VERYLOW); let slice = context.interpreter.bytecode.read_slice(N); if !context.interpreter.stack.push_slice(slice) { @@ -49,7 +48,7 @@ pub fn push( pub fn dup( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::VERYLOW); + //gas!(context.interpreter, gas::VERYLOW); if !context.interpreter.stack.dup(N) { context.interpreter.halt(InstructionResult::StackOverflow); } @@ -61,7 +60,7 @@ pub fn dup( pub fn swap( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::VERYLOW); + //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 6d3ba86570..0bea684e7f 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -32,7 +32,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context @@ -48,7 +48,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context @@ -64,7 +64,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.bytecode.bytecode_len()) @@ -95,7 +95,7 @@ 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); + //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,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.input.input().len()) @@ -144,7 +144,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!(context.interpreter, context.interpreter.input.call_value()); } @@ -180,7 +180,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.return_data.buffer().len()) @@ -219,7 +219,7 @@ 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); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.interpreter.gas.remaining()) diff --git a/crates/interpreter/src/instructions/tx_info.rs b/crates/interpreter/src/instructions/tx_info.rs index 745c99a6be..9f0e9f38cb 100644 --- a/crates/interpreter/src/instructions/tx_info.rs +++ b/crates/interpreter/src/instructions/tx_info.rs @@ -1,5 +1,4 @@ use crate::{ - gas, interpreter_types::{InterpreterTypes, RuntimeFlag, StackTr}, Host, }; @@ -13,7 +12,7 @@ use crate::InstructionContext; pub fn gasprice( context: InstructionContext<'_, H, WIRE>, ) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, U256::from(context.host.effective_gas_price()) @@ -24,7 +23,7 @@ pub fn gasprice( /// /// Gets the execution origination address. pub fn origin(context: InstructionContext<'_, H, WIRE>) { - gas!(context.interpreter, gas::BASE); + //gas!(context.interpreter, gas::BASE); push!( context.interpreter, context.host.caller().into_word().into() @@ -38,7 +37,7 @@ pub fn blob_hash( context: InstructionContext<'_, H, WIRE>, ) { check!(context.interpreter, CANCUN); - gas!(context.interpreter, gas::VERYLOW); + //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 fffb852393..ba858d8a40 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -195,7 +195,8 @@ impl Interpreter { pub fn take_next_action(&mut self) -> InterpreterAction { self.bytecode.reset_action(); // Return next action if it is some. - core::mem::take(self.bytecode.action()).expect("Interpreter to set action") + let action = core::mem::take(self.bytecode.action()).expect("Interpreter to set action"); + action } /// Halt the interpreter with the given result. @@ -208,6 +209,14 @@ impl Interpreter { .set_action(InterpreterAction::new_halt(result, self.gas)); } + /// Halt the interpreter with an out-of-gas error. + #[cold] + #[inline(never)] + pub fn halt_oog(&mut self) { + self.gas.spend_all(); + self.halt(InstructionResult::OutOfGas); + } + /// Return with the given output. /// /// This will set the action to [`InterpreterAction::Return`] and set the gas to the current gas. @@ -223,12 +232,29 @@ impl Interpreter { /// /// Internally it will increment instruction pointer by one. #[inline] - pub fn step(&mut self, instruction_table: &InstructionTable, host: &mut H) { + pub fn step( + &mut self, + instruction_table: &InstructionTable, + host: &mut H, + ) { + // Get current opcode. + let opcode = self.bytecode.opcode(); + + // SAFETY: In analysis we are doing padding of bytecode so that we are sure that last + // byte instruction is STOP so we are safe to just increment program_counter bcs on last instruction + // it will do noop and just stop execution of this contract + self.bytecode.relative_jump(1); + + let instruction = unsafe { instruction_table.get_unchecked(opcode as usize) }; + + if self.gas.record_cost_unsafe(instruction.static_gas()) { + return self.halt_oog(); + } let context = InstructionContext { interpreter: self, host, }; - context.step(instruction_table); + instruction.execute(context); } /// Executes the instruction at the current instruction pointer. @@ -243,7 +269,7 @@ impl Interpreter { /// Executes the interpreter until it returns or stops. #[inline] - pub fn run_plain( + pub fn run_plain( &mut self, instruction_table: &InstructionTable, host: &mut H, @@ -255,6 +281,24 @@ impl Interpreter { } } +/* used for cargo asm +pub fn asm_step( + interpreter: &mut Interpreter, + instruction_table: &InstructionTable, + host: &mut DummyHost, +) { + interpreter.step(instruction_table, host); +} + +pub fn asm_run( + interpreter: &mut Interpreter, + instruction_table: &InstructionTable, + host: &mut DummyHost, +) { + interpreter.run_plain(instruction_table, host); +} +*/ + /// The result of an interpreter operation. #[derive(Clone, Debug, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] diff --git a/crates/interpreter/src/interpreter/ext_bytecode.rs b/crates/interpreter/src/interpreter/ext_bytecode.rs index 53852803cc..bbfc7030bf 100644 --- a/crates/interpreter/src/interpreter/ext_bytecode.rs +++ b/crates/interpreter/src/interpreter/ext_bytecode.rs @@ -10,6 +10,10 @@ mod serde; /// Extended bytecode structure that wraps base bytecode with additional execution metadata. #[derive(Debug)] pub struct ExtBytecode { + /// The current instruction pointer. + instruction_pointer: *const u8, + /// Whether the execution should continue. + continue_execution: bool, /// Bytecode Keccak-256 hash. /// This is `None` if it hasn't been calculated yet. /// Since it's not necessary for execution, it's not calculated by default. @@ -17,11 +21,8 @@ pub struct ExtBytecode { /// Actions that the EVM should do. It contains return value of the Interpreter or inputs for `CALL` or `CREATE` instructions. /// For `RETURN` or `REVERT` instructions it contains the result of the instruction. pub action: Option, - has_set_action: bool, /// The base bytecode. base: Bytecode, - /// The current instruction pointer. - instruction_pointer: *const u8, } impl Deref for ExtBytecode { @@ -63,7 +64,7 @@ impl ExtBytecode { instruction_pointer, bytecode_hash: hash, action: None, - has_set_action: false, + continue_execution: true, } } @@ -103,28 +104,28 @@ impl ExtBytecode { impl LoopControl for ExtBytecode { #[inline] - fn is_end(&self) -> bool { - self.has_set_action + fn is_not_end(&self) -> bool { + self.continue_execution } #[inline] fn reset_action(&mut self) { - self.has_set_action = false; + self.continue_execution = true; } #[inline] fn set_action(&mut self, action: InterpreterAction) { debug_assert_eq!( - self.has_set_action, + !self.continue_execution, self.action.is_some(), "has_set_action out of sync" ); debug_assert!( - !self.has_set_action, + self.continue_execution, "action already set;\nold: {:#?}\nnew: {:#?}", self.action, action, ); - self.has_set_action = true; + self.continue_execution = false; self.action = Some(action); } diff --git a/crates/interpreter/src/interpreter_action.rs b/crates/interpreter/src/interpreter_action.rs index 08743e8885..83cf29741f 100644 --- a/crates/interpreter/src/interpreter_action.rs +++ b/crates/interpreter/src/interpreter_action.rs @@ -54,23 +54,36 @@ pub enum InterpreterAction { impl InterpreterAction { /// Returns `true` if action is call. + #[inline] pub fn is_call(&self) -> bool { matches!(self, InterpreterAction::NewFrame(FrameInput::Call(..))) } /// Returns `true` if action is create. + #[inline] pub fn is_create(&self) -> bool { matches!(self, InterpreterAction::NewFrame(FrameInput::Create(..))) } /// Returns `true` if action is return. + #[inline] pub fn is_return(&self) -> bool { matches!(self, InterpreterAction::Return { .. }) } + /// Returns [`Gas`] if action is return. + #[inline] + pub fn gas_mut(&mut self) -> Option<&mut Gas> { + match self { + InterpreterAction::Return(result) => Some(&mut result.gas), + _ => None, + } + } + /// Returns [`InterpreterResult`] if action is return. /// /// Else it returns [None]. + #[inline] pub fn into_result_return(self) -> Option { match self { InterpreterAction::Return(result) => Some(result), @@ -81,6 +94,7 @@ impl InterpreterAction { /// Returns [`InstructionResult`] if action is return. /// /// Else it returns [None]. + #[inline] pub fn instruction_result(&self) -> Option { match self { InterpreterAction::Return(result) => Some(result.result), @@ -89,21 +103,25 @@ impl InterpreterAction { } /// Create new frame action with the given frame input. + #[inline] pub fn new_frame(frame_input: FrameInput) -> Self { Self::NewFrame(frame_input) } /// Create new halt action with the given result and gas. + #[inline] pub fn new_halt(result: InstructionResult, gas: Gas) -> Self { Self::Return(InterpreterResult::new(result, Bytes::new(), gas)) } /// Create new return action with the given result, output and gas. + #[inline] pub fn new_return(result: InstructionResult, output: Bytes, gas: Gas) -> Self { Self::Return(InterpreterResult::new(result, output, gas)) } /// Create new stop action. + #[inline] pub fn new_stop() -> Self { Self::Return(InterpreterResult::new( InstructionResult::Stop, diff --git a/crates/interpreter/src/interpreter_types.rs b/crates/interpreter/src/interpreter_types.rs index c369e20dbc..4c152336a3 100644 --- a/crates/interpreter/src/interpreter_types.rs +++ b/crates/interpreter/src/interpreter_types.rs @@ -248,12 +248,12 @@ pub trait ReturnData { /// Trait controls execution of the loop. pub trait LoopControl { /// Returns `true` if the loop should continue. + fn is_not_end(&self) -> bool; + /// Is end of the loop. #[inline] - fn is_not_end(&self) -> bool { - !self.is_end() + fn is_end(&self) -> bool { + !self.is_not_end() } - /// Is end of the loop. - fn is_end(&self) -> bool; /// Sets the `end` flag internally. Action should be taken after. fn reset_action(&mut self); /// Set return action. diff --git a/examples/custom_opcodes/src/main.rs b/examples/custom_opcodes/src/main.rs index c08305de5f..c81d99f238 100644 --- a/examples/custom_opcodes/src/main.rs +++ b/examples/custom_opcodes/src/main.rs @@ -10,7 +10,7 @@ use revm::{ interpreter::{ interpreter::EthInterpreter, interpreter_types::{Immediates, Jumps}, - InstructionContext, + Instruction, InstructionContext, }, primitives::TxKind, state::Bytecode, @@ -41,10 +41,13 @@ pub fn main() { // insert our custom opcode instructions.insert_instruction( MY_STATIC_JUMP, - |ctx: InstructionContext<'_, _, EthInterpreter>| { - let offset = ctx.interpreter.bytecode.read_i16(); - ctx.interpreter.bytecode.relative_jump(offset as isize); - }, + Instruction::new( + |ctx: InstructionContext<'_, _, EthInterpreter>| { + let offset = ctx.interpreter.bytecode.read_i16(); + ctx.interpreter.bytecode.relative_jump(offset as isize); + }, + 0, + ), ); // Create a new EVM instance. From 8cee9588f2f1c8eb5f38ee3ce5b9736dde773ac4 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 4 Aug 2025 13:10:25 +0200 Subject: [PATCH 37/78] chore: rm commented code (#2839) * chore: rm commented code * chore: remove unused commented code --- crates/handler/src/frame.rs | 120 ------------------------------- crates/handler/src/validation.rs | 64 ----------------- 2 files changed, 184 deletions(-) diff --git a/crates/handler/src/frame.rs b/crates/handler/src/frame.rs index dd2cd5d9e8..823ec568df 100644 --- a/crates/handler/src/frame.rs +++ b/crates/handler/src/frame.rs @@ -361,126 +361,6 @@ impl EthFrame { Ok(ItemOrResult::Item(this.consume())) } - /* - /// Make create frame. - #[inline] - pub fn make_eofcreate_frame( - mut this: OutFrame<'_, Self>, - evm: &mut EVM, - depth: usize, - memory: SharedMemory, - inputs: Box, - ) -> Result, ERROR> { - let context = evm.ctx(); - let spec = context.cfg().spec().into(); - let return_error = |e| { - Ok(ItemOrResult::Result(FrameResult::EOFCreate( - CreateOutcome { - result: InterpreterResult { - result: e, - gas: Gas::new(inputs.gas_limit), - output: Bytes::new(), - }, - address: None, - }, - ))) - }; - - let (input, initcode, created_address) = match &inputs.kind { - EOFCreateKind::Opcode { - initcode, - input, - created_address, - } => (input.clone(), initcode.clone(), Some(*created_address)), - EOFCreateKind::Tx { .. } => { - // Decode eof and init code. - // TODO : Handle inc_nonce handling more gracefully. - // let Ok((eof, input)) = Eof::decode_dangling(initdata.clone()) else { - // context.journal_mut().inc_account_nonce(inputs.caller)?; - // return return_error(InstructionResult::InvalidEOFInitCode); - // }; - - // if eof.validate().is_err() { - // // TODO : (EOF) New error type. - // context.journal_mut().inc_account_nonce(inputs.caller)?; - // return return_error(InstructionResult::InvalidEOFInitCode); - // } - - // // Use nonce from tx to calculate address. - // let tx = context.tx(); - // let create_address = tx.caller().create(tx.nonce()); - unreachable!("EOF is disabled"); - //(CallInput::Bytes(input), eof, Some(create_address)) - } - }; - - // Check depth - if depth > CALL_STACK_LIMIT as usize { - return return_error(InstructionResult::CallTooDeep); - } - - // Fetch balance of caller. - let caller = context.journal_mut().load_account(inputs.caller)?.data; - - // Check if caller has enough balance to send to the created contract. - if caller.info.balance < inputs.value { - return return_error(InstructionResult::OutOfFunds); - } - - // Increase nonce of caller and check if it overflows - let Some(new_nonce) = caller.info.nonce.checked_add(1) else { - // Can't happen on mainnet. - return return_error(InstructionResult::Return); - }; - caller.info.nonce = new_nonce; - context - .journal_mut() - .nonce_bump_journal_entry(inputs.caller); - - let old_nonce = new_nonce - 1; - - let created_address = created_address.unwrap_or_else(|| inputs.caller.create(old_nonce)); - - // Load account so it needs to be marked as warm for access list. - context.journal_mut().load_account(created_address)?; - - // Create account, transfer funds and make the journal checkpoint. - let checkpoint = match context.journal_mut().create_account_checkpoint( - inputs.caller, - created_address, - inputs.value, - spec, - ) { - Ok(checkpoint) => checkpoint, - Err(e) => return return_error(e.into()), - }; - - let interpreter_input = InputsImpl { - target_address: created_address, - caller_address: inputs.caller, - bytecode_address: None, - input, - call_value: inputs.value, - }; - - let gas_limit = inputs.gas_limit; - this.get(EthFrame::invalid).clear( - FrameData::EOFCreate(EOFCreateFrame { created_address }), - FrameInput::EOFCreate(inputs), - depth, - memory, - ExtBytecode::new(Bytecode::Eof(initcode)), - interpreter_input, - false, - true, - spec, - gas_limit, - checkpoint, - ); - Ok(ItemOrResult::Item(this.consume())) - } - */ - /// Initializes a frame with the given context and precompiles. pub fn init_with_context< CTX: ContextTr, diff --git a/crates/handler/src/validation.rs b/crates/handler/src/validation.rs index 52cb0fbb3d..241022bf9f 100644 --- a/crates/handler/src/validation.rs +++ b/crates/handler/src/validation.rs @@ -195,32 +195,6 @@ pub fn validate_tx_env( return Err(InvalidTransaction::EmptyAuthorizationList); } } - /* // TODO(EOF) EOF removed from spec. - TransactionType::Eip7873 => { - // Check if EIP-7873 transaction is enabled. - if !spec_id.is_enabled_in(SpecId::OSAKA) { - return Err(InvalidTransaction::Eip7873NotSupported); - } - // validate chain id - if Some(context.cfg().chain_id()) != tx.chain_id() { - return Err(InvalidTransaction::InvalidChainId); - } - - // validate initcodes. - validate_eip7873_initcodes(tx.initcodes())?; - - // InitcodeTransaction is invalid if the to is nil. - if tx.kind().is_create() { - return Err(InvalidTransaction::Eip7873MissingTarget); - } - - validate_priority_fee_tx( - tx.max_fee_per_gas(), - tx.max_priority_fee_per_gas().unwrap_or_default(), - base_fee, - )?; - } - */ TransactionType::Custom => { // Custom transaction type check is not done here. } @@ -243,44 +217,6 @@ pub fn validate_tx_env( Ok(()) } -/* TODO(EOF) -/// Validate Initcode Transaction initcode list, return error if any of the following conditions are met: -/// * there are zero entries in initcodes, or if there are more than MAX_INITCODE_COUNT entries. -/// * any entry in initcodes is zero length, or if any entry exceeds MAX_INITCODE_SIZE. -/// * the to is nil. -pub fn validate_eip7873_initcodes(initcodes: &[Bytes]) -> Result<(), InvalidTransaction> { - let mut i = 0; - for initcode in initcodes { - // InitcodeTransaction is invalid if any entry in initcodes is zero length - if initcode.is_empty() { - return Err(InvalidTransaction::Eip7873EmptyInitcode { i }); - } - - // or if any entry exceeds MAX_INITCODE_SIZE. - if initcode.len() > MAX_INITCODE_SIZE { - return Err(InvalidTransaction::Eip7873InitcodeTooLarge { - i, - size: initcode.len(), - }); - } - - i += 1; - } - - // InitcodeTransaction is invalid if there are zero entries in initcodes, - if i == 0 { - return Err(InvalidTransaction::Eip7873EmptyInitcodeList); - } - - // or if there are more than MAX_INITCODE_COUNT entries. - if i > MAX_INITCODE_COUNT { - return Err(InvalidTransaction::Eip7873TooManyInitcodes { size: i }); - } - - Ok(()) -} -*/ - /// Validate initial transaction gas. pub fn validate_initial_tx_gas( tx: impl Transaction, From f0233379f627c4f414ce6fbcfbacecfdcc11ece7 Mon Sep 17 00:00:00 2001 From: Maxim Evtush <154841002+maximevtush@users.noreply.github.com> Date: Mon, 4 Aug 2025 14:52:21 +0300 Subject: [PATCH 38/78] chore: update README.md (#2842) --- README.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d0b30177e6..e9e6d1d697 100644 --- a/README.md +++ b/README.md @@ -51,13 +51,13 @@ The [book](https://bluealloy.github.io/revm/) and [`Architecture and API`](https 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 can be found here. [book](https://bluealloy.github.io/revm/dev.html) -* Architecture overview can be seen here. [book](https://bluealloy.github.io/revm/architecture.html) -* Structure of the project (list of crates and their versions) can be seen here. [book](https://github.com/bluealloy/revm/tree/main/crates) -* How to use Revm Framework can be found in MyEvm example. [book](https://github.com/bluealloy/revm/tree/main/examples/my_evm) -* Release procedure and changelogs explanation. [book](https://bluealloy.github.io/revm/release_procedure.html) -* How to use revme (Revm binary with few commands) can be found here. [code](https://github.com/bluealloy/revm/tree/main/bins/revme) -* How to run Ethereum test can be found here: [book](https://bluealloy.github.io/revm/revme.html#running-eth-tests) +* [How to build and use revm](https://bluealloy.github.io/revm/dev.html) +* [Architecture overview](https://bluealloy.github.io/revm/architecture.html) +* [Structure of the project](https://github.com/bluealloy/revm/tree/main/crates) (list of crates and their versions) +* [How to use Revm Framework](https://github.com/bluealloy/revm/tree/main/examples/my_evm) (MyEvm example) +* [Release procedure and changelogs explanation](https://bluealloy.github.io/revm/release_procedure.html) +* [How to use revme](https://github.com/bluealloy/revm/tree/main/bins/revme) (Revm binary with few commands) +* [How to run Ethereum tests](https://bluealloy.github.io/revm/revme.html#running-eth-tests) * If there is more need for explanations please open a PR request. ## Supported Rust Versions (MSRV) @@ -67,7 +67,7 @@ Revm always aims to stay up-to-date with the latest stable Rust release. The Minimum Supported Rust Version (MSRV) may be updated at any time, so we can take advantage of new features and improvements in Rust. ### Community: -For questions please open a github issue or join the public telegram group: [https://t.me/+Ig4WDWOzikA3MzA0](https://t.me/+Ig4WDWOzikA3MzA0) +For questions please open a github issue or join the public [telegram group](https://t.me/+Ig4WDWOzikA3MzA0) ### Licence Revm is licensed under MIT Licence. From fd52a1fb531f4627ea7e69780aab56536533269d Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 4 Aug 2025 13:52:42 +0200 Subject: [PATCH 39/78] chore: specialize halt, making instruction code very slightly smaller (#2840) --- crates/interpreter/src/instructions/macros.rs | 10 +++---- crates/interpreter/src/interpreter.rs | 28 +++++++++++++++++++ 2 files changed, 33 insertions(+), 5 deletions(-) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index cb62af05df..8904830211 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -47,7 +47,7 @@ macro_rules! check { .spec_id() .is_enabled_in(primitives::hardfork::SpecId::$min) { - $interpreter.halt($crate::InstructionResult::NotActivated); + $interpreter.halt_not_activated(); return; } }; @@ -101,7 +101,7 @@ macro_rules! resize_memory { $offset, $len, ) { - $interpreter.halt($crate::InstructionResult::MemoryOOG); + $interpreter.halt_memory_oog(); return $ret; } }; @@ -113,7 +113,7 @@ macro_rules! resize_memory { macro_rules! popn { ([ $($x:ident),* ],$interpreter:expr $(,$ret:expr)? ) => { let Some([$( $x ),*]) = $interpreter.stack.popn() else { - $interpreter.halt($crate::InstructionResult::StackUnderflow); + $interpreter.halt_underflow(); return $($ret)?; }; }; @@ -142,7 +142,7 @@ macro_rules! popn_top { // Workaround for https://github.com/rust-lang/rust/issues/144329. if $interpreter.stack.len() < (1 + $crate::_count!($($x)*)) { - $interpreter.halt($crate::InstructionResult::StackUnderflow); + $interpreter.halt_underflow(); return $($ret)?; } let ([$( $x ),*], $top) = unsafe { $interpreter.stack.popn_top().unwrap_unchecked() }; @@ -155,7 +155,7 @@ macro_rules! popn_top { macro_rules! push { ($interpreter:expr, $x:expr $(,$ret:item)?) => ( if !($interpreter.stack.push($x)) { - $interpreter.halt($crate::InstructionResult::StackOverflow); + $interpreter.halt_overflow(); return $($ret)?; } ) diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index ba858d8a40..aa77301911 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -217,6 +217,34 @@ impl Interpreter { self.halt(InstructionResult::OutOfGas); } + /// Halt the interpreter with an out-of-gas error. + #[cold] + #[inline(never)] + pub fn halt_memory_oog(&mut self) { + self.halt(InstructionResult::MemoryLimitOOG); + } + + /// Halt the interpreter with and overflow error. + #[cold] + #[inline(never)] + pub fn halt_overflow(&mut self) { + self.halt(InstructionResult::StackOverflow); + } + + /// Halt the interpreter with and underflow error. + #[cold] + #[inline(never)] + pub fn halt_underflow(&mut self) { + self.halt(InstructionResult::StackUnderflow); + } + + /// Halt the interpreter with and not activated error. + #[cold] + #[inline(never)] + pub fn halt_not_activated(&mut self) { + self.halt(InstructionResult::NotActivated); + } + /// Return with the given output. /// /// This will set the action to [`InterpreterAction::Return`] and set the gas to the current gas. From bc2be1946635666d3d90d47d22dce5252e9c59ce Mon Sep 17 00:00:00 2001 From: kilavvy <140459108+kilavvy@users.noreply.github.com> Date: Mon, 4 Aug 2025 14:17:29 +0200 Subject: [PATCH 40/78] chore: improve link formatting and fix grammar in revme.md documentation (#2843) * Update revme.md * Apply suggestion from @rakita --------- Co-authored-by: rakita --- book/src/revme.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/revme.md b/book/src/revme.md index 90cb09f2f0..bc0818d58b 100644 --- a/book/src/revme.md +++ b/book/src/revme.md @@ -22,12 +22,12 @@ Options: Eth tests are a suite of tests from the Ethereum Foundation that are used to test EVM implementations. Part of these tests are included in the revm repository in the `tests` folder. -Test suites for the latest hardforks can be found in EEST releases https://github.com/ethereum/execution-spec-tests/releases, and there are additional tests that cover older hardforks in https://github.com/ethereum/legacytests +Test suites for the latest hardforks can be found in [EEST releases](https://github.com/ethereum/execution-spec-tests/releases), and there are additional tests that cover older hardforks in [legacytests](https://github.com/ethereum/legacytests) 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 legacy tests, we need to first to download the repo `git clone https://github.com/ethereum/legacytests` and then run it with `cargo run --release -p revme -- statetest legacytests/Cancun/GeneralStateTests ` +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. From cb5dca9c65a6e3b78951676edaa39d3495dd3801 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Tue, 5 Aug 2025 20:01:52 +0800 Subject: [PATCH 41/78] chore(OpCode): add is_valid (#2847) --- crates/bytecode/src/opcode.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index 774ddb37d7..f08b790da7 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -195,6 +195,12 @@ impl OpCode { | OpCode::STATICCALL ) } + + /// Returns true if the opcode is valid + #[inline] + pub const fn is_valid(&self) -> bool { + OPCODE_INFO[self.0 as usize].is_some() + } } impl PartialEq for OpCode { @@ -748,4 +754,29 @@ mod tests { } } } + + #[test] + #[should_panic(expected = "opcode not found")] + fn test_new_unchecked_invalid() { + let op = unsafe { OpCode::new_unchecked(0x0C) }; + op.info(); + } + + #[test] + fn test_op_code_valid() { + let op1 = OpCode::new(ADD).unwrap(); + let op2 = OpCode::new(MUL).unwrap(); + assert!(op1.is_valid()); + assert!(op2.is_valid()); + + let op3 = unsafe { OpCode::new_unchecked(0x0C) }; + assert!(!op3.is_valid()); + } + + #[test] + fn test_modifies_memory() { + assert!(OpCode::new(MLOAD).unwrap().modifies_memory()); + assert!(OpCode::new(MSTORE).unwrap().modifies_memory()); + assert!(!OpCode::new(ADD).unwrap().modifies_memory()); + } } From cfed6081123d66ab877e6d0b6c5a8316c32022b3 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 5 Aug 2025 15:14:46 +0200 Subject: [PATCH 42/78] feat: optimize access to precompile short addresses (#2846) * chore: specialize halt, making instruction code very slightly smaller * feat: optimize access to precompile short addreesses * clippy * cleaup, helper fn, short_address_cap to 300 * doc --- crates/precompile/src/lib.rs | 79 ++++++++++++++++++++++++++++++++---- 1 file changed, 72 insertions(+), 7 deletions(-) diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 03aad2c4f1..b9f81d1345 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -63,13 +63,28 @@ pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { (len as u64).div_ceil(32) * word + base } +/// Optimize short address access. +pub const SHORT_ADDRESS_CAP: usize = 300; + /// Precompiles contain map of precompile addresses to functions and HashSet of precompile addresses. -#[derive(Clone, Default, Debug)] +#[derive(Clone, Debug)] pub struct Precompiles { /// Precompiles inner: HashMap, /// Addresses of precompile addresses: HashSet
, + /// Optimized addresses filter. + optimized_access: Vec>, +} + +impl Default for Precompiles { + fn default() -> Self { + Self { + inner: HashMap::new(), + addresses: HashSet::new(), + optimized_access: vec![None; SHORT_ADDRESS_CAP], + } + } } impl Precompiles { @@ -216,6 +231,9 @@ impl Precompiles { /// Returns the precompile for the given address. #[inline] pub fn get(&self, address: &Address) -> Option<&PrecompileFn> { + if let Some(short_address) = short_address(address) { + return self.optimized_access[short_address].as_ref(); + } self.inner.get(address) } @@ -246,6 +264,12 @@ impl 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.0) { + self.optimized_access[short_address] = Some(item.1); + } + } + self.addresses.extend(items.iter().map(|p| *p.address())); self.inner.extend(items.into_iter().map(|p| (p.0, p.1))); } @@ -262,9 +286,9 @@ impl Precompiles { .map(|(a, p)| (*a, *p)) .collect::>(); - let addresses = inner.keys().cloned().collect::>(); - - Self { inner, addresses } + let mut precompiles = Self::default(); + precompiles.extend(inner.into_iter().map(|p| PrecompileWithAddress(p.0, p.1))); + precompiles } /// Returns intersection of `self` and `other`. @@ -279,10 +303,25 @@ impl Precompiles { .map(|(a, p)| (*a, *p)) .collect::>(); - let addresses = inner.keys().cloned().collect::>(); + let mut precompiles = Self::default(); + precompiles.extend(inner.into_iter().map(|p| PrecompileWithAddress(p.0, p.1))); + precompiles + } +} - Self { inner, addresses } +/// Returns the short address from Address. +/// +/// Short address is considered address that has 18 leading zeros +/// and last two bytes are less than [`SHORT_ADDRESS_CAP`]. +pub fn short_address(address: &Address) -> Option { + if address.0[..18].iter().all(|b| *b == 0) { + let short_address = u16::from_be_bytes(address.0[18..].try_into().unwrap()) as usize; + if short_address < SHORT_ADDRESS_CAP { + return Some(short_address); + } } + + None } /// Precompile with address and function. @@ -390,7 +429,33 @@ pub const fn u64_to_address(x: u64) -> Address { #[cfg(test)] mod test { - use crate::Precompiles; + use super::*; + + fn temp_precompile(_input: &[u8], _gas_limit: u64) -> PrecompileResult { + PrecompileResult::Err(PrecompileError::OutOfGas) + } + + #[test] + fn test_optimized_access() { + let mut precompiles = Precompiles::istanbul().clone(); + assert!(precompiles.optimized_access[9].is_some()); + assert!(precompiles.optimized_access[10].is_none()); + + precompiles.extend([PrecompileWithAddress(u64_to_address(100), temp_precompile)]); + precompiles.extend([PrecompileWithAddress(u64_to_address(101), temp_precompile)]); + + assert_eq!( + precompiles.optimized_access[100].unwrap()(&[], u64::MAX), + PrecompileResult::Err(PrecompileError::OutOfGas) + ); + + assert_eq!( + precompiles + .get(&Address::left_padding_from(&[101])) + .unwrap()(&[], u64::MAX), + PrecompileResult::Err(PrecompileError::OutOfGas) + ); + } #[test] fn test_difference_precompile_sets() { From 031aaee12a5b5f4deb5d1ad1a4ea3fa4001c2734 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 5 Aug 2025 16:05:33 +0200 Subject: [PATCH 43/78] chore(deps): bump ruint (#2811) * chore(deps): bump ruint * chore: fix test compilation Type inference breakage is acceptable. Usually only happens in tests. * chore: older commit * newer commit * update to 1.16.0 * chore: bump to crates.io --- Cargo.lock | 16 ++++++++-------- crates/interpreter/src/interpreter/stack.rs | 2 +- examples/contract_deployment/src/main.rs | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6fb4278897..fe633e46f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1375,7 +1375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" dependencies = [ "lazy_static", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -1822,7 +1822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -2598,7 +2598,7 @@ checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" dependencies = [ "hermit-abi", "libc", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4091,9 +4091,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11256b5fe8c68f56ac6f39ef0720e592f33d2367a4782740d9c9142e889c7fb4" +checksum = "9ecb38f82477f20c5c3d62ef52d7c4e536e38ea9b73fb570a20c5cae0e14bcf6" dependencies = [ "alloy-rlp", "arbitrary", @@ -4172,7 +4172,7 @@ dependencies = [ "errno", "libc", "linux-raw-sys", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -4734,7 +4734,7 @@ dependencies = [ "getrandom 0.3.3", "once_cell", "rustix", - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] @@ -5285,7 +5285,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.52.0", ] [[package]] diff --git a/crates/interpreter/src/interpreter/stack.rs b/crates/interpreter/src/interpreter/stack.rs index c835a0202a..ae675fea20 100644 --- a/crates/interpreter/src/interpreter/stack.rs +++ b/crates/interpreter/src/interpreter/stack.rs @@ -422,7 +422,7 @@ mod tests { // No-op run(|stack| { stack.push_slice(b"").unwrap(); - assert_eq!(stack.data, []); + assert!(stack.data.is_empty()); }); // One word diff --git a/examples/contract_deployment/src/main.rs b/examples/contract_deployment/src/main.rs index 6e900b8cd9..02bf76e96b 100644 --- a/examples/contract_deployment/src/main.rs +++ b/examples/contract_deployment/src/main.rs @@ -92,7 +92,7 @@ fn main() -> anyhow::Result<()> { println!("storage U256(0) at {address}: {storage0:#?}"); assert_eq!( storage0.present_value(), - param.try_into()?, + StorageValue::try_from(param)?, "{:#?}", output.result ); From 33c9eb2316fe891e8fc78d4774a5729eea3836a3 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 6 Aug 2025 13:49:17 +0200 Subject: [PATCH 44/78] fix: map new once and for all (+ci) (#2852) --- .github/workflows/ci.yml | 2 +- crates/interpreter/src/instructions.rs | 2 +- crates/precompile/src/lib.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80e2ee562b..6287685f2b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -56,7 +56,7 @@ jobs: strategy: fail-fast: false matrix: - features: ["", "serde", "std"] + features: ["", "serde", "std", "std,map-foldhash"] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable diff --git a/crates/interpreter/src/instructions.rs b/crates/interpreter/src/instructions.rs index 790a526f77..185b11b6e1 100644 --- a/crates/interpreter/src/instructions.rs +++ b/crates/interpreter/src/instructions.rs @@ -30,7 +30,7 @@ pub mod utility; use crate::{interpreter_types::InterpreterTypes, Host, InstructionContext}; /// EVM opcode function signature. -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug)] pub struct Instruction { fn_: fn(InstructionContext<'_, H, W>), static_gas: u64, diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index b9f81d1345..02f7105961 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -80,8 +80,8 @@ pub struct Precompiles { impl Default for Precompiles { fn default() -> Self { Self { - inner: HashMap::new(), - addresses: HashSet::new(), + inner: HashMap::default(), + addresses: HashSet::default(), optimized_access: vec![None; SHORT_ADDRESS_CAP], } } From 36e700594b480b075ee394ee7028184ad9135415 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Wed, 6 Aug 2025 19:49:31 +0800 Subject: [PATCH 45/78] chore: rm redundant lifetime constraints (#2850) * rm redundant lifetime constraints * format --- crates/context/interface/src/transaction/either.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/crates/context/interface/src/transaction/either.rs b/crates/context/interface/src/transaction/either.rs index 46eb43cebe..c4d6413de7 100644 --- a/crates/context/interface/src/transaction/either.rs +++ b/crates/context/interface/src/transaction/either.rs @@ -10,15 +10,9 @@ where Authorization<'a> = L::Authorization<'a>, > + 'static, { - type AccessListItem<'a> - = L::AccessListItem<'a> - where - Self: 'a; - - type Authorization<'a> - = L::Authorization<'a> - where - Self: 'a; + type AccessListItem<'a> = L::AccessListItem<'a>; + + type Authorization<'a> = L::Authorization<'a>; fn tx_type(&self) -> u8 { match self { From ac7d01f3344d40a30edc8e6f6b269892ae15fba9 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 6 Aug 2025 13:56:19 +0200 Subject: [PATCH 46/78] feat: short address for journal cold/warm check (#2849) * chore: remove warm_addresses from JournalInner * feat: short address for journal cold/warm check * cleanup * typos * all all_short_address flag --- Cargo.lock | 1 + crates/context/Cargo.toml | 3 + .../context/interface/src/journaled_state.rs | 3 - crates/context/src/journal.rs | 14 +- crates/context/src/journal/inner.rs | 65 +---- crates/context/src/journal/warm_addresses.rs | 266 ++++++++++++++++++ crates/handler/src/pre_execution.rs | 14 +- crates/interpreter/src/lib.rs | 1 - crates/precompile/src/lib.rs | 27 +- crates/primitives/src/lib.rs | 18 ++ examples/cheatcode_inspector/src/main.rs | 8 +- 11 files changed, 319 insertions(+), 101 deletions(-) create mode 100644 crates/context/src/journal/warm_addresses.rs diff --git a/Cargo.lock b/Cargo.lock index fe633e46f1..520e764388 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3806,6 +3806,7 @@ dependencies = [ name = "revm-context" version = "8.0.4" dependencies = [ + "bitvec", "cfg-if", "derive-where", "revm-bytecode", diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 6a61e6efd9..c7f5131e19 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -28,6 +28,7 @@ bytecode.workspace = true # misc derive-where.workspace = true cfg-if.workspace = true +bitvec.workspace = true # Optional serde = { workspace = true, features = ["derive", "rc"], optional = true } @@ -45,6 +46,7 @@ std = [ "database-interface/std", "primitives/std", "state/std", + "bitvec/std", ] serde = [ "dep:serde", @@ -55,6 +57,7 @@ serde = [ "database/serde", "database-interface/serde", "derive-where/serde", + "bitvec/serde", ] dev = [ "memory_limit", diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index e8ff56adc0..9d45323f14 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -66,9 +66,6 @@ pub trait JournalTr { storage_keys: impl IntoIterator, ) -> Result<(), ::Error>; - /// Warms the account. - fn warm_account(&mut self, address: Address); - /// 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 891b6907f3..206abbb4e8 100644 --- a/crates/context/src/journal.rs +++ b/crates/context/src/journal.rs @@ -4,6 +4,7 @@ //! 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 inner::JournalInner; @@ -140,24 +141,19 @@ impl JournalTr for Journal { self.inner.selfdestruct(&mut self.database, address, target) } - fn warm_account(&mut self, address: Address) { - self.inner.warm_preloaded_addresses.insert(address); - } - fn warm_coinbase_account(&mut self, address: Address) { - self.inner.warm_coinbase_address = Some(address); + self.inner.warm_addresses.set_coinbase(address); } fn warm_precompiles(&mut self, precompiles: HashSet
) { - self.inner.precompiles = precompiles; self.inner - .warm_preloaded_addresses - .clone_from(&self.inner.precompiles); + .warm_addresses + .set_precompile_addresses(precompiles); } #[inline] fn precompile_addresses(&self) -> &HashSet
{ - &self.inner.precompiles + self.inner.warm_addresses.precompiles() } /// Returns call depth. diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index fc45b372e2..a7cefb75a3 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -1,5 +1,5 @@ //! Module containing the [`JournalInner`] that is part of [`crate::Journal`]. -use crate::entry::SelfdestructionRevertStatus; +use crate::{entry::SelfdestructionRevertStatus, warm_addresses::WarmAddresses}; use super::JournalEntryTr; use bytecode::Bytecode; @@ -12,7 +12,7 @@ use database_interface::Database; use primitives::{ hardfork::SpecId::{self, *}, hash_map::Entry, - Address, HashMap, HashSet, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, + Address, HashMap, Log, StorageKey, StorageValue, B256, KECCAK_EMPTY, U256, }; use state::{Account, EvmState, EvmStorageSlot, TransientStorage}; use std::vec::Vec; @@ -53,17 +53,8 @@ pub struct JournalInner { /// [EIP-161]: https://eips.ethereum.org/EIPS/eip-161 /// [EIP-6780]: https://eips.ethereum.org/EIPS/eip-6780 pub spec: SpecId, - /// Warm loaded addresses are used to check if loaded address - /// should be considered cold or warm loaded when the account - /// is first accessed. - /// - /// Note that this not include newly loaded accounts, account and storage - /// is considered warm if it is found in the `State`. - pub warm_preloaded_addresses: HashSet
, - /// Warm coinbase address, stored separately to avoid cloning preloaded addresses. - pub warm_coinbase_address: Option
, - /// Precompile addresses - pub precompiles: HashSet
, + /// Warm addresses containing both coinbase and current precompiles. + pub warm_addresses: WarmAddresses, } impl Default for JournalInner { @@ -86,9 +77,7 @@ impl JournalInner { transaction_id: 0, depth: 0, spec: SpecId::default(), - warm_preloaded_addresses: HashSet::default(), - precompiles: HashSet::default(), - warm_coinbase_address: None, + warm_addresses: WarmAddresses::new(), } } @@ -116,13 +105,10 @@ impl JournalInner { journal, transaction_id, spec, - warm_preloaded_addresses, - precompiles, - warm_coinbase_address, + warm_addresses, } = self; // Spec precompiles and state are not changed. It is always set again execution. let _ = spec; - let _ = precompiles; let _ = state; transient_storage.clear(); *depth = 0; @@ -131,11 +117,7 @@ impl JournalInner { journal.clear(); // Clear coinbase address warming for next tx - *warm_coinbase_address = None; - // Load precompiles into warm_preloaded_addresses. - // TODO for precompiles we can use max transaction_id so they are always touched warm loaded. - // at least after state clear EIP. - reset_preloaded_addresses(warm_preloaded_addresses, precompiles); + warm_addresses.clear_coinbase(); // increment transaction id. *transaction_id += 1; logs.clear(); @@ -152,11 +134,8 @@ impl JournalInner { journal, transaction_id, spec, - warm_preloaded_addresses, - warm_coinbase_address, - precompiles, + warm_addresses, } = self; - let is_spurious_dragon_enabled = spec.is_enabled_in(SPURIOUS_DRAGON); // iterate over all journals entries and revert our global state journal.drain(..).rev().for_each(|entry| { @@ -166,9 +145,9 @@ impl JournalInner { *depth = 0; logs.clear(); *transaction_id += 1; + // Clear coinbase address warming for next tx - *warm_coinbase_address = None; - reset_preloaded_addresses(warm_preloaded_addresses, precompiles); + warm_addresses.clear_coinbase(); } /// Take the [`EvmState`] and clears the journal by resetting it to initial state. @@ -187,16 +166,12 @@ impl JournalInner { journal, transaction_id, spec, - warm_preloaded_addresses, - warm_coinbase_address, - precompiles, + warm_addresses, } = self; // Spec is not changed. And it is always set again in execution. let _ = spec; // Clear coinbase address warming for next tx - *warm_coinbase_address = None; - // Load precompiles into warm_preloaded_addresses. - reset_preloaded_addresses(warm_preloaded_addresses, precompiles); + warm_addresses.clear_coinbase(); let state = mem::take(state); logs.clear(); @@ -679,8 +654,7 @@ impl JournalInner { }; // Precompiles among some other account(coinbase included) are warm loaded so we need to take that into account - let is_cold = !self.warm_preloaded_addresses.contains(&address) - && self.warm_coinbase_address.as_ref() != Some(&address); + let is_cold = self.warm_addresses.is_cold(&address); StateLoad { data: vac.insert(account), @@ -881,16 +855,3 @@ pub fn sload_with_account( Ok(StateLoad::new(value, is_cold)) } - -fn reset_preloaded_addresses( - warm_preloaded_addresses: &mut HashSet
, - precompiles: &HashSet
, -) { - // `warm_preloaded_addresses` is append-only, and is initialized with `precompiles`. - // Avoid unnecessarily cloning if it hasn't changed. - if warm_preloaded_addresses.len() == precompiles.len() { - debug_assert_eq!(warm_preloaded_addresses, precompiles); - return; - } - warm_preloaded_addresses.clone_from(precompiles); -} diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs new file mode 100644 index 0000000000..47dbd32e02 --- /dev/null +++ b/crates/context/src/journal/warm_addresses.rs @@ -0,0 +1,266 @@ +//! This module contains [`WarmAddresses`] struct that stores addresses that are warm loaded. +//! +//! It is used to optimize access to precompile addresses. + +use bitvec::{bitvec, order::Lsb0, vec::BitVec}; +use primitives::{short_address, Address, HashSet, SHORT_ADDRESS_CAP}; + +/// Stores addresses that are warm loaded. Contains precompiles and coinbase address. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct WarmAddresses { + /// Set of warm loaded precompile addresses. + precompile_set: HashSet
, + /// Bit vector of precompile short addresses. If address is shorter than [`SHORT_ADDRESS_CAP`] it + /// 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, + /// Coinbase address. + coinbase: Option
, +} + +impl Default for WarmAddresses { + fn default() -> Self { + Self::new() + } +} + +impl WarmAddresses { + /// Create a new warm addresses instance. + #[inline] + pub fn new() -> Self { + Self { + precompile_set: HashSet::new(), + precompile_short_addresses: BitVec::new(), + all_short_addresses: true, + coinbase: None, + } + } + + /// Returns the precompile addresses. + #[inline] + pub fn precompiles(&self) -> &HashSet
{ + &self.precompile_set + } + + /// Returns the coinbase address. + #[inline] + pub fn coinbase(&self) -> Option
{ + self.coinbase + } + + /// Set the precompile addresses and short addresses. + #[inline] + pub fn set_precompile_addresses(&mut self, addresses: HashSet
) { + // short address is always smaller than SHORT_ADDRESS_CAP + self.precompile_short_addresses = bitvec![usize, Lsb0; 0; SHORT_ADDRESS_CAP]; + + let mut all_short_addresses = true; + for address in addresses.iter() { + if let Some(short_address) = short_address(address) { + self.precompile_short_addresses.set(short_address, true); + } else { + all_short_addresses = false; + } + } + + self.all_short_addresses = all_short_addresses; + self.precompile_set = addresses; + } + + /// Set the coinbase address. + #[inline] + pub fn set_coinbase(&mut self, address: Address) { + self.coinbase = Some(address); + } + + /// Clear the coinbase address. + #[inline] + pub fn clear_coinbase(&mut self) { + self.coinbase = None; + } + + /// Returns true if the address is warm loaded. + #[inline] + pub fn is_warm(&self, address: &Address) -> bool { + // check if it is coinbase + if Some(*address) == self.coinbase { + return true; + } + + // if there are no precompiles, it is cold loaded and bitvec is not set. + if self.precompile_set.is_empty() { + return false; + } + + // check if it is short precompile address + if let Some(short_address) = short_address(address) { + return self.precompile_short_addresses[short_address]; + } + + // if all precompiles are short addresses, it is cold loaded. + if self.all_short_addresses { + return false; + } + + // in the end check if it is inside precompile set + self.precompile_set.contains(address) + } + + /// Returns true if the address is cold loaded. + #[inline] + pub fn is_cold(&self, address: &Address) -> bool { + !self.is_warm(address) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use primitives::{address, Address}; + + #[test] + fn test_initialization() { + let warm_addresses = WarmAddresses::new(); + assert!(warm_addresses.precompile_set.is_empty()); + assert!(warm_addresses.precompile_short_addresses.is_empty()); + assert!(warm_addresses.coinbase.is_none()); + + // Test Default trait + let default_addresses = WarmAddresses::default(); + assert_eq!(warm_addresses, default_addresses); + } + + #[test] + fn test_coinbase_management() { + let mut warm_addresses = WarmAddresses::new(); + let coinbase_addr = address!("1234567890123456789012345678901234567890"); + + // Test setting coinbase + warm_addresses.set_coinbase(coinbase_addr); + assert_eq!(warm_addresses.coinbase, Some(coinbase_addr)); + assert!(warm_addresses.is_warm(&coinbase_addr)); + + // Test clearing coinbase + warm_addresses.clear_coinbase(); + assert!(warm_addresses.coinbase.is_none()); + assert!(!warm_addresses.is_warm(&coinbase_addr)); + } + + #[test] + fn test_short_address_precompiles() { + let mut warm_addresses = WarmAddresses::new(); + + // Create short addresses (18 leading zeros, last 2 bytes < 300) + let mut bytes1 = [0u8; 20]; + bytes1[19] = 1u8; + let short_addr1 = Address::from(bytes1); + + let mut bytes2 = [0u8; 20]; + bytes2[19] = 5u8; + let short_addr2 = Address::from(bytes2); + + let mut precompiles = HashSet::new(); + precompiles.insert(short_addr1); + precompiles.insert(short_addr2); + + warm_addresses.set_precompile_addresses(precompiles.clone()); + + // Verify storage + assert_eq!(warm_addresses.precompile_set, precompiles); + assert_eq!( + warm_addresses.precompile_short_addresses.len(), + SHORT_ADDRESS_CAP + ); + + // Verify bitvec optimization + assert!(warm_addresses.precompile_short_addresses[1]); + assert!(warm_addresses.precompile_short_addresses[5]); + assert!(!warm_addresses.precompile_short_addresses[0]); + + // Verify warmth detection + assert!(warm_addresses.is_warm(&short_addr1)); + assert!(warm_addresses.is_warm(&short_addr2)); + + // Test non-existent short address + let mut other_bytes = [0u8; 20]; + other_bytes[19] = 20u8; + let other_short_addr = Address::from(other_bytes); + assert!(!warm_addresses.is_warm(&other_short_addr)); + } + + #[test] + fn test_regular_address_precompiles() { + let mut warm_addresses = WarmAddresses::new(); + + // Create non-short addresses + let regular_addr = address!("1234567890123456789012345678901234567890"); + let mut bytes = [0u8; 20]; + bytes[18] = 1u8; + bytes[19] = 44u8; // 300 + let boundary_addr = Address::from(bytes); + + let mut precompiles = HashSet::new(); + precompiles.insert(regular_addr); + precompiles.insert(boundary_addr); + + warm_addresses.set_precompile_addresses(precompiles.clone()); + + // Verify storage + assert_eq!(warm_addresses.precompile_set, precompiles); + assert!(!warm_addresses.precompile_short_addresses.any()); + + // Verify warmth detection + assert!(warm_addresses.is_warm(®ular_addr)); + assert!(warm_addresses.is_warm(&boundary_addr)); + + // Test non-existent regular address + let other_addr = address!("0987654321098765432109876543210987654321"); + assert!(!warm_addresses.is_warm(&other_addr)); + } + + #[test] + fn test_mixed_address_types() { + let mut warm_addresses = WarmAddresses::new(); + + let mut short_bytes = [0u8; 20]; + short_bytes[19] = 7u8; + let short_addr = Address::from(short_bytes); + let regular_addr = address!("1234567890123456789012345678901234567890"); + + let mut precompiles = HashSet::new(); + precompiles.insert(short_addr); + precompiles.insert(regular_addr); + + warm_addresses.set_precompile_addresses(precompiles); + + // Both types should be warm + assert!(warm_addresses.is_warm(&short_addr)); + assert!(warm_addresses.is_warm(®ular_addr)); + + // Verify short address optimization is used + assert!(warm_addresses.precompile_short_addresses[7]); + assert!(!warm_addresses.precompile_short_addresses[8]); + } + + #[test] + fn test_short_address_boundary() { + let mut warm_addresses = WarmAddresses::new(); + + // Address at boundary (SHORT_ADDRESS_CAP - 1) + let mut boundary_bytes = [0u8; 20]; + let boundary_val = (SHORT_ADDRESS_CAP - 1) as u16; + boundary_bytes[18] = (boundary_val >> 8) as u8; + boundary_bytes[19] = boundary_val as u8; + let boundary_addr = Address::from(boundary_bytes); + + let mut precompiles = HashSet::new(); + precompiles.insert(boundary_addr); + + warm_addresses.set_precompile_addresses(precompiles); + + assert!(warm_addresses.is_warm(&boundary_addr)); + assert!(warm_addresses.precompile_short_addresses[SHORT_ADDRESS_CAP - 1]); + } +} diff --git a/crates/handler/src/pre_execution.rs b/crates/handler/src/pre_execution.rs index 7a7debca4b..0c9bf87b9e 100644 --- a/crates/handler/src/pre_execution.rs +++ b/crates/handler/src/pre_execution.rs @@ -55,16 +55,10 @@ pub fn load_accounts< if tx.tx_type() != TransactionType::Legacy { if let Some(access_list) = tx.access_list() { for item in access_list { - let address = item.address(); - let mut storage = item.storage_slots().peekable(); - if storage.peek().is_none() { - journal.warm_account(*address); - } else { - journal.warm_account_and_storage( - *address, - storage.map(|i| StorageKey::from_be_bytes(i.0)), - )?; - } + journal.warm_account_and_storage( + *item.address(), + item.storage_slots().map(|i| StorageKey::from_be_bytes(i.0)), + )?; } } } diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index e860126833..8c0a6b87b1 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -43,4 +43,3 @@ pub use interpreter_action::{ FrameInput, InterpreterAction, }; pub use interpreter_types::InterpreterTypes; -pub use primitives::{eip7907::MAX_CODE_SIZE, eip7907::MAX_INITCODE_SIZE}; diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 02f7105961..d461eb75ce 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -55,7 +55,9 @@ cfg_if::cfg_if! { use aurora_engine_modexp as _; use core::hash::Hash; -use primitives::{hardfork::SpecId, Address, HashMap, HashSet, OnceLock}; +use primitives::{ + hardfork::SpecId, short_address, Address, HashMap, HashSet, OnceLock, SHORT_ADDRESS_CAP, +}; use std::vec::Vec; /// Calculate the linear cost of a precompile. @@ -63,9 +65,6 @@ pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { (len as u64).div_ceil(32) * word + base } -/// Optimize short address access. -pub const SHORT_ADDRESS_CAP: usize = 300; - /// Precompiles contain map of precompile addresses to functions and HashSet of precompile addresses. #[derive(Clone, Debug)] pub struct Precompiles { @@ -75,6 +74,8 @@ pub struct Precompiles { addresses: HashSet
, /// Optimized addresses filter. optimized_access: Vec>, + /// `true` if all precompiles are short addresses. + all_short_addresses: bool, } impl Default for Precompiles { @@ -83,6 +84,7 @@ impl Default for Precompiles { inner: HashMap::default(), addresses: HashSet::default(), optimized_access: vec![None; SHORT_ADDRESS_CAP], + all_short_addresses: true, } } } @@ -267,6 +269,8 @@ impl Precompiles { for item in items.iter() { if let Some(short_address) = short_address(&item.0) { self.optimized_access[short_address] = Some(item.1); + } else { + self.all_short_addresses = false; } } @@ -309,21 +313,6 @@ impl Precompiles { } } -/// Returns the short address from Address. -/// -/// Short address is considered address that has 18 leading zeros -/// and last two bytes are less than [`SHORT_ADDRESS_CAP`]. -pub fn short_address(address: &Address) -> Option { - if address.0[..18].iter().all(|b| *b == 0) { - let short_address = u16::from_be_bytes(address.0[18..].try_into().unwrap()) as usize; - if short_address < SHORT_ADDRESS_CAP { - return Some(short_address); - } - } - - None -} - /// Precompile with address and function. #[derive(Clone, Debug)] pub struct PrecompileWithAddress(pub Address, pub PrecompileFn); diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index d5ea735c68..fd1f0b8c14 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -45,3 +45,21 @@ pub type StorageKey = U256; /// Type alias for EVM storage values (256-bit unsigned integers). /// Used to store data values in smart contract storage slots. pub type StorageValue = U256; + +/// Optimize short address access. +pub const SHORT_ADDRESS_CAP: usize = 300; + +/// Returns the short address from Address. +/// +/// Short address is considered address that has 18 leading zeros +/// and last two bytes are less than [`SHORT_ADDRESS_CAP`]. +#[inline] +pub fn short_address(address: &Address) -> Option { + if address.0[..18].iter().all(|b| *b == 0) { + let short_address = u16::from_be_bytes(address.0[18..].try_into().unwrap()) as usize; + if short_address < SHORT_ADDRESS_CAP { + return Some(short_address); + } + } + None +} diff --git a/examples/cheatcode_inspector/src/main.rs b/examples/cheatcode_inspector/src/main.rs index 5ca73b86d9..7337d1ef18 100644 --- a/examples/cheatcode_inspector/src/main.rs +++ b/examples/cheatcode_inspector/src/main.rs @@ -117,14 +117,8 @@ impl JournalTr for Backend { .warm_account_and_storage(address, storage_keys) } - fn warm_account(&mut self, address: Address) { - self.journaled_state - .warm_preloaded_addresses - .insert(address); - } - fn warm_coinbase_account(&mut self, address: Address) { - self.journaled_state.warm_coinbase_address = Some(address) + self.journaled_state.warm_coinbase_account(address) } fn warm_precompiles(&mut self, addresses: HashSet
) { From 74e7969bc9085e78a2732a6021331970ded86a13 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 6 Aug 2025 14:27:50 +0200 Subject: [PATCH 47/78] fix: correct various typos in documentation and comments (#2855) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: correct various typos in documentation and comments - Fixed "that" to "than" in comparison context - Corrected "RJUMV" to "RJUMPV" - Fixed "a address" to "an address" - Changed "This fields" to "These fields" - Fixed "have signed" to "has signed" - Corrected "All function has" to "All functions have" - Fixed "frm" to "from" - Clarified "Returns authorization the chain id" to "Returns the chain id from the authorization" - Fixed "all Ethereum transaction" to "all Ethereum transactions" - Changed "Use for" to "Used for" for consistency - Corrected "in requires" to "it requires" 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * chore: remove obsolete RJUMPV comments RJUMPV is no longer part of the EVM, so removing all related documentation. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude * refactor: replace HashSet::new() with HashSet::default() Standardize HashSet initialization to use default() for consistency. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --------- Co-authored-by: Claude --- crates/bytecode/src/opcode.rs | 10 ++-------- crates/context/interface/src/block.rs | 2 +- crates/context/interface/src/block/blob.rs | 2 +- crates/context/interface/src/cfg.rs | 2 +- crates/context/interface/src/context.rs | 4 ++-- crates/context/interface/src/transaction/eip7702.rs | 2 +- .../interface/src/transaction/transaction_type.rs | 2 +- crates/context/src/journal/warm_addresses.rs | 10 +++++----- 8 files changed, 14 insertions(+), 20 deletions(-) diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index f08b790da7..199b45406a 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -160,7 +160,7 @@ impl OpCode { /// Returns the number of both input and output stack elements. /// - /// Can be slightly faster that calling `inputs` and `outputs` separately. + /// Can be slightly faster than calling `inputs` and `outputs` separately. pub const fn input_output(&self) -> (u8, u8) { let info = self.info(); (info.inputs, info.outputs) @@ -223,9 +223,6 @@ pub struct OpCodeInfo { /// Stack outputs outputs: u8, /// Number of intermediate bytes - /// - /// RJUMPV is a special case where the bytes len depends on bytecode value, - /// for RJUMV size will be set to one byte as it is the minimum immediate size. immediate_size: u8, /// If the opcode stops execution. aka STOP, RETURN, .. terminating: bool, @@ -303,16 +300,13 @@ impl OpCodeInfo { } /// Used for [`OPCODE_INFO`] to set the immediate bytes number in the [`OpCodeInfo`]. -/// -/// RJUMPV is special case where the bytes len is depending on bytecode value, -/// for RJUMPV size will be set to one byte while minimum is two. #[inline] pub const fn immediate_size(mut op: OpCodeInfo, n: u8) -> OpCodeInfo { op.immediate_size = n; op } -/// Use for [`OPCODE_INFO`] to set the terminating flag to true in the [`OpCodeInfo`]. +/// Used for [`OPCODE_INFO`] to set the terminating flag to true in the [`OpCodeInfo`]. #[inline] pub const fn terminating(mut op: OpCodeInfo) -> OpCodeInfo { op.terminating = true; diff --git a/crates/context/interface/src/block.rs b/crates/context/interface/src/block.rs index dcc4c53af2..544c0994bc 100644 --- a/crates/context/interface/src/block.rs +++ b/crates/context/interface/src/block.rs @@ -16,7 +16,7 @@ pub trait Block { /// The number of ancestor blocks of this block (block height). fn number(&self) -> U256; - /// Beneficiary (Coinbase, miner) is a address that have signed the block. + /// Beneficiary (Coinbase, miner) is an address that has signed the block. /// /// This is the receiver address of priority gas rewards. fn beneficiary(&self) -> Address; diff --git a/crates/context/interface/src/block/blob.rs b/crates/context/interface/src/block/blob.rs index fab7bc10e3..2927559697 100644 --- a/crates/context/interface/src/block/blob.rs +++ b/crates/context/interface/src/block/blob.rs @@ -43,7 +43,7 @@ impl BlobExcessGasAndPrice { /// Calculate this block excess gas and price from the parent excess gas and gas used /// and the target blob gas per block. /// - /// This fields will be used to calculate `excess_blob_gas` with [`calc_excess_blob_gas`] func. + /// These fields will be used to calculate `excess_blob_gas` with [`calc_excess_blob_gas`] func. #[deprecated( note = "Use `calc_excess_blob_gas` and `BlobExcessGasAndPrice::new` instead. Only works for forks before Osaka." )] diff --git a/crates/context/interface/src/cfg.rs b/crates/context/interface/src/cfg.rs index 3212b81520..cd91706edc 100644 --- a/crates/context/interface/src/cfg.rs +++ b/crates/context/interface/src/cfg.rs @@ -7,7 +7,7 @@ use primitives::{hardfork::SpecId, Address, TxKind, U256}; /// Configuration for the EVM. #[auto_impl(&, &mut, Box, Arc)] pub trait Cfg { - /// Specification id type, in requires to be convertible to `SpecId` so it can be used + /// Specification id type, it requires to be convertible to `SpecId` so it can be used /// by default in mainnet. type Spec: Into + Clone; diff --git a/crates/context/interface/src/context.rs b/crates/context/interface/src/context.rs index bbf1311a18..0be6f53439 100644 --- a/crates/context/interface/src/context.rs +++ b/crates/context/interface/src/context.rs @@ -13,7 +13,7 @@ use std::string::String; /// It is used to access the transaction, block, configuration, database, journal, and chain. /// It is also used to set the error of the EVM. /// -/// All function has a `*_mut` variant except the function for [`ContextTr::tx`] and [`ContextTr::block`]. +/// All functions have a `*_mut` variant except the function for [`ContextTr::tx`] and [`ContextTr::block`]. #[auto_impl(&mut, Box)] pub trait ContextTr: Host { /// Block type @@ -79,7 +79,7 @@ pub trait ContextTr: Host { fn tx_local_mut(&mut self) -> (&Self::Tx, &mut Self::Local); } -/// Inner Context error used for Interpreter to set error without returning it frm instruction +/// Inner Context error used for Interpreter to set error without returning it from instruction #[derive(Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ContextError { diff --git a/crates/context/interface/src/transaction/eip7702.rs b/crates/context/interface/src/transaction/eip7702.rs index b92ba7d47b..6262c79a8c 100644 --- a/crates/context/interface/src/transaction/eip7702.rs +++ b/crates/context/interface/src/transaction/eip7702.rs @@ -16,7 +16,7 @@ pub trait AuthorizationTr { /// signature s-value should be less than SECP256K1N_HALF. fn authority(&self) -> Option
; - /// Returns authorization the chain id. + /// Returns the chain id from the authorization. fn chain_id(&self) -> U256; /// Returns the nonce. diff --git a/crates/context/interface/src/transaction/transaction_type.rs b/crates/context/interface/src/transaction/transaction_type.rs index 1946c6647f..3d011eca2f 100644 --- a/crates/context/interface/src/transaction/transaction_type.rs +++ b/crates/context/interface/src/transaction/transaction_type.rs @@ -1,6 +1,6 @@ //! Transaction type enum. -/// Transaction types of all Ethereum transaction +/// Transaction types of all Ethereum transactions #[repr(u8)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] diff --git a/crates/context/src/journal/warm_addresses.rs b/crates/context/src/journal/warm_addresses.rs index 47dbd32e02..6e72b725f7 100644 --- a/crates/context/src/journal/warm_addresses.rs +++ b/crates/context/src/journal/warm_addresses.rs @@ -31,7 +31,7 @@ impl WarmAddresses { #[inline] pub fn new() -> Self { Self { - precompile_set: HashSet::new(), + precompile_set: HashSet::default(), precompile_short_addresses: BitVec::new(), all_short_addresses: true, coinbase: None, @@ -161,7 +161,7 @@ mod tests { bytes2[19] = 5u8; let short_addr2 = Address::from(bytes2); - let mut precompiles = HashSet::new(); + let mut precompiles = HashSet::default(); precompiles.insert(short_addr1); precompiles.insert(short_addr2); @@ -201,7 +201,7 @@ mod tests { bytes[19] = 44u8; // 300 let boundary_addr = Address::from(bytes); - let mut precompiles = HashSet::new(); + let mut precompiles = HashSet::default(); precompiles.insert(regular_addr); precompiles.insert(boundary_addr); @@ -229,7 +229,7 @@ mod tests { let short_addr = Address::from(short_bytes); let regular_addr = address!("1234567890123456789012345678901234567890"); - let mut precompiles = HashSet::new(); + let mut precompiles = HashSet::default(); precompiles.insert(short_addr); precompiles.insert(regular_addr); @@ -255,7 +255,7 @@ mod tests { boundary_bytes[19] = boundary_val as u8; let boundary_addr = Address::from(boundary_bytes); - let mut precompiles = HashSet::new(); + let mut precompiles = HashSet::default(); precompiles.insert(boundary_addr); warm_addresses.set_precompile_addresses(precompiles); From efb7bb11d0d33782a0094e2ad7732881f1378936 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 7 Aug 2025 01:45:32 +0200 Subject: [PATCH 48/78] chore: release (#2854) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 30 +++++++++++------------ Cargo.toml | 28 +++++++++++----------- bins/revme/CHANGELOG.md | 22 +++++++++++++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 19 +++++++++++++++ crates/bytecode/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 16 +++++++++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 17 +++++++++++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 7 ++++++ crates/database/Cargo.toml | 2 +- crates/database/interface/CHANGELOG.md | 7 ++++++ crates/database/interface/Cargo.toml | 2 +- crates/ee-tests/CHANGELOG.md | 20 ++++++++++++++++ crates/handler/CHANGELOG.md | 32 +++++++++++++++++++++++++ crates/handler/Cargo.toml | 2 +- crates/inspector/CHANGELOG.md | 14 +++++++++++ crates/inspector/Cargo.toml | 2 +- crates/interpreter/CHANGELOG.md | 33 ++++++++++++++++++++++++++ crates/interpreter/Cargo.toml | 2 +- crates/op-revm/CHANGELOG.md | 26 ++++++++++++++++++++ crates/op-revm/Cargo.toml | 2 +- crates/precompile/CHANGELOG.md | 31 ++++++++++++++++++++++++ crates/precompile/Cargo.toml | 2 +- crates/primitives/CHANGELOG.md | 22 +++++++++++++++++ crates/primitives/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 22 +++++++++++++++++ crates/revm/Cargo.toml | 2 +- crates/state/CHANGELOG.md | 19 +++++++++++++++ crates/state/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 7 ++++++ crates/statetest-types/Cargo.toml | 2 +- 33 files changed, 358 insertions(+), 44 deletions(-) create mode 100644 crates/ee-tests/CHANGELOG.md diff --git a/Cargo.lock b/Cargo.lock index 520e764388..875d37bcb0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3034,7 +3034,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "8.1.0" +version = "9.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3773,7 +3773,7 @@ dependencies = [ [[package]] name = "revm" -version = "27.1.0" +version = "27.2.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3793,7 +3793,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "6.1.0" +version = "6.2.0" dependencies = [ "bitvec", "paste", @@ -3804,7 +3804,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "8.0.4" +version = "9.0.0" dependencies = [ "bitvec", "cfg-if", @@ -3820,7 +3820,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "9.0.0" +version = "10.0.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3834,7 +3834,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "7.0.2" +version = "7.0.3" dependencies = [ "alloy-eips", "alloy-provider", @@ -3852,7 +3852,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "7.0.2" +version = "7.0.3" dependencies = [ "anyhow", "auto_impl", @@ -3880,7 +3880,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "8.1.0" +version = "9.0.0" dependencies = [ "alloy-eip7702", "alloy-provider", @@ -3902,7 +3902,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "8.1.0" +version = "8.2.0" dependencies = [ "auto_impl", "either", @@ -3919,7 +3919,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "24.0.0" +version = "25.0.0" dependencies = [ "bincode 2.0.1", "revm-bytecode", @@ -3930,7 +3930,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "25.0.0" +version = "26.0.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3960,7 +3960,7 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "20.1.0" +version = "20.2.0" dependencies = [ "alloy-primitives", "num_enum", @@ -3970,7 +3970,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "7.0.2" +version = "7.0.3" dependencies = [ "bitflags", "revm-bytecode", @@ -3980,7 +3980,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "8.0.5" +version = "8.0.6" dependencies = [ "k256", "revm", @@ -3991,7 +3991,7 @@ dependencies = [ [[package]] name = "revme" -version = "7.1.0" +version = "7.2.0" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 91b5e3b83e..db046307b6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "27.1.0", default-features = false } -primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.1.0", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.1.0", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "7.0.2", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.2", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "7.0.2", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "24.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "8.1.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "25.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "8.0.5", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "8.0.4", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "9.0.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "8.1.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "8.1.0", default-features = false } +revm = { path = "crates/revm", version = "27.2.0", default-features = false } +primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.2.0", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.0", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "7.0.3", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.3", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "7.0.3", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "8.2.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "26.0.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "8.0.6", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "9.0.0", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.0.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "9.0.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "9.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 3932b96718..755f25f0fc 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -1,4 +1,26 @@ # 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] + +## [7.2.0](https://github.com/bluealloy/revm/compare/revme-v7.1.0...revme-v7.2.0) - 2025-08-06 + +### Added + +- Reuse bls12-381 codepaths to implement kzg point evaluation precompile ([#2809](https://github.com/bluealloy/revm/pull/2809)) + +### Other + +- *(benches)* rename anaysis-inspector to snailtracer-inspect ([#2834](https://github.com/bluealloy/revm/pull/2834)) +- *(benches)* clean up criterion callsites ([#2833](https://github.com/bluealloy/revm/pull/2833)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) +- fix clippy ([#2785](https://github.com/bluealloy/revm/pull/2785)) +- add gas_limit to revme evm ([#2779](https://github.com/bluealloy/revm/pull/2779)) +# 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/), diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index fa17cd696b..83912a38b3 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 = "7.1.0" +version = "7.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index 9c484b890e..c86123cf0e 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,6 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.2.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v6.1.0...revm-bytecode-v6.2.0) - 2025-08-06 + +### Added + +- removed padding in case last opcode is terminating or unknown ([#2816](https://github.com/bluealloy/revm/pull/2816)) + +### Fixed + +- correct various typos in documentation and comments ([#2855](https://github.com/bluealloy/revm/pull/2855)) + +### Other + +- *(OpCode)* add is_valid ([#2847](https://github.com/bluealloy/revm/pull/2847)) +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- *(benches)* clean up criterion callsites ([#2833](https://github.com/bluealloy/revm/pull/2833)) +- improve ExtBytecode hash handling ([#2826](https://github.com/bluealloy/revm/pull/2826)) +- 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)) + ## [6.1.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v6.0.1...revm-bytecode-v6.1.0) - 2025-07-23 ### Added diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index c0eaf54d4f..4e4335cae3 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "6.1.0" +version = "6.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 70646c5757..76e712b570 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] +## [9.0.0](https://github.com/bluealloy/revm/compare/revm-context-v8.0.4...revm-context-v9.0.0) - 2025-08-06 + +### Added + +- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) + +### Fixed + +- correct various typos in documentation and comments ([#2855](https://github.com/bluealloy/revm/pull/2855)) + +### Other + +- rm redundant lifetime constraints ([#2850](https://github.com/bluealloy/revm/pull/2850)) +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) + ## [8.0.4](https://github.com/bluealloy/revm/compare/revm-context-v8.0.3...revm-context-v8.0.4) - 2025-07-23 ### Fixed diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index c7f5131e19..6f947017da 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "8.0.4" +version = "9.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 0cf77dcb7e..e7135ad2c5 100644 --- a/crates/context/interface/CHANGELOG.md +++ b/crates/context/interface/CHANGELOG.md @@ -7,6 +7,23 @@ 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-context-interface-v9.0.0...revm-context-interface-v10.0.0) - 2025-08-06 + +### Added + +- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) + +### Fixed + +- correct various typos in documentation and comments ([#2855](https://github.com/bluealloy/revm/pull/2855)) +- swapped comments for db and db_mut methods in JournalTr trait ([#2774](https://github.com/bluealloy/revm/pull/2774)) + +### Other + +- rm redundant lifetime constraints ([#2850](https://github.com/bluealloy/revm/pull/2850)) +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) + ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v8.0.1...revm-context-interface-v9.0.0) - 2025-07-23 ### Fixed diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 1e72618b9e..1f1dfa8c34 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 = "9.0.0" +version = "10.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index 1cfa90d7b8..39c228f1af 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.0.3](https://github.com/bluealloy/revm/compare/revm-database-v7.0.2...revm-database-v7.0.3) - 2025-08-06 + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) + ## [7.0.2](https://github.com/bluealloy/revm/compare/revm-database-v7.0.1...revm-database-v7.0.2) - 2025-07-23 ### Other diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 1424eb9bba..72c606100a 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "7.0.2" +version = "7.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 1e2d3eb839..6cb55fedad 100644 --- a/crates/database/interface/CHANGELOG.md +++ b/crates/database/interface/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.0.3](https://github.com/bluealloy/revm/compare/revm-database-interface-v7.0.2...revm-database-interface-v7.0.3) - 2025-08-06 + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) + ## [7.0.2](https://github.com/bluealloy/revm/compare/revm-database-interface-v7.0.1...revm-database-interface-v7.0.2) - 2025-07-23 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index f898efb4e2..d822889615 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 = "7.0.2" +version = "7.0.3" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/ee-tests/CHANGELOG.md b/crates/ee-tests/CHANGELOG.md new file mode 100644 index 0000000000..f6c03b2070 --- /dev/null +++ b/crates/ee-tests/CHANGELOG.md @@ -0,0 +1,20 @@ +# 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] + +## [0.1.0](https://github.com/bluealloy/revm/releases/tag/revm-ee-tests-v0.1.0) - 2025-08-06 + +### Added + +- gastable, record static gas in Interpreter loop ([#2822](https://github.com/bluealloy/revm/pull/2822)) +- fix renamed functions for system_call ([#2824](https://github.com/bluealloy/revm/pull/2824)) +- refactor test utils ([#2813](https://github.com/bluealloy/revm/pull/2813)) + +### Other + +- *(op-revm)* Adds caller nonce assertion to op-revm intergation tests ([#2815](https://github.com/bluealloy/revm/pull/2815)) diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 19ce478016..0a2fbb8016 100644 --- a/crates/handler/CHANGELOG.md +++ b/crates/handler/CHANGELOG.md @@ -5,6 +5,38 @@ 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] + +## [9.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v8.1.0...revm-handler-v9.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)) +- fix renamed functions for system_call ([#2824](https://github.com/bluealloy/revm/pull/2824)) +- Align naming of SystemCallEvm function to ExecuteEvm ([#2814](https://github.com/bluealloy/revm/pull/2814)) + +### Fixed + +- nonce changed is not reverted in journal if fail due to insufficient balance ([#2805](https://github.com/bluealloy/revm/pull/2805)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- rm commented code ([#2839](https://github.com/bluealloy/revm/pull/2839)) +- *(benches)* clean up criterion callsites ([#2833](https://github.com/bluealloy/revm/pull/2833)) +- improve ExtBytecode hash handling ([#2826](https://github.com/bluealloy/revm/pull/2826)) +- fix run-tests.sh ([#2801](https://github.com/bluealloy/revm/pull/2801)) +- 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 dyn Crypto trait to PrecompileFn ([#2772](https://github.com/bluealloy/revm/pull/2772)) +# 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). + ## [8.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v8.0.3...revm-handler-v8.1.0) - 2025-07-23 diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 7cb95a10a3..9eff0128cf 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "8.1.0" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 2c6729f593..858e936ec4 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.2.0](https://github.com/bluealloy/revm/compare/revm-inspector-v8.1.0...revm-inspector-v8.2.0) - 2025-08-06 + +### Added + +- fix renamed functions for system_call ([#2824](https://github.com/bluealloy/revm/pull/2824)) +- add system transaction inspection support ([#2808](https://github.com/bluealloy/revm/pull/2808)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- fix inspector, cleanup loop ([#2797](https://github.com/bluealloy/revm/pull/2797)) +- 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)) + ## [8.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v8.0.3...revm-inspector-v8.1.0) - 2025-07-23 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 553f176b5a..68af709e7c 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "8.1.0" +version = "8.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 473ea6dea4..75d2a11614 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -1,4 +1,37 @@ # 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] + +## [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/), diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index a07f25631a..da461c04f1 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 = "24.0.0" +version = "25.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 bc9d37965e..110d7f1fbd 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.0.0](https://github.com/bluealloy/revm/compare/op-revm-v8.1.0...op-revm-v9.0.0) - 2025-08-06 + +### Added + +- fix renamed functions for system_call ([#2824](https://github.com/bluealloy/revm/pull/2824)) +- refactor test utils ([#2813](https://github.com/bluealloy/revm/pull/2813)) +- add system transaction inspection support ([#2808](https://github.com/bluealloy/revm/pull/2808)) +- Align naming of SystemCallEvm function to ExecuteEvm ([#2814](https://github.com/bluealloy/revm/pull/2814)) +- rename bn128 to bn254 for Ethereum standard consistency ([#2810](https://github.com/bluealloy/revm/pull/2810)) + +### Fixed + +- *(op-revm)* system tx not enveloped ([#2807](https://github.com/bluealloy/revm/pull/2807)) +- nonce changed is not reverted in journal if fail due to insufficient balance ([#2805](https://github.com/bluealloy/revm/pull/2805)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- *(op-revm)* Adds caller nonce assertion to op-revm intergation tests ([#2815](https://github.com/bluealloy/revm/pull/2815)) +- *(op-revm)* Full test coverage `OpTransactionError` ([#2818](https://github.com/bluealloy/revm/pull/2818)) +- Update test data for renamed tests ([#2817](https://github.com/bluealloy/revm/pull/2817)) +- 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)) +- Add dyn Crypto trait to PrecompileFn ([#2772](https://github.com/bluealloy/revm/pull/2772)) + ## [8.1.0](https://github.com/bluealloy/revm/compare/op-revm-v8.0.3...op-revm-v8.1.0) - 2025-07-23 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 5035af78be..4706ab61f3 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 = "8.1.0" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index c36189fd5c..b5f37a11c1 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -1,4 +1,35 @@ # 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] + +## [26.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v25.0.0...revm-precompile-v26.0.0) - 2025-08-06 + +### Added + +- short address for journal cold/warm check ([#2849](https://github.com/bluealloy/revm/pull/2849)) +- optimize access to precompile short addresses ([#2846](https://github.com/bluealloy/revm/pull/2846)) +- Reuse bls12-381 codepaths to implement kzg point evaluation precompile ([#2809](https://github.com/bluealloy/revm/pull/2809)) +- rename bn128 to bn254 for Ethereum standard consistency ([#2810](https://github.com/bluealloy/revm/pull/2810)) + +### Fixed + +- map new once and for all (+ci) ([#2852](https://github.com/bluealloy/revm/pull/2852)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- simplify the ecrecover test ([#2836](https://github.com/bluealloy/revm/pull/2836)) +- 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)) +- fix clippy ([#2785](https://github.com/bluealloy/revm/pull/2785)) +- Add dyn Crypto trait to PrecompileFn ([#2772](https://github.com/bluealloy/revm/pull/2772)) +# 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/), diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 9b87997d90..6fbd79c742 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 = "25.0.0" +version = "26.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index cb1711f1b7..d1f0ae85dd 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -1,4 +1,26 @@ # 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] + +## [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/), diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index 55d3e9c548..eaec8a799f 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-primitives" description = "Revm primitives types" -version = "20.1.0" +version = "20.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index f380d29a73..7e272a746f 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -1,4 +1,26 @@ # 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] + +## [27.2.0](https://github.com/bluealloy/revm/compare/revm-v27.1.0...revm-v27.2.0) - 2025-08-06 + +### Added + +- Reuse bls12-381 codepaths to implement kzg point evaluation precompile ([#2809](https://github.com/bluealloy/revm/pull/2809)) +- refactor test utils ([#2813](https://github.com/bluealloy/revm/pull/2813)) +- add system transaction inspection support ([#2808](https://github.com/bluealloy/revm/pull/2808)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- 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)) +# 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/), diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 7bd144584b..b0ab358d04 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 = "27.1.0" +version = "27.2.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index 6399b58a73..6fa0424496 100644 --- a/crates/state/CHANGELOG.md +++ b/crates/state/CHANGELOG.md @@ -5,6 +5,25 @@ 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] + +## [7.0.3](https://github.com/bluealloy/revm/compare/revm-state-v7.0.2...revm-state-v7.0.3) - 2025-08-06 + +### Fixed + +- manally implementation PartialOrd and Ord for AccountInfo ([#2835](https://github.com/bluealloy/revm/pull/2835)) + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) +# 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). + ## [4.0.0](https://github.com/bluealloy/revm/compare/revm-state-v3.0.1...revm-state-v4.0.0) - 2025-05-07 diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index efc15e41af..e6ac718259 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "7.0.2" +version = "7.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 ae820d737d..13dc744de2 100644 --- a/crates/statetest-types/CHANGELOG.md +++ b/crates/statetest-types/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.0.6](https://github.com/bluealloy/revm/compare/revm-statetest-types-v8.0.5...revm-statetest-types-v8.0.6) - 2025-08-06 + +### Other + +- update README.md ([#2842](https://github.com/bluealloy/revm/pull/2842)) +- add rust-version and note about MSRV ([#2789](https://github.com/bluealloy/revm/pull/2789)) + ## [8.0.5](https://github.com/bluealloy/revm/compare/revm-statetest-types-v8.0.4...revm-statetest-types-v8.0.5) - 2025-07-23 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index be5f10e420..0a03658428 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 = "8.0.5" +version = "8.0.6" authors.workspace = true edition.workspace = true keywords.workspace = true From 1c721c900cd5bbb323e35f5e10bb2a5b4d87ea56 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 7 Aug 2025 02:18:42 +0200 Subject: [PATCH 49/78] bump: tag v84 revm v28.0.0 (#2856) * chore: migration guide, cleanup * bump: prep for v84 revm v28.0.0 --- CHANGELOG.md | 22 ++++ Cargo.lock | 6 +- Cargo.toml | 6 +- MIGRATION_GUIDE.md | 6 ++ .../context/interface/src/journaled_state.rs | 8 ++ crates/ee-tests/Cargo.toml | 22 ++-- crates/ee-tests/src/lib.rs | 1 + crates/ee-tests/src/revm_tests.rs | 4 +- crates/inspector/CHANGELOG.md | 2 +- crates/inspector/Cargo.toml | 2 +- .../src/interpreter/subroutine_stack.rs | 101 ------------------ crates/revm/CHANGELOG.md | 4 +- crates/revm/Cargo.toml | 2 +- crates/statetest-types/CHANGELOG.md | 2 +- crates/statetest-types/Cargo.toml | 2 +- examples/custom_precompile_journal/Cargo.toml | 9 +- 16 files changed, 74 insertions(+), 125 deletions(-) delete mode 100644 crates/interpreter/src/interpreter/subroutine_stack.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4ef1d8d6c3..4f92dcb7b7 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. +# v84 +date: 07.08.2025 + +Small perf and maintainance release. + +revm-inspector@9.0.0 revm@28.0.0 revm-statetest-types@9.0.0 + +`revm-primitives`: 20.1.0 -> 20.2.0 (✓ API compatible changes) +`revm-bytecode`: 6.1.0 -> 6.2.0 (✓ API compatible changes) +`revm-state`: 7.0.2 -> 7.0.3 (✓ API compatible changes) +`revm-database-interface`: 7.0.2 -> 7.0.3 (✓ API compatible changes) +`revm-context-interface`: 9.0.0 -> 10.0.0 (⚠ API breaking changes) +`revm-context`: 8.0.4 -> 9.0.0 (⚠ API breaking changes) +`revm-database`: 7.0.2 -> 7.0.3 (✓ API compatible changes) +`revm-interpreter`: 24.0.0 -> 25.0.0 (⚠ API breaking changes) +`revm-precompile`: 25.0.0 -> 26.0.0 (⚠ API breaking changes) +`revm-handler`: 8.1.0 -> 9.0.0 (⚠ API breaking changes) +`revm-inspector`: 8.1.0 -> 9.0.0 (✓ API compatible changes) +`revm`: 27.1.0 -> 28.0.0 (✓ API compatible changes) +`revm-statetest-types`: 8.0.5 -> 9.0.0 (✓ API compatible changes) +`revme`: 7.1.0 -> 7.2.0 (✓ API compatible changes) +`op-revm`: 8.1.0 -> 9.0.0 (⚠ API breaking changes) # v83 date: 23.07.2025 diff --git a/Cargo.lock b/Cargo.lock index 875d37bcb0..aeddc323a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3773,7 +3773,7 @@ dependencies = [ [[package]] name = "revm" -version = "27.2.0" +version = "28.0.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3902,7 +3902,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "8.2.0" +version = "9.0.0" dependencies = [ "auto_impl", "either", @@ -3980,7 +3980,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "8.0.6" +version = "9.0.0" dependencies = [ "k256", "revm", diff --git a/Cargo.toml b/Cargo.toml index db046307b6..169a514a25 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,16 +41,16 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "27.2.0", default-features = false } +revm = { path = "crates/revm", version = "28.0.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.2.0", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.0", default-features = false } database = { path = "crates/database", package = "revm-database", version = "7.0.3", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.3", default-features = false } state = { path = "crates/state", package = "revm-state", version = "7.0.3", default-features = false } interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "8.2.0", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "9.0.0", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "26.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "8.0.6", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "9.0.0", default-features = false } context = { path = "crates/context", package = "revm-context", version = "9.0.0", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.0.0", default-features = false } handler = { path = "crates/handler", package = "revm-handler", version = "9.0.0", default-features = false } diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 0b4d7184db..be654ae3de 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -3,6 +3,12 @@ * `SystemCallEvm` functions got renamed and old ones are deprecated. Renaming is done to align it with other API calls. * `transact_system_call_finalize` is now `system_call`. * `transact_system_call` is now `system_call_one`. +* `ExtBytecode::regenerate_hash` got deprecated in support for `get_or_calculate_hash` or `calculate_hash`. +* Precompiles: + * Bn128 renamed to Bn254. https://github.com/ethereum/EIPs/pull/10029#issue-3240867404 +* `InstructionResult` now starts from 1 (previous 0) for perf purposes. +* In `JournalInner` previous `precompiles`, `warm_coinbase_address` and `warm_preloaded_addresses` pub fields are now moved to `warm_addresses` to encapsulate addresses that are warm by default. All access list account are all loaded from database. + # v82 tag (revm v27.1.0) from v81 tag (revm v27.0.3) diff --git a/crates/context/interface/src/journaled_state.rs b/crates/context/interface/src/journaled_state.rs index 9d45323f14..df1ae23a8b 100644 --- a/crates/context/interface/src/journaled_state.rs +++ b/crates/context/interface/src/journaled_state.rs @@ -66,6 +66,14 @@ pub trait JournalTr { 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, []) + } + /// Warms the coinbase account. fn warm_coinbase_account(&mut self, address: Address); diff --git a/crates/ee-tests/Cargo.toml b/crates/ee-tests/Cargo.toml index ad256d1627..fee90fdd51 100644 --- a/crates/ee-tests/Cargo.toml +++ b/crates/ee-tests/Cargo.toml @@ -1,12 +1,17 @@ [package] name = "revm-ee-tests" -version = "0.1.0" -authors = ["revm"] -edition = "2021" -rust-version = "1.80.1" -license = "MIT" description = "Common test utilities for REVM crates" -repository = "https://github.com/bluealloy/revm" +version = "0.1.0" +authors.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true + +[lints] +workspace = true [dependencies] serde = { version = "1.0", features = ["derive"] } @@ -22,4 +27,7 @@ alloy-primitives = { workspace = true } [features] default = [] -optional_balance_check = ["revm/optional_balance_check", "op-revm/optional_balance_check"] +optional_balance_check = [ + "revm/optional_balance_check", + "op-revm/optional_balance_check", +] diff --git a/crates/ee-tests/src/lib.rs b/crates/ee-tests/src/lib.rs index 42b8d48dbf..e07453abcf 100644 --- a/crates/ee-tests/src/lib.rs +++ b/crates/ee-tests/src/lib.rs @@ -7,6 +7,7 @@ use std::path::PathBuf; use serde_json::Value; /// Configuration for the test data comparison utility. +#[derive(Debug, Clone, PartialEq, Eq)] pub struct TestdataConfig { /// The directory where test data files are stored. pub testdata_dir: PathBuf, diff --git a/crates/ee-tests/src/revm_tests.rs b/crates/ee-tests/src/revm_tests.rs index 8758052a36..b89459ebfc 100644 --- a/crates/ee-tests/src/revm_tests.rs +++ b/crates/ee-tests/src/revm_tests.rs @@ -82,7 +82,7 @@ fn test_selfdestruct_multi_tx() { /// Verifies that created contracts persist correctly across transactions /// and that their state is properly maintained. #[test] -pub fn test_multi_tx_create() { +fn test_multi_tx_create() { let mut evm = Context::mainnet() .modify_cfg_chained(|cfg| { cfg.spec = SpecId::BERLIN; @@ -191,7 +191,7 @@ pub fn test_multi_tx_create() { /// Creates deployment bytecode for a contract. /// Prepends the initialization code that will deploy the provided runtime bytecode. -pub fn deployment_contract(bytes: &[u8]) -> Bytes { +fn deployment_contract(bytes: &[u8]) -> Bytes { assert!(bytes.len() < 256); let len = bytes.len(); let ret = &[ diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 858e936ec4..7dacd2da19 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] -## [8.2.0](https://github.com/bluealloy/revm/compare/revm-inspector-v8.1.0...revm-inspector-v8.2.0) - 2025-08-06 +## [9.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v8.1.0...revm-inspector-v9.0.0) - 2025-08-06 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 68af709e7c..4d2459dab7 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "8.2.0" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/src/interpreter/subroutine_stack.rs b/crates/interpreter/src/interpreter/subroutine_stack.rs deleted file mode 100644 index 9c39d5b4ee..0000000000 --- a/crates/interpreter/src/interpreter/subroutine_stack.rs +++ /dev/null @@ -1,101 +0,0 @@ -use std::vec::Vec; - -use crate::interpreter_types::SubRoutineStack; - -/// Function(Sub Routine) return frame in eof -/// -/// Needed information for returning from a function. -#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct SubRoutineReturnFrame { - /// The index of the code container that this frame is executing. - pub idx: usize, - /// The program counter where frame execution should continue. - pub pc: usize, -} - -impl SubRoutineReturnFrame { - /// Return new function frame. - pub fn new(idx: usize, pc: usize) -> Self { - Self { idx, pc } - } -} - -/// Function Stack -#[derive(Clone, Debug, Default, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct SubRoutineImpl { - /// Stack of return frames for managing nested subroutine calls - pub return_stack: Vec, - /// Index of the currently executing code section - pub current_code_idx: usize, -} - -impl SubRoutineImpl { - /// Returns new function stack. - pub fn new() -> Self { - Self { - return_stack: Vec::new(), - current_code_idx: 0, - } - } - - /// Clears the function stack. - pub fn clear(&mut self) { - self.return_stack.clear(); - self.current_code_idx = 0; - } - - /// Returns the number of subroutine frames on the stack. - pub fn len(&self) -> usize { - self.return_stack.len() - } - - /// Returns true if the subroutine stack is empty. - pub fn is_empty(&self) -> bool { - self.return_stack.is_empty() - } - - /// Return stack length - pub fn return_stack_len(&self) -> usize { - self.return_stack.len() - } - - /// Sets current_code_idx, this is needed for JUMPF opcode. - pub fn set_current_code_idx(&mut self, idx: usize) { - self.current_code_idx = idx; - } -} - -impl SubRoutineStack for SubRoutineImpl { - fn len(&self) -> usize { - self.return_stack.len() - } - - fn routine_idx(&self) -> usize { - self.current_code_idx - } - - fn push(&mut self, program_counter: usize, new_idx: usize) -> bool { - if self.return_stack.len() >= 1024 { - return false; - } - self.return_stack.push(SubRoutineReturnFrame { - idx: self.current_code_idx, - pc: program_counter, - }); - self.current_code_idx = new_idx; - true - } - - fn pop(&mut self) -> Option { - self.return_stack.pop().map(|i| { - self.current_code_idx = i.idx; - i.pc - }) - } - - fn set_routine_idx(&mut self, idx: usize) { - self.current_code_idx = idx; - } -} diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 7e272a746f..9fabcc2879 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] -## [27.2.0](https://github.com/bluealloy/revm/compare/revm-v27.1.0...revm-v27.2.0) - 2025-08-06 +## [28.0.0](https://github.com/bluealloy/revm/compare/revm-v27.1.0...revm-v28.0.0) - 2025-08-06 ### Added @@ -26,8 +26,6 @@ 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] - ## [27.1.0](https://github.com/bluealloy/revm/compare/revm-v27.0.3...revm-v27.1.0) - 2025-07-23 ### Added diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index b0ab358d04..ce5ae49ea6 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 = "27.2.0" +version = "28.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 13dc744de2..ef52d33898 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] -## [8.0.6](https://github.com/bluealloy/revm/compare/revm-statetest-types-v8.0.5...revm-statetest-types-v8.0.6) - 2025-08-06 +## [9.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v8.0.5...revm-statetest-types-v9.0.0) - 2025-08-06 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 0a03658428..c1c48c1d75 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 = "8.0.6" +version = "9.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/examples/custom_precompile_journal/Cargo.toml b/examples/custom_precompile_journal/Cargo.toml index d450da17a2..8a052ce301 100644 --- a/examples/custom_precompile_journal/Cargo.toml +++ b/examples/custom_precompile_journal/Cargo.toml @@ -1,7 +1,14 @@ [package] name = "example-custom-precompile-journal" version = "0.1.0" -edition = "2021" +publish = false +authors.workspace = true +edition.workspace = true +keywords.workspace = true +license.workspace = true +repository.workspace = true +readme.workspace = true +rust-version.workspace = true [dependencies] revm = { path = "../../crates/revm", features = ["optional_eip3607"] } From 814427f7cbfbfb55e805091cf8a7683c97cf2a4d Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 7 Aug 2025 02:30:59 +0200 Subject: [PATCH 50/78] chore: rm ee-test from revm/op-revm (#2857) --- Cargo.lock | 2 -- crates/op-revm/Cargo.toml | 1 - crates/revm/Cargo.toml | 1 - 3 files changed, 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index aeddc323a6..40b344da14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3040,7 +3040,6 @@ dependencies = [ "alloy-sol-types", "auto_impl", "revm", - "revm-ee-tests", "rstest", "serde", "serde_json", @@ -3780,7 +3779,6 @@ dependencies = [ "revm-context-interface", "revm-database", "revm-database-interface", - "revm-ee-tests", "revm-handler", "revm-inspector", "revm-interpreter", diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 4706ab61f3..9c5b5d930c 100644 --- a/crates/op-revm/Cargo.toml +++ b/crates/op-revm/Cargo.toml @@ -32,7 +32,6 @@ sha2.workspace = true serde_json = { workspace = true, features = ["alloc", "preserve_order"] } serde = { workspace = true, features = ["derive"] } alloy-primitives.workspace = true -ee-tests.workspace = true [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst"] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index ce5ae49ea6..d7a2900ff3 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -34,7 +34,6 @@ state.workspace = true [dev-dependencies] serde_json = { workspace = true, features = ["alloc", "preserve_order"] } serde = { workspace = true, features = ["derive"] } -ee-tests.workspace = true [features] default = ["std", "secp256k1", "portable", "tracer", "c-kzg", "blst"] From 64ac080bac404f08f118fb07f42c56de1aabb31d Mon Sep 17 00:00:00 2001 From: radik878 Date: Thu, 7 Aug 2025 14:12:56 +0300 Subject: [PATCH 51/78] docs: update outdated opcode memory reference link (#2859) --- crates/bytecode/src/opcode.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bytecode/src/opcode.rs b/crates/bytecode/src/opcode.rs index 199b45406a..20a0aaad55 100644 --- a/crates/bytecode/src/opcode.rs +++ b/crates/bytecode/src/opcode.rs @@ -174,7 +174,7 @@ impl OpCode { /// Returns true if the opcode modifies memory. /// - /// + /// /// /// #[inline] From 7aa94b780bba8cb962f7cbe4c163a7ef3ce7122a Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 7 Aug 2025 15:09:04 +0200 Subject: [PATCH 52/78] chore: fix tags in migration guide (#2861) --- MIGRATION_GUIDE.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index be654ae3de..c5ba105dff 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,4 +1,4 @@ -# v83 tag (revm v28.0.0) from v82 tag (revm v27.1.0) +# v84 tag (revm v28.0.0) from v83 tag (revm v27.1.0) * `SystemCallEvm` functions got renamed and old ones are deprecated. Renaming is done to align it with other API calls. * `transact_system_call_finalize` is now `system_call`. @@ -10,7 +10,7 @@ * In `JournalInner` previous `precompiles`, `warm_coinbase_address` and `warm_preloaded_addresses` pub fields are now moved to `warm_addresses` to encapsulate addresses that are warm by default. All access list account are all loaded from database. -# v82 tag (revm v27.1.0) from v81 tag (revm v27.0.3) +# v83 tag (revm v27.1.0) from v82 tag (revm v27.0.3) * `ContextTr` gained `Host` supertrait. * Previously Host was implemented for any T that has ContextTr, this restricts specializations. From 96fbbefb1d4494a7d85af6608568f6dcef09fd96 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Fri, 8 Aug 2025 01:53:33 +0800 Subject: [PATCH 53/78] chore: make ci happy (#2863) --- crates/context/interface/src/transaction.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/context/interface/src/transaction.rs b/crates/context/interface/src/transaction.rs index 091512df3e..474d3e6ff7 100644 --- a/crates/context/interface/src/transaction.rs +++ b/crates/context/interface/src/transaction.rs @@ -55,7 +55,7 @@ pub trait Transaction { /// Note : Common field for all transactions. fn gas_limit(&self) -> u64; - /// The value sent to the receiver of [`TxKind::Call`][primitives::TxKind::Call]. + /// The value sent to the receiver of [`TxKind::Call`]. /// /// Note : Common field for all transactions. fn value(&self) -> U256; From dfe1fdbb02ce6ec8f537195032e1d0b36460490a Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Fri, 8 Aug 2025 01:54:28 +0800 Subject: [PATCH 54/78] chore: use HashMap::or_insert_with lazily compute (#2864) --- crates/database/src/states/bundle_account.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/database/src/states/bundle_account.rs b/crates/database/src/states/bundle_account.rs index ffa4b20b4f..5fa6035da3 100644 --- a/crates/database/src/states/bundle_account.rs +++ b/crates/database/src/states/bundle_account.rs @@ -118,7 +118,7 @@ impl BundleAccount { // if storage is not present set original value as current value. self.storage .entry(key) - .or_insert(StorageSlot::new(value)) + .or_insert_with(|| StorageSlot::new(value)) .present_value = value; } RevertToSlot::Destroyed => { From 00914e5d3704953f0d182d2d5ac76d3290ec22ae Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 9 Aug 2025 00:10:48 +0200 Subject: [PATCH 55/78] perf: small performance and safety improvements (#2868) - Remove unwrap() in primitives::short_address by using direct array indexing - Use lazy allocation with or_insert_with to avoid unnecessary Vec allocations - Pre-allocate Vec capacity in State::increment_balances based on iterator hint - Simplify iterator pattern in bundle_state to use destructuring - Use mem::take instead of mem::replace for bool values - Add #[inline] attributes to small hot-path functions in state module - Use unwrap_or_default() instead of unwrap_or(0) for cleaner code These are small incremental improvements that enhance performance and code safety without changing functionality. --- crates/database/src/states/bundle_state.rs | 4 ++-- crates/database/src/states/state.rs | 3 ++- crates/inspector/src/count_inspector.rs | 2 +- crates/primitives/src/lib.rs | 2 +- crates/state/src/lib.rs | 11 ++++++++++- 5 files changed, 16 insertions(+), 6 deletions(-) diff --git a/crates/database/src/states/bundle_state.rs b/crates/database/src/states/bundle_state.rs index 7b24298e04..f4b0a6cceb 100644 --- a/crates/database/src/states/bundle_state.rs +++ b/crates/database/src/states/bundle_state.rs @@ -307,7 +307,7 @@ impl BundleBuilder { reverts_size += account_revert.size_hint(); reverts_map .entry(block_number) - .or_insert(Vec::new()) + .or_insert_with(Vec::new) .push((address, account_revert)); } }); @@ -618,7 +618,7 @@ impl BundleState { // database so we can check if plain state was wiped or not. let mut account_storage_changed = Vec::with_capacity(account.storage.len()); - for (key, slot) in account.storage.iter().map(|(k, v)| (*k, *v)) { + for (&key, &slot) in account.storage.iter() { // If storage was destroyed that means that storage was wiped. // In that case we need to check if present storage value is different then ZERO. let destroyed_and_not_zero = was_destroyed && !slot.present_value.is_zero(); diff --git a/crates/database/src/states/state.rs b/crates/database/src/states/state.rs index 76ba828a6f..22f8263343 100644 --- a/crates/database/src/states/state.rs +++ b/crates/database/src/states/state.rs @@ -93,7 +93,8 @@ impl State { balances: impl IntoIterator, ) -> Result<(), DB::Error> { // Make transition and update cache state - let mut transitions = Vec::new(); + let balances = balances.into_iter(); + let mut transitions = Vec::with_capacity(balances.size_hint().0); for (address, balance) in balances { if balance == 0 { continue; diff --git a/crates/inspector/src/count_inspector.rs b/crates/inspector/src/count_inspector.rs index dd29efe15f..a80d09af62 100644 --- a/crates/inspector/src/count_inspector.rs +++ b/crates/inspector/src/count_inspector.rs @@ -47,7 +47,7 @@ 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(0) + self.opcode_counts.get(&opcode).copied().unwrap_or_default() } /// Get a reference to all opcode counts. diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index fd1f0b8c14..8fb8bceeb2 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -56,7 +56,7 @@ pub const SHORT_ADDRESS_CAP: usize = 300; #[inline] pub fn short_address(address: &Address) -> Option { if address.0[..18].iter().all(|b| *b == 0) { - let short_address = u16::from_be_bytes(address.0[18..].try_into().unwrap()) as usize; + let short_address = u16::from_be_bytes([address.0[18], address.0[19]]) as usize; if short_address < SHORT_ADDRESS_CAP { return Some(short_address); } diff --git a/crates/state/src/lib.rs b/crates/state/src/lib.rs index d10af7eac3..985af53a3d 100644 --- a/crates/state/src/lib.rs +++ b/crates/state/src/lib.rs @@ -52,46 +52,55 @@ impl Account { } /// Marks the account as self destructed. + #[inline] pub fn mark_selfdestruct(&mut self) { self.status |= AccountStatus::SelfDestructed; } /// Unmarks the account as self destructed. + #[inline] pub fn unmark_selfdestruct(&mut self) { self.status -= AccountStatus::SelfDestructed; } /// Is account marked for self destruct. + #[inline] pub fn is_selfdestructed(&self) -> bool { self.status.contains(AccountStatus::SelfDestructed) } /// Marks the account as touched + #[inline] pub fn mark_touch(&mut self) { self.status |= AccountStatus::Touched; } /// Unmarks the touch flag. + #[inline] pub fn unmark_touch(&mut self) { self.status -= AccountStatus::Touched; } /// If account status is marked as touched. + #[inline] pub fn is_touched(&self) -> bool { self.status.contains(AccountStatus::Touched) } /// Marks the account as newly created. + #[inline] pub fn mark_created(&mut self) { self.status |= AccountStatus::Created; } /// Unmarks the created flag. + #[inline] pub fn unmark_created(&mut self) { self.status -= AccountStatus::Created; } /// Marks the account as cold. + #[inline] pub fn mark_cold(&mut self) { self.status |= AccountStatus::Cold; } @@ -393,7 +402,7 @@ impl EvmStorageSlot { pub fn mark_warm_with_transaction_id(&mut self, transaction_id: usize) -> bool { let same_id = self.transaction_id == transaction_id; self.transaction_id = transaction_id; - let was_cold = core::mem::replace(&mut self.is_cold, false); + let was_cold = core::mem::take(&mut self.is_cold); if same_id { // only if transaction id is same we are returning was_cold. From 1c9e9c0dfcc927f5a1e300d3077514a647d8614d Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 9 Aug 2025 00:37:15 +0200 Subject: [PATCH 56/78] fix(osaka): do base/mod zero check after gas calc (#2872) --- crates/precompile/src/modexp.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index c787de05f6..9a7c170381 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -126,11 +126,6 @@ where return Err(PrecompileError::ModexpEip7823LimitSize); } - // special case for both base and mod length being 0. - if base_len == 0 && mod_len == 0 { - return Ok(PrecompileOutput::new(min_gas, Bytes::new())); - } - // Used to extract ADJUSTED_EXPONENT_LENGTH. let exp_highp_len = min(exp_len, 32); @@ -151,6 +146,10 @@ where return Err(PrecompileError::OutOfGas); } + if base_len == 0 && mod_len == 0 { + return Ok(PrecompileOutput::new(gas_cost, Bytes::new())); + } + // Padding is needed if the input does not contain all 3 values. let input_len = base_len.saturating_add(exp_len).saturating_add(mod_len); let input = right_pad_vec(input, input_len); From 82c08476582e3357cde9c93f0cba74c6d19f0870 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Sat, 9 Aug 2025 07:01:59 +0800 Subject: [PATCH 57/78] chore: use mem::take (#2870) --- crates/database/src/states/bundle_account.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/database/src/states/bundle_account.rs b/crates/database/src/states/bundle_account.rs index 5fa6035da3..54bd85ff10 100644 --- a/crates/database/src/states/bundle_account.rs +++ b/crates/database/src/states/bundle_account.rs @@ -232,7 +232,7 @@ impl BundleAccount { } AccountStatus::Destroyed => { // Clear this storage and move it to the Revert. - let this_storage = self.storage.drain().collect(); + let this_storage = core::mem::take(&mut self.storage); let ret = match self.status { AccountStatus::InMemoryChange | AccountStatus::Changed | AccountStatus::Loaded | AccountStatus::LoadedEmptyEIP161 => { Some(AccountRevert::new_selfdestructed(self.status, info_revert, this_storage)) @@ -356,7 +356,7 @@ impl BundleAccount { // Destroyed again will set empty account. AccountStatus::DestroyedChanged, AccountInfoRevert::RevertTo(self.info.clone().unwrap_or_default()), - self.storage.drain().collect(), + core::mem::take(&mut self.storage), HashMap::default(), )) } From f3c794b4df282d8053d60e67bca5c4a306031357 Mon Sep 17 00:00:00 2001 From: Arsenii Kulikov Date: Fri, 8 Aug 2025 16:04:04 -0700 Subject: [PATCH 58/78] feat: impl inspector for tuple (#2871) --- crates/inspector/src/inspector.rs | 58 +++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/crates/inspector/src/inspector.rs b/crates/inspector/src/inspector.rs index 7a2101c377..0df83be214 100644 --- a/crates/inspector/src/inspector.rs +++ b/crates/inspector/src/inspector.rs @@ -113,6 +113,64 @@ pub trait Inspector { } } +impl Inspector for (L, R) +where + L: Inspector, + R: Inspector, +{ + fn initialize_interp(&mut self, interp: &mut Interpreter, context: &mut CTX) { + self.0.initialize_interp(interp, context); + self.1.initialize_interp(interp, context); + } + + fn step(&mut self, interp: &mut Interpreter, context: &mut CTX) { + self.0.step(interp, context); + self.1.step(interp, context); + } + + fn step_end(&mut self, interp: &mut Interpreter, context: &mut CTX) { + self.0.step_end(interp, context); + 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 call(&mut self, context: &mut CTX, inputs: &mut CallInputs) -> Option { + self.0 + .call(context, inputs) + .or_else(|| self.1.call(context, inputs)) + } + + fn call_end(&mut self, context: &mut CTX, inputs: &CallInputs, outcome: &mut CallOutcome) { + self.0.call_end(context, inputs, outcome); + self.1.call_end(context, inputs, outcome); + } + + fn create(&mut self, context: &mut CTX, inputs: &mut CreateInputs) -> Option { + self.0 + .create(context, inputs) + .or_else(|| self.1.create(context, inputs)) + } + + fn create_end( + &mut self, + context: &mut CTX, + inputs: &CreateInputs, + outcome: &mut CreateOutcome, + ) { + self.0.create_end(context, inputs, outcome); + self.1.create_end(context, inputs, outcome); + } + + fn selfdestruct(&mut self, contract: Address, target: Address, value: U256) { + self.0.selfdestruct(contract, target, value); + self.1.selfdestruct(contract, target, value); + } +} + /// Extends the journal with additional methods that are used by the inspector. #[auto_impl(&mut, Box)] pub trait JournalExt { From 012aacedd6f64cb1e0ad651eace25a3bd3cb0191 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 11 Aug 2025 00:44:27 +0200 Subject: [PATCH 59/78] Aggregate changes from PRs #2866, #2867, and #2874 (#2876) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - PR #2866: Fix comment reference from calc_excess_blob_gas to calc_excess_blob_gas_osaka - PR #2867: Remove debug macro from test code in inspector lib - PR #2874: Replace len() == 0 with is_empty() for idiomatic Rust 🤖 Generated with [Claude Code](https://claude.ai/code) Co-authored-by: Claude --- crates/context/interface/src/block/blob.rs | 2 +- crates/inspector/src/lib.rs | 1 - crates/precompile/src/lib.rs | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/context/interface/src/block/blob.rs b/crates/context/interface/src/block/blob.rs index 2927559697..bb8e661ef3 100644 --- a/crates/context/interface/src/block/blob.rs +++ b/crates/context/interface/src/block/blob.rs @@ -65,7 +65,7 @@ impl BlobExcessGasAndPrice { } /// Calculates the `excess_blob_gas` from the parent header's `blob_gas_used` and `excess_blob_gas`. -/// uses [`calc_excess_blob_gas`] internally. +/// Uses [`calc_excess_blob_gas_osaka`] internally. #[inline] pub fn calc_excess_blob_gas( parent_excess_blob_gas: u64, diff --git a/crates/inspector/src/lib.rs b/crates/inspector/src/lib.rs index 93072de4bd..35338857bb 100644 --- a/crates/inspector/src/lib.rs +++ b/crates/inspector/src/lib.rs @@ -56,7 +56,6 @@ mod tests { fn test_step_halt() { let bytecode = [opcode::INVALID]; let r = run(&bytecode, HaltInspector); - dbg!(&r); assert!(r.is_success()); } diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index d461eb75ce..60eafe27e9 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -247,7 +247,7 @@ impl Precompiles { /// Is the precompiles list empty. pub fn is_empty(&self) -> bool { - self.inner.len() == 0 + self.inner.is_empty() } /// Returns the number of precompiles. From f2093b4e80b4fb8d6f736cb784761adf702f3028 Mon Sep 17 00:00:00 2001 From: Rej Ect <99460023+rejected-l@users.noreply.github.com> Date: Tue, 12 Aug 2025 11:24:30 +0200 Subject: [PATCH 60/78] build: update checkout action to v5 (#2880) --- .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 0dd2edabe8..58ca23373b 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@v4 + - uses: actions/checkout@v5 with: submodules: true - uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/book.yml b/.github/workflows/book.yml index 8733a73aba..919f41802f 100644 --- a/.github/workflows/book.yml +++ b/.github/workflows/book.yml @@ -17,7 +17,7 @@ jobs: name: test steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install mdbook run: | @@ -42,7 +42,7 @@ jobs: name: lint steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: Install mdbook-linkcheck run: | @@ -58,7 +58,7 @@ jobs: build: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 with: fetch-depth: 0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6287685f2b..dd65e75198 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@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} @@ -40,7 +40,7 @@ jobs: matrix: features: ["", "kzg-rs"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: targets: riscv32imac-unknown-none-elf @@ -58,7 +58,7 @@ jobs: matrix: features: ["", "serde", "std", "std,map-foldhash"] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable - run: cargo check --no-default-features -p revm --features=${{ matrix.features }} @@ -67,7 +67,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable - uses: taiki-e/install-action@cargo-hack - uses: Swatinem/rust-cache@v2 @@ -81,7 +81,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable - run: cargo clippy --workspace --all-targets --all-features env: @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: components: rust-docs @@ -105,7 +105,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: dtolnay/rust-toolchain@stable with: components: rustfmt @@ -115,7 +115,7 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - name: run zepter run: | cargo install zepter -f --locked @@ -126,5 +126,5 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 30 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v5 - uses: crate-ci/typos@v1 diff --git a/.github/workflows/ethereum-tests.yml b/.github/workflows/ethereum-tests.yml index 8bd366d24b..c8d6f99f27 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@v4 + uses: actions/checkout@v5 - name: Install toolchain uses: dtolnay/rust-toolchain@stable diff --git a/.github/workflows/release-plz.yml b/.github/workflows/release-plz.yml index d5b034760d..8390d785d2 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@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Install Rust toolchain From 149f5cc18edbc7cd47941434a0165394b841e428 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 12:06:55 +0200 Subject: [PATCH 61/78] chore: codspeed sstore sload opcodes (#2881) --- bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv b/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv index 29eb985378..d6a0d9cdf3 100644 --- a/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv +++ b/bins/revme/src/cmd/bench/gas_cost_estimator_sample.csv @@ -136,4 +136,6 @@ SWAP13_50,SWAP13,50,600360036003600360036003600360036003600360036003600360036003 SWAP14_50,SWAP14,50,6003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d9d SWAP15_50,SWAP15,50,6003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e9e SWAP16_50,SWAP16,50,60036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360039f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f9f -CLZ_50,CLZ,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360031e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e5050505050505050505050 \ No newline at end of file +CLZ_50,CLZ,50,6000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360031e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e501e505050505050505050505000 +SSTORE_50, SSTORE,50,600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555555500 +SLOAD_50, SLOAD,50,600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600060006000600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003600360036003545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545454545400 \ No newline at end of file From 220093a062cefb84b6c1a54a48290a0075b58b94 Mon Sep 17 00:00:00 2001 From: Snezhkko Date: Tue, 12 Aug 2025 19:27:12 +0300 Subject: [PATCH 62/78] chore(bytecode): remove unused Debug import (#2879) --- crates/bytecode/src/bytecode.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/bytecode/src/bytecode.rs b/crates/bytecode/src/bytecode.rs index b3095d3678..a6f09b7aa5 100644 --- a/crates/bytecode/src/bytecode.rs +++ b/crates/bytecode/src/bytecode.rs @@ -8,7 +8,6 @@ use crate::{ eip7702::{Eip7702Bytecode, EIP7702_MAGIC_BYTES}, BytecodeDecodeError, JumpTable, LegacyAnalyzedBytecode, LegacyRawBytecode, }; -use core::fmt::Debug; use primitives::{keccak256, Address, Bytes, B256, KECCAK_EMPTY}; /// Main bytecode structure with all variants. From 0e54e91d69c5d086ad32211864d1a544f2a9318f Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 12 Aug 2025 23:45:30 +0200 Subject: [PATCH 63/78] Revert "feat: removed padding in case last opcode is terminal (#2816)" (#2883) * Revert "feat: removed padding in case last opcode is terminating or unknown (#2816)" This reverts commit 5f67c14ab9402ef896a725c348187c34afde5201. * clippy and rm tests * doc comment changed --- crates/bytecode/src/legacy/analysis.rs | 27 +------------------------- crates/bytecode/src/legacy/analyzed.rs | 21 +------------------- 2 files changed, 2 insertions(+), 46 deletions(-) diff --git a/crates/bytecode/src/legacy/analysis.rs b/crates/bytecode/src/legacy/analysis.rs index 1ead1c478a..193b188642 100644 --- a/crates/bytecode/src/legacy/analysis.rs +++ b/crates/bytecode/src/legacy/analysis.rs @@ -39,14 +39,7 @@ pub fn analyze_legacy(bytecode: Bytes) -> (JumpTable, Bytes) { } } - let overflow_padding = (iterator as usize) - (end as usize); - - let stop_padding = opcode::OpCode::info_by_op(opcode) - .map(|o| !o.is_terminating() as usize) - .unwrap_or(1); - - let padding = overflow_padding + stop_padding; - + let padding = (iterator as usize) - (end as usize) + (opcode != opcode::STOP) as usize; let bytecode = if padding > 0 { let mut padded = Vec::with_capacity(bytecode.len() + padding); padded.extend_from_slice(&bytecode); @@ -180,22 +173,4 @@ mod tests { let (jump_table, _) = analyze_legacy(bytecode.clone().into()); assert!(!jump_table.is_valid(1)); // JUMPDEST in push data should not be valid } - - #[test] - fn test_terminating_opcodes_behavior() { - // Test all known terminating opcodes - let terminating_opcodes = [ - opcode::STOP, - opcode::RETURN, - opcode::REVERT, - opcode::INVALID, - opcode::SELFDESTRUCT, - ]; - - for &terminating_opcode in &terminating_opcodes { - let bytecode = vec![opcode::PUSH1, 0x01, terminating_opcode]; - let (_, padded_bytecode) = analyze_legacy(bytecode.clone().into()); - assert_eq!(padded_bytecode.len(), bytecode.len()); - } - } } diff --git a/crates/bytecode/src/legacy/analyzed.rs b/crates/bytecode/src/legacy/analyzed.rs index 7c29214b8d..72b0a43069 100644 --- a/crates/bytecode/src/legacy/analyzed.rs +++ b/crates/bytecode/src/legacy/analyzed.rs @@ -1,5 +1,4 @@ use super::JumpTable; -use crate::opcode; use primitives::Bytes; /// Legacy analyzed bytecode represents the original bytecode format used in Ethereum. @@ -66,7 +65,7 @@ impl LegacyAnalyzedBytecode { /// /// * If `original_len` is greater than `bytecode.len()` /// * If jump table length is less than `original_len`. - /// * If last bytecode byte is not `0x00` or if bytecode is empty. + /// * If bytecode is empty. pub fn new(bytecode: Bytes, original_len: usize, jump_table: JumpTable) -> Self { assert!( original_len <= bytecode.len(), @@ -77,16 +76,6 @@ impl LegacyAnalyzedBytecode { "jump table length is less than original length" ); assert!(!bytecode.is_empty(), "bytecode cannot be empty"); - - if let Some(&last_opcode) = bytecode.last() { - assert!( - opcode::OpCode::info_by_op(last_opcode) - .map(|o| o.is_terminating()) - .unwrap_or(false), - "last bytecode byte should be terminating" - ); - } - Self { bytecode, original_len, @@ -163,12 +152,4 @@ mod tests { let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 0]); let _ = LegacyAnalyzedBytecode::new(bytecode, 0, jump_table); } - - #[test] - #[should_panic(expected = "last bytecode byte should be terminating")] - fn test_panic_on_non_stop_bytecode() { - let bytecode = Bytes::from_static(&[opcode::PUSH1, 0x01]); - let jump_table = JumpTable::new(bitvec![u8, Lsb0; 0; 2]); - let _ = LegacyAnalyzedBytecode::new(bytecode, 2, jump_table); - } } From dd1fee86b663cdce44f2dfd69579dc87d1198f30 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 23:56:59 +0200 Subject: [PATCH 64/78] chore: release (#2873) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 30 +++++++++++++------------- Cargo.toml | 28 ++++++++++++------------ bins/revme/CHANGELOG.md | 6 ++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 8 +++++++ crates/bytecode/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 | 8 +++++++ 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 | 11 ++++++++++ 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/precompile/CHANGELOG.md | 10 +++++++++ crates/precompile/Cargo.toml | 2 +- crates/primitives/CHANGELOG.md | 6 ++++++ crates/primitives/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 +- 32 files changed, 148 insertions(+), 44 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 40b344da14..820a52e4b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3034,7 +3034,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "9.0.0" +version = "9.0.1" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3772,7 +3772,7 @@ dependencies = [ [[package]] name = "revm" -version = "28.0.0" +version = "28.0.1" dependencies = [ "revm-bytecode", "revm-context", @@ -3791,7 +3791,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "6.2.0" +version = "6.2.1" dependencies = [ "bitvec", "paste", @@ -3802,7 +3802,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "9.0.0" +version = "9.0.1" dependencies = [ "bitvec", "cfg-if", @@ -3818,7 +3818,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "10.0.0" +version = "10.0.1" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3832,7 +3832,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "7.0.3" +version = "7.0.4" dependencies = [ "alloy-eips", "alloy-provider", @@ -3850,7 +3850,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "7.0.3" +version = "7.0.4" dependencies = [ "anyhow", "auto_impl", @@ -3878,7 +3878,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "9.0.0" +version = "9.0.1" dependencies = [ "alloy-eip7702", "alloy-provider", @@ -3900,7 +3900,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "9.0.0" +version = "9.1.0" dependencies = [ "auto_impl", "either", @@ -3917,7 +3917,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "25.0.0" +version = "25.0.1" dependencies = [ "bincode 2.0.1", "revm-bytecode", @@ -3928,7 +3928,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "26.0.0" +version = "26.0.1" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3958,7 +3958,7 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "20.2.0" +version = "20.2.1" dependencies = [ "alloy-primitives", "num_enum", @@ -3968,7 +3968,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "7.0.3" +version = "7.0.4" dependencies = [ "bitflags", "revm-bytecode", @@ -3978,7 +3978,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "9.0.0" +version = "9.0.1" dependencies = [ "k256", "revm", @@ -3989,7 +3989,7 @@ dependencies = [ [[package]] name = "revme" -version = "7.2.0" +version = "7.2.1" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 169a514a25..4a0e5b44fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "28.0.0", default-features = false } -primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.2.0", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.0", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "7.0.3", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.3", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "7.0.3", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.0", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "9.0.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "26.0.0", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "9.0.0", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "9.0.0", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.0.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "9.0.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "9.0.0", default-features = false } +revm = { path = "crates/revm", version = "28.0.1", default-features = false } +primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.2.1", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.1", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "7.0.4", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.4", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "7.0.4", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.1", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "9.1.0", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "26.0.1", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "9.0.1", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "9.0.1", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.0.1", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "9.0.1", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "9.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 755f25f0fc..21cfe2711e 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] +## [7.2.1](https://github.com/bluealloy/revm/compare/revme-v7.2.0...revme-v7.2.1) - 2025-08-12 + +### Other + +- codspeed sstore sload opcodes ([#2881](https://github.com/bluealloy/revm/pull/2881)) + ## [7.2.0](https://github.com/bluealloy/revm/compare/revme-v7.1.0...revme-v7.2.0) - 2025-08-06 ### Added diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 83912a38b3..5fd519ff82 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 = "7.2.0" +version = "7.2.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index c86123cf0e..1a20ca601d 100644 --- a/crates/bytecode/CHANGELOG.md +++ b/crates/bytecode/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.2.1](https://github.com/bluealloy/revm/compare/revm-bytecode-v6.2.0...revm-bytecode-v6.2.1) - 2025-08-12 + +### Other + +- Revert "feat: removed padding in case last opcode is terminal ([#2816](https://github.com/bluealloy/revm/pull/2816))" ([#2883](https://github.com/bluealloy/revm/pull/2883)) +- *(bytecode)* remove unused Debug import ([#2879](https://github.com/bluealloy/revm/pull/2879)) +- update outdated opcode memory reference link ([#2859](https://github.com/bluealloy/revm/pull/2859)) + ## [6.2.0](https://github.com/bluealloy/revm/compare/revm-bytecode-v6.1.0...revm-bytecode-v6.2.0) - 2025-08-06 ### Added diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index 4e4335cae3..39af599e6f 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "6.2.0" +version = "6.2.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index 76e712b570..fd85a9bd89 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] +## [9.0.1](https://github.com/bluealloy/revm/compare/revm-context-v9.0.0...revm-context-v9.0.1) - 2025-08-12 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode, revm-state, revm-context-interface, revm-database, revm-database-interface + ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-context-v8.0.4...revm-context-v9.0.0) - 2025-08-06 ### Added diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 6f947017da..443a6aa532 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "9.0.0" +version = "9.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/interface/CHANGELOG.md b/crates/context/interface/CHANGELOG.md index e7135ad2c5..e384ec6c67 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] +## [10.0.1](https://github.com/bluealloy/revm/compare/revm-context-interface-v10.0.0...revm-context-interface-v10.0.1) - 2025-08-12 + +### Other + +- Aggregate changes from PRs #2866, #2867, and #2874 ([#2876](https://github.com/bluealloy/revm/pull/2876)) +- make ci happy ([#2863](https://github.com/bluealloy/revm/pull/2863)) + ## [10.0.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v9.0.0...revm-context-interface-v10.0.0) - 2025-08-06 ### Added diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index 1f1dfa8c34..f704454a56 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 = "10.0.0" +version = "10.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index 39c228f1af..3ddba63d80 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.0.4](https://github.com/bluealloy/revm/compare/revm-database-v7.0.3...revm-database-v7.0.4) - 2025-08-12 + +### Other + +- use mem::take ([#2870](https://github.com/bluealloy/revm/pull/2870)) +- small performance and safety improvements ([#2868](https://github.com/bluealloy/revm/pull/2868)) +- use HashMap::or_insert_with lazily compute ([#2864](https://github.com/bluealloy/revm/pull/2864)) + ## [7.0.3](https://github.com/bluealloy/revm/compare/revm-database-v7.0.2...revm-database-v7.0.3) - 2025-08-06 ### Other diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 72c606100a..e8d1786ab0 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "7.0.3" +version = "7.0.4" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/interface/CHANGELOG.md b/crates/database/interface/CHANGELOG.md index 6cb55fedad..ebf4f3b5af 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] +## [7.0.4](https://github.com/bluealloy/revm/compare/revm-database-interface-v7.0.3...revm-database-interface-v7.0.4) - 2025-08-12 + +### Other + +- updated the following local packages: revm-primitives, revm-state + ## [7.0.3](https://github.com/bluealloy/revm/compare/revm-database-interface-v7.0.2...revm-database-interface-v7.0.3) - 2025-08-06 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index d822889615..46d52ea292 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 = "7.0.3" +version = "7.0.4" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 0a2fbb8016..2300934602 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] +## [9.0.1](https://github.com/bluealloy/revm/compare/revm-handler-v9.0.0...revm-handler-v9.0.1) - 2025-08-12 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode, revm-state, revm-context-interface, revm-database, revm-precompile, revm-database-interface, revm-context, revm-interpreter + ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v8.1.0...revm-handler-v9.0.0) - 2025-08-06 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 9eff0128cf..e82763dace 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "9.0.0" +version = "9.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 7dacd2da19..668f4180b3 100644 --- a/crates/inspector/CHANGELOG.md +++ b/crates/inspector/CHANGELOG.md @@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v9.0.0...revm-inspector-v9.1.0) - 2025-08-12 + +### Added + +- impl inspector for tuple ([#2871](https://github.com/bluealloy/revm/pull/2871)) + +### Other + +- Aggregate changes from PRs #2866, #2867, and #2874 ([#2876](https://github.com/bluealloy/revm/pull/2876)) +- small performance and safety improvements ([#2868](https://github.com/bluealloy/revm/pull/2868)) + ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v8.1.0...revm-inspector-v9.0.0) - 2025-08-06 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 4d2459dab7..feb4c5a6af 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "9.0.0" +version = "9.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 75d2a11614..7b16ab2694 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] +## [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 diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index da461c04f1..fdc779ba44 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 = "25.0.0" +version = "25.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 110d7f1fbd..0639417411 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] +## [9.0.1](https://github.com/bluealloy/revm/compare/op-revm-v9.0.0...op-revm-v9.0.1) - 2025-08-12 + +### Other + +- updated the following local packages: revm + ## [9.0.0](https://github.com/bluealloy/revm/compare/op-revm-v8.1.0...op-revm-v9.0.0) - 2025-08-06 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 9c5b5d930c..39557efcd1 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 = "9.0.0" +version = "9.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index b5f37a11c1..ccbe8633c0 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [26.0.1](https://github.com/bluealloy/revm/compare/revm-precompile-v26.0.0...revm-precompile-v26.0.1) - 2025-08-12 + +### Fixed + +- *(osaka)* do base/mod zero check after gas calc ([#2872](https://github.com/bluealloy/revm/pull/2872)) + +### Other + +- Aggregate changes from PRs #2866, #2867, and #2874 ([#2876](https://github.com/bluealloy/revm/pull/2876)) + ## [26.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v25.0.0...revm-precompile-v26.0.0) - 2025-08-06 ### Added diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 6fbd79c742..532e86723b 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 = "26.0.0" +version = "26.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index d1f0ae85dd..9b8105eae8 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] +## [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 diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index eaec8a799f..e6de97202f 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-primitives" description = "Revm primitives types" -version = "20.2.0" +version = "20.2.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 9fabcc2879..52c94eb72d 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] +## [28.0.1](https://github.com/bluealloy/revm/compare/revm-v28.0.0...revm-v28.0.1) - 2025-08-12 + +### Other + +- updated the following local packages: revm-primitives, revm-bytecode, revm-state, revm-context-interface, revm-database, revm-precompile, revm-inspector, revm-database-interface, revm-context, revm-interpreter, revm-handler + ## [28.0.0](https://github.com/bluealloy/revm/compare/revm-v27.1.0...revm-v28.0.0) - 2025-08-06 ### Added diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index d7a2900ff3..b44630da84 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 = "28.0.0" +version = "28.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index 6fa0424496..dcb663e857 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] +## [7.0.4](https://github.com/bluealloy/revm/compare/revm-state-v7.0.3...revm-state-v7.0.4) - 2025-08-12 + +### Other + +- small performance and safety improvements ([#2868](https://github.com/bluealloy/revm/pull/2868)) + ## [7.0.3](https://github.com/bluealloy/revm/compare/revm-state-v7.0.2...revm-state-v7.0.3) - 2025-08-06 ### Fixed diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index e6ac718259..070248bf77 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "7.0.3" +version = "7.0.4" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index ef52d33898..aedf5b0076 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] +## [9.0.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v9.0.0...revm-statetest-types-v9.0.1) - 2025-08-12 + +### Other + +- updated the following local packages: revm + ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-statetest-types-v8.0.5...revm-statetest-types-v9.0.0) - 2025-08-06 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index c1c48c1d75..5dce5eed34 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 = "9.0.0" +version = "9.0.1" authors.workspace = true edition.workspace = true keywords.workspace = true From 46290cc27b6516201906918ac245d3dfc96e09fb Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 13 Aug 2025 00:10:57 +0200 Subject: [PATCH 65/78] bump: tag v85 revm v28.0.1 (#2884) --- CHANGELOG.md | 82 +++++++++++++++++++++++++++++----------------- MIGRATION_GUIDE.md | 4 +++ 2 files changed, 56 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f92dcb7b7..dd21bb4f94 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. +# v85 +date: 12.08.2025 + +Reverting: "feat: removed padding in case last opcode is terminal (#2816)" (#2883) + +* `revm-primitives`: 20.2.0 -> 20.2.1 (✓ API compatible changes) +* `revm-bytecode`: 6.2.0 -> 6.2.1 (✓ API compatible changes) +* `revm-state`: 7.0.3 -> 7.0.4 (✓ API compatible changes) +* `revm-context-interface`: 10.0.0 -> 10.0.1 (✓ API compatible changes) +* `revm-database`: 7.0.3 -> 7.0.4 (✓ API compatible changes) +* `revm-precompile`: 26.0.0 -> 26.0.1 (✓ API compatible changes) +* `revm-inspector`: 9.0.0 -> 9.1.0 (✓ API compatible changes) +* `revme`: 7.2.0 -> 7.2.1 (✓ API compatible changes) +* `revm-ee-tests`: 0.1.0 +* `revm-database-interface`: 7.0.3 -> 7.0.4 +* `revm-context`: 9.0.0 -> 9.0.1 +* `revm-interpreter`: 25.0.0 -> 25.0.1 +* `revm-handler`: 9.0.0 -> 9.0.1 +* `revm`: 28.0.0 -> 28.0.1 +* `revm-statetest-types`: 9.0.0 -> 9.0.1 +* `op-revm`: 9.0.0 -> 9.0.1 + # v84 date: 07.08.2025 @@ -7,42 +29,42 @@ Small perf and maintainance release. revm-inspector@9.0.0 revm@28.0.0 revm-statetest-types@9.0.0 -`revm-primitives`: 20.1.0 -> 20.2.0 (✓ API compatible changes) -`revm-bytecode`: 6.1.0 -> 6.2.0 (✓ API compatible changes) -`revm-state`: 7.0.2 -> 7.0.3 (✓ API compatible changes) -`revm-database-interface`: 7.0.2 -> 7.0.3 (✓ API compatible changes) -`revm-context-interface`: 9.0.0 -> 10.0.0 (⚠ API breaking changes) -`revm-context`: 8.0.4 -> 9.0.0 (⚠ API breaking changes) -`revm-database`: 7.0.2 -> 7.0.3 (✓ API compatible changes) -`revm-interpreter`: 24.0.0 -> 25.0.0 (⚠ API breaking changes) -`revm-precompile`: 25.0.0 -> 26.0.0 (⚠ API breaking changes) -`revm-handler`: 8.1.0 -> 9.0.0 (⚠ API breaking changes) -`revm-inspector`: 8.1.0 -> 9.0.0 (✓ API compatible changes) -`revm`: 27.1.0 -> 28.0.0 (✓ API compatible changes) -`revm-statetest-types`: 8.0.5 -> 9.0.0 (✓ API compatible changes) -`revme`: 7.1.0 -> 7.2.0 (✓ API compatible changes) -`op-revm`: 8.1.0 -> 9.0.0 (⚠ API breaking changes) +* `revm-primitives`: 20.1.0 -> 20.2.0 (✓ API compatible changes) +* `revm-bytecode`: 6.1.0 -> 6.2.0 (✓ API compatible changes) +* `revm-state`: 7.0.2 -> 7.0.3 (✓ API compatible changes) +* `revm-database-interface`: 7.0.2 -> 7.0.3 (✓ API compatible changes) +* `revm-context-interface`: 9.0.0 -> 10.0.0 (⚠ API breaking changes) +* `revm-context`: 8.0.4 -> 9.0.0 (⚠ API breaking changes) +* `revm-database`: 7.0.2 -> 7.0.3 (✓ API compatible changes) +* `revm-interpreter`: 24.0.0 -> 25.0.0 (⚠ API breaking changes) +* `revm-precompile`: 25.0.0 -> 26.0.0 (⚠ API breaking changes) +* `revm-handler`: 8.1.0 -> 9.0.0 (⚠ API breaking changes) +* `revm-inspector`: 8.1.0 -> 9.0.0 (✓ API compatible changes) +* `revm`: 27.1.0 -> 28.0.0 (✓ API compatible changes) +* `revm-statetest-types`: 8.0.5 -> 9.0.0 (✓ API compatible changes) +* `revme`: 7.1.0 -> 7.2.0 (✓ API compatible changes) +* `op-revm`: 8.1.0 -> 9.0.0 (⚠ API breaking changes) # v83 date: 23.07.2025 Fusaka devnet-3 support. Performance regresion fixes. -`revm-primitives`: 20.0.0 -> 20.1.0 (✓ API compatible changes) -`revm-bytecode`: 6.0.1 -> 6.1.0 (✓ API compatible changes) -`revm-database-interface`: 7.0.1 -> 7.0.2 (✓ API compatible changes) -`revm-context-interface`: 8.0.1 -> 9.0.0 (⚠ API breaking changes) -`revm-context`: 8.0.3 -> 8.0.4 (✓ API compatible changes) -`revm-interpreter`: 23.0.2 -> 24.0.0 (⚠ API breaking changes) -`revm-precompile`: 24.0.1 -> 25.0.0 (⚠ API breaking changes) -`revm-handler`: 8.0.3 -> 8.1.0 (✓ API compatible changes) -`revm-inspector`: 8.0.3 -> 8.1.0 (✓ API compatible changes) -`revm`: 27.0.3 -> 27.1.0 (✓ API compatible changes) -`revme`: 7.0.4 -> 7.1.0 (✓ API compatible changes) -`op-revm`: 8.0.3 -> 8.1.0 (✓ API compatible changes) -`revm-state`: 7.0.1 -> 7.0.2 -`revm-database`: 7.0.1 -> 7.0.2 -`revm-statetest-types`: 8.0.4 -> 8.0.5 +* `revm-primitives`: 20.0.0 -> 20.1.0 (✓ API compatible changes) +* `revm-bytecode`: 6.0.1 -> 6.1.0 (✓ API compatible changes) +* `revm-database-interface`: 7.0.1 -> 7.0.2 (✓ API compatible changes) +* `revm-context-interface`: 8.0.1 -> 9.0.0 (⚠ API breaking changes) +* `revm-context`: 8.0.3 -> 8.0.4 (✓ API compatible changes) +* `revm-interpreter`: 23.0.2 -> 24.0.0 (⚠ API breaking changes) +* `revm-precompile`: 24.0.1 -> 25.0.0 (⚠ API breaking changes) +* `revm-handler`: 8.0.3 -> 8.1.0 (✓ API compatible changes) +* `revm-inspector`: 8.0.3 -> 8.1.0 (✓ API compatible changes) +* `revm`: 27.0.3 -> 27.1.0 (✓ API compatible changes) +* `revme`: 7.0.4 -> 7.1.0 (✓ API compatible changes) +* `op-revm`: 8.0.3 -> 8.1.0 (✓ API compatible changes) +* `revm-state`: 7.0.1 -> 7.0.2 +* `revm-database`: 7.0.1 -> 7.0.2 +* `revm-statetest-types`: 8.0.4 -> 8.0.5 # v82 date 14.07.2025 diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index c5ba105dff..573a9154f1 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,3 +1,7 @@ +# v85 tag (revm v28.0.1) from v84 tag (revm v28.0.0) + +Forward compatible version. + # v84 tag (revm v28.0.0) from v83 tag (revm v27.1.0) * `SystemCallEvm` functions got renamed and old ones are deprecated. Renaming is done to align it with other API calls. From aaff4e6bc8a9338c9a3166582d1a1257ffbb7121 Mon Sep 17 00:00:00 2001 From: nk_ysg Date: Wed, 13 Aug 2025 18:34:29 +0800 Subject: [PATCH 66/78] test: add AccountStatus unit test (#2869) * test: add AccountStatus unit test * update --- crates/database/src/states/account_status.rs | 390 ++++++++++++++++--- 1 file changed, 330 insertions(+), 60 deletions(-) diff --git a/crates/database/src/states/account_status.rs b/crates/database/src/states/account_status.rs index ac443fb280..8b3bfcebf7 100644 --- a/crates/database/src/states/account_status.rs +++ b/crates/database/src/states/account_status.rs @@ -41,9 +41,7 @@ impl AccountStatus { pub fn is_not_modified(&self) -> bool { matches!( self, - AccountStatus::LoadedNotExisting - | AccountStatus::Loaded - | AccountStatus::LoadedEmptyEIP161 + Self::LoadedNotExisting | Self::Loaded | Self::LoadedEmptyEIP161 ) } @@ -52,9 +50,7 @@ impl AccountStatus { pub fn was_destroyed(&self) -> bool { matches!( self, - AccountStatus::Destroyed - | AccountStatus::DestroyedChanged - | AccountStatus::DestroyedAgain + Self::Destroyed | Self::DestroyedChanged | Self::DestroyedAgain ) } @@ -62,11 +58,11 @@ impl AccountStatus { pub fn is_storage_known(&self) -> bool { matches!( self, - AccountStatus::LoadedNotExisting - | AccountStatus::InMemoryChange - | AccountStatus::Destroyed - | AccountStatus::DestroyedChanged - | AccountStatus::DestroyedAgain + Self::LoadedNotExisting + | Self::InMemoryChange + | Self::Destroyed + | Self::DestroyedChanged + | Self::DestroyedAgain ) } @@ -74,27 +70,27 @@ impl AccountStatus { /// This means that some storage values can be found in both /// memory and database. pub fn is_modified_and_not_destroyed(&self) -> bool { - matches!(self, AccountStatus::Changed | AccountStatus::InMemoryChange) + matches!(self, Self::Changed | Self::InMemoryChange) } /// Returns the next account status on creation. - pub fn on_created(&self) -> AccountStatus { + pub fn on_created(&self) -> Self { match self { // If account was destroyed previously just copy new info to it. - AccountStatus::DestroyedAgain - | AccountStatus::Destroyed - | AccountStatus::DestroyedChanged => AccountStatus::DestroyedChanged, + Self::DestroyedAgain + | Self::Destroyed + | Self::DestroyedChanged => Self::DestroyedChanged, // If account is loaded from db. - AccountStatus::LoadedNotExisting + Self::LoadedNotExisting // Loaded empty eip161 to creates is not possible as CREATE2 was added after EIP-161 - | AccountStatus::LoadedEmptyEIP161 - | AccountStatus::Loaded - | AccountStatus::Changed - | AccountStatus::InMemoryChange => { + | Self::LoadedEmptyEIP161 + | Self::Loaded + | Self::Changed + | Self::InMemoryChange => { // If account is loaded and not empty this means that account has some balance. // This means that account cannot be created. // We are assuming that EVM did necessary checks before allowing account to be created. - AccountStatus::InMemoryChange + Self::InMemoryChange } } } @@ -104,20 +100,16 @@ impl AccountStatus { /// # Panics /// /// If current status is [AccountStatus::Loaded] or [AccountStatus::Changed]. - pub fn on_touched_empty_post_eip161(&self) -> AccountStatus { + pub fn on_touched_empty_post_eip161(&self) -> Self { match self { // Account can be touched but not existing. The status should remain the same. - AccountStatus::LoadedNotExisting => AccountStatus::LoadedNotExisting, + Self::LoadedNotExisting => Self::LoadedNotExisting, // Account can be created empty and only then touched. - AccountStatus::InMemoryChange - | AccountStatus::Destroyed - | AccountStatus::LoadedEmptyEIP161 => AccountStatus::Destroyed, + Self::InMemoryChange | Self::Destroyed | Self::LoadedEmptyEIP161 => Self::Destroyed, // Transition to destroy the account. - AccountStatus::DestroyedAgain | AccountStatus::DestroyedChanged => { - AccountStatus::DestroyedAgain - } + Self::DestroyedAgain | Self::DestroyedChanged => Self::DestroyedAgain, // Account statuses considered unreachable. - AccountStatus::Loaded | AccountStatus::Changed => { + Self::Loaded | Self::Changed => { unreachable!("Wrong state transition, touch empty is not possible from {self:?}"); } } @@ -129,77 +121,69 @@ impl AccountStatus { /// # Panics /// /// If current status is [AccountStatus::Loaded] or [AccountStatus::Changed]. - pub fn on_touched_created_pre_eip161(&self, had_no_info: bool) -> Option { + pub fn on_touched_created_pre_eip161(&self, had_no_info: bool) -> Option { match self { - AccountStatus::LoadedEmptyEIP161 => None, - AccountStatus::DestroyedChanged => { + Self::LoadedEmptyEIP161 => None, + Self::DestroyedChanged => { if had_no_info { None } else { - Some(AccountStatus::DestroyedChanged) + Some(Self::DestroyedChanged) } } - AccountStatus::Destroyed | AccountStatus::DestroyedAgain => { - Some(AccountStatus::DestroyedChanged) - } - AccountStatus::InMemoryChange | AccountStatus::LoadedNotExisting => { - Some(AccountStatus::InMemoryChange) - } - AccountStatus::Loaded | AccountStatus::Changed => { + Self::Destroyed | Self::DestroyedAgain => Some(Self::DestroyedChanged), + Self::InMemoryChange | Self::LoadedNotExisting => Some(Self::InMemoryChange), + Self::Loaded | Self::Changed => { unreachable!("Wrong state transition, touch crate is not possible from {self:?}") } } } /// Returns the next account status on change. - pub fn on_changed(&self, had_no_nonce_and_code: bool) -> AccountStatus { + pub fn on_changed(&self, had_no_nonce_and_code: bool) -> Self { match self { // If the account was loaded as not existing, promote it to changed. // This account was likely created by a balance transfer. - AccountStatus::LoadedNotExisting => AccountStatus::InMemoryChange, + Self::LoadedNotExisting => Self::InMemoryChange, // Change on empty account, should transfer storage if there is any. // There is possibility that there are storage entries inside db. // That storage is used in merkle tree calculation before state clear EIP. - AccountStatus::LoadedEmptyEIP161 => AccountStatus::InMemoryChange, + Self::LoadedEmptyEIP161 => Self::InMemoryChange, // The account was loaded as existing. - AccountStatus::Loaded => { + Self::Loaded => { if had_no_nonce_and_code { // Account is fully in memory - AccountStatus::InMemoryChange + Self::InMemoryChange } else { // Can be contract and some of storage slots can be present inside db. - AccountStatus::Changed + Self::Changed } } // On change, the "changed" type account statuses are preserved. // Any checks for empty accounts are done outside of this fn. - AccountStatus::Changed => AccountStatus::Changed, - AccountStatus::InMemoryChange => AccountStatus::InMemoryChange, - AccountStatus::DestroyedChanged => AccountStatus::DestroyedChanged, + Self::Changed => Self::Changed, + Self::InMemoryChange => Self::InMemoryChange, + Self::DestroyedChanged => Self::DestroyedChanged, // If account is destroyed and then changed this means this is // balance transfer. - AccountStatus::Destroyed | AccountStatus::DestroyedAgain => { - AccountStatus::DestroyedChanged - } + Self::Destroyed | Self::DestroyedAgain => Self::DestroyedChanged, } } /// Returns the next account status on selfdestruct. - pub fn on_selfdestructed(&self) -> AccountStatus { + pub fn on_selfdestructed(&self) -> Self { match self { // Non existing account can't be destroyed. - AccountStatus::LoadedNotExisting => AccountStatus::LoadedNotExisting, + Self::LoadedNotExisting => Self::LoadedNotExisting, // If account is created and selfdestructed in the same block, mark it as destroyed again. // Note: There is no big difference between Destroyed and DestroyedAgain in this case, // but was added for clarity. - AccountStatus::DestroyedChanged - | AccountStatus::DestroyedAgain - | AccountStatus::Destroyed => AccountStatus::DestroyedAgain, + Self::DestroyedChanged | Self::DestroyedAgain | Self::Destroyed => Self::DestroyedAgain, // Transition to destroyed status. - _ => AccountStatus::Destroyed, + _ => Self::Destroyed, } } @@ -271,4 +255,290 @@ mod test { assert!(!AccountStatus::DestroyedChanged.is_modified_and_not_destroyed()); assert!(!AccountStatus::DestroyedAgain.is_modified_and_not_destroyed()); } + + #[test] + fn test_on_created() { + assert_eq!( + AccountStatus::Destroyed.on_created(), + AccountStatus::DestroyedChanged + ); + assert_eq!( + AccountStatus::DestroyedAgain.on_created(), + AccountStatus::DestroyedChanged + ); + assert_eq!( + AccountStatus::DestroyedChanged.on_created(), + AccountStatus::DestroyedChanged + ); + + assert_eq!( + AccountStatus::LoadedNotExisting.on_created(), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::Loaded.on_created(), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_created(), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::Changed.on_created(), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::InMemoryChange.on_created(), + AccountStatus::InMemoryChange + ); + } + + #[test] + fn test_on_touched_empty_post_eip161() { + assert_eq!( + AccountStatus::LoadedNotExisting.on_touched_empty_post_eip161(), + AccountStatus::LoadedNotExisting + ); + assert_eq!( + AccountStatus::InMemoryChange.on_touched_empty_post_eip161(), + AccountStatus::Destroyed + ); + assert_eq!( + AccountStatus::Destroyed.on_touched_empty_post_eip161(), + AccountStatus::Destroyed + ); + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_touched_empty_post_eip161(), + AccountStatus::Destroyed + ); + assert_eq!( + AccountStatus::DestroyedAgain.on_touched_empty_post_eip161(), + AccountStatus::DestroyedAgain + ); + assert_eq!( + AccountStatus::DestroyedChanged.on_touched_empty_post_eip161(), + AccountStatus::DestroyedAgain + ); + } + + #[test] + fn test_on_touched_created_pre_eip161() { + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_touched_created_pre_eip161(true), + None + ); + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_touched_created_pre_eip161(false), + None + ); + + assert_eq!( + AccountStatus::DestroyedChanged.on_touched_created_pre_eip161(true), + None + ); + assert_eq!( + AccountStatus::DestroyedChanged.on_touched_created_pre_eip161(false), + Some(AccountStatus::DestroyedChanged) + ); + + assert_eq!( + AccountStatus::Destroyed.on_touched_created_pre_eip161(true), + Some(AccountStatus::DestroyedChanged) + ); + assert_eq!( + AccountStatus::Destroyed.on_touched_created_pre_eip161(false), + Some(AccountStatus::DestroyedChanged) + ); + + assert_eq!( + AccountStatus::DestroyedAgain.on_touched_created_pre_eip161(true), + Some(AccountStatus::DestroyedChanged) + ); + assert_eq!( + AccountStatus::DestroyedAgain.on_touched_created_pre_eip161(false), + Some(AccountStatus::DestroyedChanged) + ); + + assert_eq!( + AccountStatus::InMemoryChange.on_touched_created_pre_eip161(true), + Some(AccountStatus::InMemoryChange) + ); + assert_eq!( + AccountStatus::InMemoryChange.on_touched_created_pre_eip161(false), + Some(AccountStatus::InMemoryChange) + ); + + assert_eq!( + AccountStatus::LoadedNotExisting.on_touched_created_pre_eip161(true), + Some(AccountStatus::InMemoryChange) + ); + assert_eq!( + AccountStatus::LoadedNotExisting.on_touched_created_pre_eip161(false), + Some(AccountStatus::InMemoryChange) + ); + } + + #[test] + fn test_on_changed() { + assert_eq!( + AccountStatus::LoadedNotExisting.on_changed(true), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::LoadedNotExisting.on_changed(false), + AccountStatus::InMemoryChange + ); + + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_changed(true), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_changed(false), + AccountStatus::InMemoryChange + ); + + assert_eq!( + AccountStatus::Loaded.on_changed(true), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::Loaded.on_changed(false), + AccountStatus::Changed + ); + + assert_eq!( + AccountStatus::Changed.on_changed(true), + AccountStatus::Changed + ); + assert_eq!( + AccountStatus::Changed.on_changed(false), + AccountStatus::Changed + ); + + assert_eq!( + AccountStatus::InMemoryChange.on_changed(true), + AccountStatus::InMemoryChange + ); + assert_eq!( + AccountStatus::InMemoryChange.on_changed(false), + AccountStatus::InMemoryChange + ); + + assert_eq!( + AccountStatus::DestroyedChanged.on_changed(true), + AccountStatus::DestroyedChanged + ); + assert_eq!( + AccountStatus::DestroyedChanged.on_changed(false), + AccountStatus::DestroyedChanged + ); + + assert_eq!( + AccountStatus::Destroyed.on_changed(true), + AccountStatus::DestroyedChanged + ); + assert_eq!( + AccountStatus::Destroyed.on_changed(false), + AccountStatus::DestroyedChanged + ); + + assert_eq!( + AccountStatus::DestroyedAgain.on_changed(true), + AccountStatus::DestroyedChanged + ); + assert_eq!( + AccountStatus::DestroyedAgain.on_changed(false), + AccountStatus::DestroyedChanged + ); + } + + #[test] + fn test_on_selfdestructed() { + assert_eq!( + AccountStatus::LoadedNotExisting.on_selfdestructed(), + AccountStatus::LoadedNotExisting + ); + + assert_eq!( + AccountStatus::DestroyedChanged.on_selfdestructed(), + AccountStatus::DestroyedAgain + ); + assert_eq!( + AccountStatus::DestroyedAgain.on_selfdestructed(), + AccountStatus::DestroyedAgain + ); + assert_eq!( + AccountStatus::Destroyed.on_selfdestructed(), + AccountStatus::DestroyedAgain + ); + + assert_eq!( + AccountStatus::Loaded.on_selfdestructed(), + AccountStatus::Destroyed + ); + assert_eq!( + AccountStatus::LoadedEmptyEIP161.on_selfdestructed(), + AccountStatus::Destroyed + ); + assert_eq!( + AccountStatus::InMemoryChange.on_selfdestructed(), + AccountStatus::Destroyed + ); + assert_eq!( + AccountStatus::Changed.on_selfdestructed(), + AccountStatus::Destroyed + ); + } + + #[test] + fn test_transition() { + let mut status = AccountStatus::Destroyed; + status.transition(AccountStatus::Loaded); + assert_eq!(status, AccountStatus::DestroyedChanged); + + let mut status = AccountStatus::DestroyedChanged; + status.transition(AccountStatus::InMemoryChange); + assert_eq!(status, AccountStatus::DestroyedChanged); + + let mut status = AccountStatus::DestroyedAgain; + status.transition(AccountStatus::Changed); + assert_eq!(status, AccountStatus::DestroyedChanged); + + let mut status = AccountStatus::InMemoryChange; + status.transition(AccountStatus::Loaded); + assert_eq!(status, AccountStatus::InMemoryChange); + + let mut status = AccountStatus::InMemoryChange; + status.transition(AccountStatus::Changed); + assert_eq!(status, AccountStatus::InMemoryChange); + + let mut status = AccountStatus::Loaded; + status.transition(AccountStatus::Changed); + assert_eq!(status, AccountStatus::Changed); + + let mut status = AccountStatus::LoadedNotExisting; + status.transition(AccountStatus::InMemoryChange); + assert_eq!(status, AccountStatus::InMemoryChange); + + let mut status = AccountStatus::LoadedEmptyEIP161; + status.transition(AccountStatus::Loaded); + assert_eq!(status, AccountStatus::Loaded); + + let mut status = AccountStatus::Destroyed; + status.transition(AccountStatus::DestroyedChanged); + assert_eq!(status, AccountStatus::DestroyedChanged); + + let mut status = AccountStatus::DestroyedAgain; + status.transition(AccountStatus::Destroyed); + assert_eq!(status, AccountStatus::Destroyed); + + let mut status = AccountStatus::Loaded; + status.transition(AccountStatus::Destroyed); + assert_eq!(status, AccountStatus::Destroyed); + + let mut status = AccountStatus::Changed; + status.transition(AccountStatus::DestroyedAgain); + assert_eq!(status, AccountStatus::DestroyedAgain); + } } From c59916a499fac64acd02782b60389378bacadc34 Mon Sep 17 00:00:00 2001 From: healthyyyoung Date: Wed, 13 Aug 2025 18:35:03 +0800 Subject: [PATCH 67/78] chore(database): remove unused dependencies (#2885) --- Cargo.lock | 4 ---- crates/database/Cargo.toml | 2 -- crates/database/interface/Cargo.toml | 2 -- 3 files changed, 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 820a52e4b8..37b1048622 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3837,12 +3837,10 @@ dependencies = [ "alloy-eips", "alloy-provider", "alloy-transport", - "anyhow", "revm-bytecode", "revm-database-interface", "revm-primitives", "revm-state", - "rstest", "serde", "serde_json", "tokio", @@ -3852,12 +3850,10 @@ dependencies = [ name = "revm-database-interface" version = "7.0.4" dependencies = [ - "anyhow", "auto_impl", "either", "revm-primitives", "revm-state", - "rstest", "serde", "tokio", ] diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index e8d1786ab0..73091d089a 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -37,8 +37,6 @@ alloy-transport = { workspace = true, optional = true } [dev-dependencies] serde_json = { workspace = true, features = ["alloc"] } -anyhow.workspace = true -rstest.workspace = true [features] default = ["std"] diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index 46d52ea292..bd37356942 100644 --- a/crates/database/interface/Cargo.toml +++ b/crates/database/interface/Cargo.toml @@ -33,8 +33,6 @@ serde = { workspace = true, features = ["derive", "rc"], optional = true } tokio = { workspace = true, optional = true } [dev-dependencies] -anyhow.workspace = true -rstest.workspace = true [features] default = ["std"] From 6697f70dd3165e5149a0342b29d6f23f7b082cac Mon Sep 17 00:00:00 2001 From: phrwlk Date: Wed, 13 Aug 2025 16:37:59 +0300 Subject: [PATCH 68/78] chore: use core::fmt and remove unused Debug import (#2887) --- crates/bytecode/src/decode_errors.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/bytecode/src/decode_errors.rs b/crates/bytecode/src/decode_errors.rs index f281e4f355..4f92a6a930 100644 --- a/crates/bytecode/src/decode_errors.rs +++ b/crates/bytecode/src/decode_errors.rs @@ -1,6 +1,5 @@ use crate::eip7702::Eip7702DecodeError; -use core::fmt::Debug; -use std::fmt; +use core::fmt; /// Bytecode decode errors #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] From 38c7e0063705f98c665dfdb48b06c01df2933cb6 Mon Sep 17 00:00:00 2001 From: jakevin Date: Mon, 18 Aug 2025 07:49:51 +0800 Subject: [PATCH 69/78] fix(handler): correct transaction ID decrement logic (#2892) Co-authored-by: megakabi --- crates/op-revm/src/handler.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/op-revm/src/handler.rs b/crates/op-revm/src/handler.rs index f00414ec50..f70421fc72 100644 --- a/crates/op-revm/src/handler.rs +++ b/crates/op-revm/src/handler.rs @@ -436,7 +436,7 @@ where let old_balance = acc.info.balance; // decrement transaction id as it was incremented when we discarded the tx. - acc.transaction_id -= acc.transaction_id; + acc.transaction_id -= 1; acc.info.nonce = acc.info.nonce.saturating_add(1); acc.info.balance = acc .info From 129b5ef2e7569d87c3c3c3f8933eaba4f88e2ca4 Mon Sep 17 00:00:00 2001 From: Fibonacci747 Date: Mon, 18 Aug 2025 01:55:51 +0200 Subject: [PATCH 70/78] fix(interpreter): correct CreateContractStartingWithEF halt mapping (#2890) --- crates/interpreter/src/instruction_result.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index e1c76d7546..c6d8f3cada 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -332,10 +332,12 @@ impl> From for SuccessOrHalt Self::Halt(HaltReason::OverflowPayment.into()), // Check for first call is done separately. InstructionResult::PrecompileError => Self::Halt(HaltReason::PrecompileError.into()), InstructionResult::NonceOverflow => Self::Halt(HaltReason::NonceOverflow.into()), - InstructionResult::CreateContractSizeLimit - | InstructionResult::CreateContractStartingWithEF => { + InstructionResult::CreateContractSizeLimit => { Self::Halt(HaltReason::CreateContractSizeLimit.into()) } + InstructionResult::CreateContractStartingWithEF => { + Self::Halt(HaltReason::CreateContractStartingWithEF.into()) + } InstructionResult::CreateInitCodeSizeLimit => { Self::Halt(HaltReason::CreateInitCodeSizeLimit.into()) } From 58bdb54533265838433ef4062e5f3a43adbf4342 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Tue, 19 Aug 2025 11:33:13 +0200 Subject: [PATCH 71/78] fix: ensure token is loaded (#2893) --- examples/erc20_gas/src/handler.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/erc20_gas/src/handler.rs b/examples/erc20_gas/src/handler.rs index c747319899..dee0a99a6f 100644 --- a/examples/erc20_gas/src/handler.rs +++ b/examples/erc20_gas/src/handler.rs @@ -83,6 +83,7 @@ where .expect("effective balance is always smaller than max balance so it can't overflow"); let account_balance_slot = erc_address_storage(tx.caller()); + context.journal_mut().load_account(TOKEN)?; let account_balance = context .journal_mut() .sload(TOKEN, account_balance_slot) From 6f9a57c203f4c44031733ba93abb0e862e290a1a Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 19 Aug 2025 13:08:32 +0200 Subject: [PATCH 72/78] example(erc20): mark token contract as touched (#2895) --- examples/erc20_gas/src/handler.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/erc20_gas/src/handler.rs b/examples/erc20_gas/src/handler.rs index dee0a99a6f..eeeed76fad 100644 --- a/examples/erc20_gas/src/handler.rs +++ b/examples/erc20_gas/src/handler.rs @@ -83,7 +83,8 @@ where .expect("effective balance is always smaller than max balance so it can't overflow"); let account_balance_slot = erc_address_storage(tx.caller()); - context.journal_mut().load_account(TOKEN)?; + context.journal_mut().load_account(TOKEN)?.data.mark_touch(); + let account_balance = context .journal_mut() .sload(TOKEN, account_balance_slot) @@ -102,7 +103,6 @@ where // Transfer will be done inside `*_inner` functions. if is_balance_check_disabled { // ignore balance check. - // TODO add transfer value to the erc20 slot. } else if max_balance_spending > account_balance { return Err(InvalidTransaction::LackOfFundForMaxFee { fee: Box::new(max_balance_spending), @@ -137,6 +137,7 @@ where let reimbursement = effective_gas_price.saturating_mul((gas.remaining() + gas.refunded() as u64) as u128); + token_operation::( context, TREASURY, From 8073236d357474272d146babfc9fe13b001c8c28 Mon Sep 17 00:00:00 2001 From: Alessandro Mazza <121622391+alessandromazza98@users.noreply.github.com> Date: Tue, 19 Aug 2025 16:55:06 +0200 Subject: [PATCH 73/78] feat: add generic state to ResultAndState (#2897) --- crates/context/interface/src/result.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/context/interface/src/result.rs b/crates/context/interface/src/result.rs index e9dd33769b..340da3a72b 100644 --- a/crates/context/interface/src/result.rs +++ b/crates/context/interface/src/result.rs @@ -30,7 +30,7 @@ pub struct ExecResultAndState { } /// Type alias for backwards compatibility. -pub type ResultAndState = ExecResultAndState>; +pub type ResultAndState = ExecResultAndState, S>; /// Tuple containing multiple execution results and state. pub type ResultVecAndState = ExecResultAndState, S>; From 7482d2100fcde82283cfe69229d2dfa29e50fcee Mon Sep 17 00:00:00 2001 From: sashass1315 Date: Tue, 19 Aug 2025 17:55:20 +0300 Subject: [PATCH 74/78] fix: EIP-7702 target check to return correct error (#2896) --- crates/context/src/tx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/context/src/tx.rs b/crates/context/src/tx.rs index b7752a3aea..d3510e5c6c 100644 --- a/crates/context/src/tx.rs +++ b/crates/context/src/tx.rs @@ -541,7 +541,7 @@ impl TxEnvBuilder { // target is required if !self.kind.is_call() { - return Err(DeriveTxTypeError::MissingTargetForEip4844.into()); + return Err(DeriveTxTypeError::MissingTargetForEip7702.into()); } } TransactionType::Custom => { From ae1655da953356fa6707e529bec09f80dd88abde Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 21 Aug 2025 13:44:13 +0200 Subject: [PATCH 75/78] feat(fusaka): Add PrecompileId (#2904) --- crates/handler/src/precompile_provider.rs | 2 +- crates/op-revm/src/precompiles.rs | 20 +- crates/precompile/src/blake2.rs | 6 +- crates/precompile/src/bls12_381.rs | 4 +- crates/precompile/src/bls12_381/g1_add.rs | 7 +- crates/precompile/src/bls12_381/g1_msm.rs | 7 +- crates/precompile/src/bls12_381/g2_add.rs | 7 +- crates/precompile/src/bls12_381/g2_msm.rs | 7 +- .../precompile/src/bls12_381/map_fp2_to_g2.rs | 12 +- .../precompile/src/bls12_381/map_fp_to_g1.rs | 11 +- crates/precompile/src/bls12_381/pairing.rs | 7 +- crates/precompile/src/bn254.rs | 26 +-- crates/precompile/src/hash.rs | 15 +- crates/precompile/src/id.rs | 181 ++++++++++++++++++ crates/precompile/src/identity.rs | 9 +- crates/precompile/src/kzg_point_evaluation.rs | 5 +- crates/precompile/src/lib.rs | 103 ++++++---- crates/precompile/src/modexp.rs | 16 +- crates/precompile/src/secp256k1.rs | 11 +- crates/precompile/src/secp256r1.rs | 20 +- 20 files changed, 371 insertions(+), 105 deletions(-) create mode 100644 crates/precompile/src/id.rs diff --git a/crates/handler/src/precompile_provider.rs b/crates/handler/src/precompile_provider.rs index 62ca92d473..eb75bf6135 100644 --- a/crates/handler/src/precompile_provider.rs +++ b/crates/handler/src/precompile_provider.rs @@ -121,7 +121,7 @@ impl PrecompileProvider for EthPrecompiles { CallInput::Bytes(bytes) => bytes.0.iter().as_slice(), }; - match (*precompile)(input_bytes, gas_limit) { + match precompile.execute(input_bytes, gas_limit) { Ok(output) => { let underflow = result.gas.record_cost(output.gas_used); assert!(underflow, "Gas underflow is not possible"); diff --git a/crates/op-revm/src/precompiles.rs b/crates/op-revm/src/precompiles.rs index e4e14b9082..579ceb30c8 100644 --- a/crates/op-revm/src/precompiles.rs +++ b/crates/op-revm/src/precompiles.rs @@ -6,7 +6,7 @@ use revm::{ handler::{EthPrecompiles, PrecompileProvider}, interpreter::{InputsImpl, InterpreterResult}, precompile::{ - self, bn254, secp256r1, PrecompileError, PrecompileResult, PrecompileWithAddress, + self, bn254, secp256r1, Precompile, PrecompileError, PrecompileId, PrecompileResult, Precompiles, }, primitives::{hardfork::SpecId, Address, OnceLock}, @@ -144,10 +144,8 @@ 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: PrecompileWithAddress = - PrecompileWithAddress(bn254::pair::ADDRESS, |input, gas_limit| { - run_pair(input, gas_limit) - }); + pub const GRANITE: Precompile = + Precompile::new(PrecompileId::Bn254Pairing, bn254::pair::ADDRESS, run_pair); /// Run the bn254 pair precompile with Optimism input limit. pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { @@ -179,14 +177,14 @@ pub mod bls12_381 { pub const ISTHMUS_PAIRING_MAX_INPUT_SIZE: usize = 235008; /// G1 msm precompile. - pub const ISTHMUS_G1_MSM: PrecompileWithAddress = - PrecompileWithAddress(G1_MSM_ADDRESS, run_g1_msm); + pub const ISTHMUS_G1_MSM: Precompile = + Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, run_g1_msm); /// G2 msm precompile. - pub const ISTHMUS_G2_MSM: PrecompileWithAddress = - PrecompileWithAddress(G2_MSM_ADDRESS, run_g2_msm); + pub const ISTHMUS_G2_MSM: Precompile = + Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, run_g2_msm); /// Pairing precompile. - pub const ISTHMUS_PAIRING: PrecompileWithAddress = - PrecompileWithAddress(PAIRING_ADDRESS, run_pair); + pub const ISTHMUS_PAIRING: Precompile = + Precompile::new(PrecompileId::Bls12Pairing, PAIRING_ADDRESS, run_pair); /// Run the g1 msm precompile with Optimism input limit. pub fn run_g1_msm(input: &[u8], gas_limit: u64) -> PrecompileResult { diff --git a/crates/precompile/src/blake2.rs b/crates/precompile/src/blake2.rs index 82bfca129c..91b12fcd25 100644 --- a/crates/precompile/src/blake2.rs +++ b/crates/precompile/src/blake2.rs @@ -1,12 +1,14 @@ //! Blake2 precompile. More details in [`run`] -use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; const F_ROUND: u64 = 1; const INPUT_LENGTH: usize = 213; /// Blake2 precompile -pub const FUN: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_address(9), run); +pub const FUN: Precompile = Precompile::new(PrecompileId::Blake2F, crate::u64_to_address(9), run); /// reference: /// input format: diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs index 8e04a6c05b..0c6ff83b9e 100644 --- a/crates/precompile/src/bls12_381.rs +++ b/crates/precompile/src/bls12_381.rs @@ -1,6 +1,6 @@ //! BLS12-381 precompiles added in [`EIP-2537`](https://eips.ethereum.org/EIPS/eip-2537) //! For more details check modules for each precompile. -use crate::PrecompileWithAddress; +use crate::Precompile; #[allow(dead_code)] pub(crate) mod arkworks; @@ -41,7 +41,7 @@ pub mod pairing; mod utils; /// Returns the BLS12-381 precompiles with their addresses. -pub fn precompiles() -> impl Iterator { +pub fn precompiles() -> impl Iterator { [ g1_add::PRECOMPILE, g1_msm::PRECOMPILE, diff --git a/crates/precompile/src/bls12_381/g1_add.rs b/crates/precompile/src/bls12_381/g1_add.rs index 606bb686cf..3b2dd2e59d 100644 --- a/crates/precompile/src/bls12_381/g1_add.rs +++ b/crates/precompile/src/bls12_381/g1_add.rs @@ -3,10 +3,13 @@ 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::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile. -pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_ADD_ADDRESS, g1_add); +pub const PRECOMPILE: Precompile = + Precompile::new(PrecompileId::Bls12G1Add, G1_ADD_ADDRESS, g1_add); /// G1 addition call expects `256` bytes as an input that is interpreted as byte /// concatenation of two G1 points (`128` bytes each). diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index 493616594e..c4840cfe1c 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -6,10 +6,13 @@ use crate::bls12_381_const::{ PADDED_G1_LENGTH, SCALAR_LENGTH, }; use crate::bls12_381_utils::msm_required_gas; -use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1MSM precompile. -pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G1_MSM_ADDRESS, g1_msm); +pub const PRECOMPILE: Precompile = + Precompile::new(PrecompileId::Bls12G1Msm, G1_MSM_ADDRESS, g1_msm); /// Implements EIP-2537 G1MSM precompile. /// G1 multi-scalar-multiplication call expects `160*k` bytes as an input that is interpreted diff --git a/crates/precompile/src/bls12_381/g2_add.rs b/crates/precompile/src/bls12_381/g2_add.rs index 2d3d1265c8..d3af54f4c3 100644 --- a/crates/precompile/src/bls12_381/g2_add.rs +++ b/crates/precompile/src/bls12_381/g2_add.rs @@ -3,10 +3,13 @@ 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::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2ADD precompile. -pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_ADD_ADDRESS, g2_add); +pub const PRECOMPILE: Precompile = + Precompile::new(PrecompileId::Bls12G2Add, G2_ADD_ADDRESS, g2_add); /// G2 addition call expects `512` bytes as an input that is interpreted as byte /// concatenation of two G2 points (`256` bytes each). diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index 6d2830ee6a..eaa2c4f4f7 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -5,10 +5,13 @@ use crate::bls12_381_const::{ PADDED_G2_LENGTH, SCALAR_LENGTH, }; use crate::bls12_381_utils::msm_required_gas; -use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2MSM precompile. -pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(G2_MSM_ADDRESS, g2_msm); +pub const PRECOMPILE: Precompile = + Precompile::new(PrecompileId::Bls12G2Msm, G2_MSM_ADDRESS, g2_msm); /// Implements EIP-2537 G2MSM precompile. /// G2 multi-scalar-multiplication call expects `288*k` bytes as an input that is interpreted 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 a0c0a928dd..847f9638d6 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -3,12 +3,16 @@ 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::{crypto, PrecompileWithAddress}; -use crate::{PrecompileError, PrecompileOutput, PrecompileResult}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP2_TO_G2 precompile. -pub const PRECOMPILE: PrecompileWithAddress = - PrecompileWithAddress(MAP_FP2_TO_G2_ADDRESS, map_fp2_to_g2); +pub const PRECOMPILE: Precompile = Precompile::new( + PrecompileId::Bls12MapFp2ToGp2, + MAP_FP2_TO_G2_ADDRESS, + map_fp2_to_g2, +); /// Field-to-curve call expects 128 bytes as an input that is interpreted as /// an element of Fp2. Output of this call is 256 bytes and is an encoded G2 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 b52b9cc2ce..64a8f11393 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -1,11 +1,16 @@ //! 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::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP_TO_G1 precompile. -pub const PRECOMPILE: PrecompileWithAddress = - PrecompileWithAddress(MAP_FP_TO_G1_ADDRESS, map_fp_to_g1); +pub const PRECOMPILE: Precompile = Precompile::new( + PrecompileId::Bls12MapFpToGp1, + MAP_FP_TO_G1_ADDRESS, + map_fp_to_g1, +); /// Field-to-curve call expects 64 bytes as an input that is interpreted as an /// element of Fp. Output of this call is 128 bytes and is an encoded G1 point. diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index 1b20b8d99b..4cf4c3f5b5 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -5,12 +5,15 @@ use crate::bls12_381_const::{ PADDED_G1_LENGTH, PADDED_G2_LENGTH, PAIRING_ADDRESS, PAIRING_INPUT_LENGTH, PAIRING_MULTIPLIER_BASE, PAIRING_OFFSET_BASE, }; -use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; use primitives::B256; use std::vec::Vec; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_PAIRING precompile. -pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(PAIRING_ADDRESS, pairing); +pub const PRECOMPILE: Precompile = + Precompile::new(PrecompileId::Bls12Pairing, PAIRING_ADDRESS, pairing); /// Pairing call expects 384*k (k being a positive integer) bytes as an inputs /// that is interpreted as byte concatenation of k slices. Each slice has the diff --git a/crates/precompile/src/bn254.rs b/crates/precompile/src/bn254.rs index 5663c9b917..b254b29526 100644 --- a/crates/precompile/src/bn254.rs +++ b/crates/precompile/src/bn254.rs @@ -2,7 +2,7 @@ use crate::{ crypto, utilities::{bool_to_bytes32, right_pad}, - Address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, + Address, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; use std::vec::Vec; @@ -29,8 +29,8 @@ pub mod add { pub const ISTANBUL_ADD_GAS_COST: u64 = 150; /// Bn254 add precompile with ISTANBUL gas rules - pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + pub const ISTANBUL: Precompile = + Precompile::new(PrecompileId::Bn254Add, ADDRESS, |input, gas_limit| { run_add(input, ISTANBUL_ADD_GAS_COST, gas_limit) }); @@ -38,8 +38,8 @@ pub mod add { pub const BYZANTIUM_ADD_GAS_COST: u64 = 500; /// Bn254 add precompile with BYZANTIUM gas rules - pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + pub const BYZANTIUM: Precompile = + Precompile::new(PrecompileId::Bn254Add, ADDRESS, |input, gas_limit| { run_add(input, BYZANTIUM_ADD_GAS_COST, gas_limit) }); } @@ -55,8 +55,8 @@ pub mod mul { pub const ISTANBUL_MUL_GAS_COST: u64 = 6_000; /// Bn254 mul precompile with ISTANBUL gas rules - pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + pub const ISTANBUL: Precompile = + Precompile::new(PrecompileId::Bn254Mul, ADDRESS, |input, gas_limit| { run_mul(input, ISTANBUL_MUL_GAS_COST, gas_limit) }); @@ -64,8 +64,8 @@ pub mod mul { pub const BYZANTIUM_MUL_GAS_COST: u64 = 40_000; /// Bn254 mul precompile with BYZANTIUM gas rules - pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + pub const BYZANTIUM: Precompile = + Precompile::new(PrecompileId::Bn254Mul, ADDRESS, |input, gas_limit| { run_mul(input, BYZANTIUM_MUL_GAS_COST, gas_limit) }); } @@ -84,8 +84,8 @@ pub mod pair { pub const ISTANBUL_PAIR_BASE: u64 = 45_000; /// Bn254 pair precompile with ISTANBUL gas rules - pub const ISTANBUL: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + pub const ISTANBUL: Precompile = + Precompile::new(PrecompileId::Bn254Pairing, ADDRESS, |input, gas_limit| { run_pair( input, ISTANBUL_PAIR_PER_POINT, @@ -101,8 +101,8 @@ pub mod pair { pub const BYZANTIUM_PAIR_BASE: u64 = 100_000; /// Bn254 pair precompile with BYZANTIUM gas rules - pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(ADDRESS, |input, gas_limit| { + pub const BYZANTIUM: Precompile = + Precompile::new(PrecompileId::Bn254Pairing, ADDRESS, |input, gas_limit| { run_pair( input, BYZANTIUM_PAIR_PER_POINT, diff --git a/crates/precompile/src/hash.rs b/crates/precompile/src/hash.rs index 2c81db2ef6..3ac8988f36 100644 --- a/crates/precompile/src/hash.rs +++ b/crates/precompile/src/hash.rs @@ -1,15 +1,20 @@ //! Hash precompiles, it contains SHA-256 and RIPEMD-160 hash precompiles //! More details in [`sha256_run`] and [`ripemd160_run`] use super::calc_linear_cost_u32; -use crate::{crypto, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{ + crypto, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, +}; /// SHA-256 precompile -pub const SHA256: PrecompileWithAddress = - PrecompileWithAddress(crate::u64_to_address(2), sha256_run); +pub const SHA256: Precompile = + Precompile::new(PrecompileId::Sha256, crate::u64_to_address(2), sha256_run); /// RIPEMD-160 precompile -pub const RIPEMD160: PrecompileWithAddress = - PrecompileWithAddress(crate::u64_to_address(3), ripemd160_run); +pub const RIPEMD160: Precompile = Precompile::new( + PrecompileId::Ripemd160, + crate::u64_to_address(3), + ripemd160_run, +); /// Computes the SHA-256 hash of the input data /// diff --git a/crates/precompile/src/id.rs b/crates/precompile/src/id.rs new file mode 100644 index 0000000000..49c8259fff --- /dev/null +++ b/crates/precompile/src/id.rs @@ -0,0 +1,181 @@ +use std::borrow::Cow; + +use primitives::{address, Address}; + +use crate::{Precompile, PrecompileSpecId}; + +/// Precompile with address and function. +/// Unique precompile identifier. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum PrecompileId { + /// Elliptic curve digital signature algorithm (ECDSA) public key recovery function. + EcRec, + /// SHA2-256 hash function. + Sha256, + /// RIPEMD-160 hash function. + Ripemd160, + /// Identity precompile. + Identity, + /// Arbitrary-precision exponentiation under modulo. + ModExp, + /// Point addition (ADD) on the elliptic curve 'alt_bn128'. + Bn254Add, + /// Scalar multiplication (MUL) on the elliptic curve 'alt_bn128'. + Bn254Mul, + /// Bilinear function on groups on the elliptic curve 'alt_bn128'. + Bn254Pairing, + /// Compression function F used in the BLAKE2 cryptographic hashing algorithm. + Blake2F, + /// Verify p(z) = y given commitment that corresponds to the polynomial p(x) and a KZG proof. Also verify that the provided commitment matches the provided versioned_hash. + KzgPointEvaluation, + /// Point addition in G1 (curve over base prime field). + Bls12G1Add, + /// Multi-scalar-multiplication (MSM) in G1 (curve over base prime field). + Bls12G1Msm, + /// Point addition in G2 (curve over quadratic extension of the base prime field). + Bls12G2Add, + /// Multi-scalar-multiplication (MSM) in G2 (curve over quadratic extension of the base prime field). + Bls12G2Msm, + /// Pairing operations between a set of pairs of (G1, G2) points. + Bls12Pairing, + /// Base field element mapping into the G1 point. + Bls12MapFpToGp1, + /// Extension field element mapping into the G2 point. + Bls12MapFp2ToGp2, + /// ECDSA signature verification over the secp256r1 elliptic curve (also known as P-256 or prime256v1). + P256Verify, + /// Custom precompile identifier. + Custom(Cow<'static, str>), +} + +impl PrecompileId { + /// Create new custom precompile ID. + pub fn custom(id: I) -> Self + where + I: Into>, + { + 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 { + Self::EcRec => "ECREC", + Self::Sha256 => "SHA256", + Self::Ripemd160 => "RIPEMD160", + Self::Identity => "ID", + Self::ModExp => "MODEXP", + Self::Bn254Add => "BN254_ADD", + Self::Bn254Mul => "BN254_MUL", + Self::Bn254Pairing => "BN254_PAIRING", + Self::Blake2F => "BLAKE2F", + Self::KzgPointEvaluation => "KZG_POINT_EVALUATION", + Self::Bls12G1Add => "BLS12_G1ADD", + Self::Bls12G1Msm => "BLS12_G1MSM", + Self::Bls12G2Add => "BLS12_G2ADD", + Self::Bls12G2Msm => "BLS12_G2MSM", + Self::Bls12Pairing => "BLS12_PAIRING_CHECK", + Self::Bls12MapFpToGp1 => "BLS12_MAP_FP_TO_G1", + Self::Bls12MapFp2ToGp2 => "BLS12_MAP_FP2_TO_G2", + Self::P256Verify => "P256VERIFY", + Self::Custom(a) => a.as_ref(), + } + } + + /// Returns the precompile function for the given spec. + /// + /// If case of [`PrecompileId::Custom`] it will return [`None`]. + /// + /// For case where precompile was still not introduced in the spec, + /// it will return [`Some`] with fork closest to activation. + pub fn precompile(&self, spec: PrecompileSpecId) -> Option { + use PrecompileSpecId::*; + + let precompile = match self { + Self::EcRec => crate::secp256k1::ECRECOVER, + Self::Sha256 => crate::hash::SHA256, + Self::Ripemd160 => crate::hash::RIPEMD160, + Self::Identity => crate::identity::FUN, + Self::ModExp => { + // ModExp changes gas calculation based on spec + if spec < BERLIN { + crate::modexp::BYZANTIUM + } else if spec < OSAKA { + crate::modexp::BERLIN + } else { + crate::modexp::OSAKA + } + } + Self::Bn254Add => { + // BN254 add - gas cost changes in Istanbul + if spec < ISTANBUL { + crate::bn254::add::BYZANTIUM + } else { + crate::bn254::add::ISTANBUL + } + } + Self::Bn254Mul => { + // BN254 mul - gas cost changes in Istanbul + if spec < ISTANBUL { + crate::bn254::mul::BYZANTIUM + } else { + crate::bn254::mul::ISTANBUL + } + } + Self::Bn254Pairing => { + // BN254 pairing - gas cost changes in Istanbul + if spec < ISTANBUL { + crate::bn254::pair::BYZANTIUM + } else { + crate::bn254::pair::ISTANBUL + } + } + Self::Blake2F => crate::blake2::FUN, + Self::KzgPointEvaluation => crate::kzg_point_evaluation::POINT_EVALUATION, + Self::Bls12G1Add => crate::bls12_381::g1_add::PRECOMPILE, + Self::Bls12G1Msm => crate::bls12_381::g1_msm::PRECOMPILE, + Self::Bls12G2Add => crate::bls12_381::g2_add::PRECOMPILE, + Self::Bls12G2Msm => crate::bls12_381::g2_msm::PRECOMPILE, + Self::Bls12Pairing => crate::bls12_381::pairing::PRECOMPILE, + Self::Bls12MapFpToGp1 => crate::bls12_381::map_fp_to_g1::PRECOMPILE, + Self::Bls12MapFp2ToGp2 => crate::bls12_381::map_fp2_to_g2::PRECOMPILE, + Self::P256Verify => { + // P256 verify - gas cost changes in Osaka + if spec < OSAKA { + crate::secp256r1::P256VERIFY + } else { + crate::secp256r1::P256VERIFY_OSAKA + } + } + Self::Custom(_) => return None, + }; + + Some(precompile) + } +} diff --git a/crates/precompile/src/identity.rs b/crates/precompile/src/identity.rs index 9377bf440c..69129b138a 100644 --- a/crates/precompile/src/identity.rs +++ b/crates/precompile/src/identity.rs @@ -1,11 +1,14 @@ //! Identity precompile returns use super::calc_linear_cost_u32; -use crate::{PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress}; +use crate::{Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult}; use primitives::Bytes; /// Address of the identity precompile. -pub const FUN: PrecompileWithAddress = - PrecompileWithAddress(crate::u64_to_address(4), identity_run); +pub const FUN: Precompile = Precompile::new( + PrecompileId::Identity, + crate::u64_to_address(4), + identity_run, +); /// The base cost of the operation pub const IDENTITY_BASE: u64 = 15; diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index bc78dd932d..9bec2c322c 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -1,7 +1,7 @@ //! KZG point evaluation precompile added in [`EIP-4844`](https://eips.ethereum.org/EIPS/eip-4844) //! For more details check [`run`] function. use crate::{ - crypto, Address, PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, + crypto, Address, Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; pub mod arkworks; @@ -11,7 +11,8 @@ pub mod blst; use primitives::hex_literal::hex; /// KZG point evaluation precompile, containing address and function to run. -pub const POINT_EVALUATION: PrecompileWithAddress = PrecompileWithAddress(ADDRESS, run); +pub const POINT_EVALUATION: Precompile = + Precompile::new(PrecompileId::KzgPointEvaluation, ADDRESS, run); /// Address of the KZG point evaluation precompile. pub const ADDRESS: Address = crate::u64_to_address(0x0A); diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 60eafe27e9..92c420054f 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -14,6 +14,7 @@ pub mod bls12_381_const; pub mod bls12_381_utils; pub mod bn254; pub mod hash; +mod id; pub mod identity; pub mod interface; pub mod kzg_point_evaluation; @@ -22,6 +23,7 @@ pub mod secp256k1; pub mod secp256r1; pub mod utilities; +pub use id::PrecompileId; pub use interface::*; // silence arkworks lint as bn impl will be used as default if both are enabled. @@ -69,11 +71,11 @@ pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { #[derive(Clone, Debug)] pub struct Precompiles { /// Precompiles - inner: HashMap, - /// Addresses of precompile + inner: HashMap, + /// Addresses of precompiles. addresses: HashSet
, /// Optimized addresses filter. - optimized_access: Vec>, + optimized_access: Vec>, /// `true` if all precompiles are short addresses. all_short_addresses: bool, } @@ -119,7 +121,7 @@ impl Precompiles { } /// Returns inner HashMap of precompiles. - pub fn inner(&self) -> &HashMap { + pub fn inner(&self) -> &HashMap { &self.inner } @@ -232,7 +234,7 @@ impl Precompiles { /// Returns the precompile for the given address. #[inline] - pub fn get(&self, address: &Address) -> Option<&PrecompileFn> { + pub fn get(&self, address: &Address) -> Option<&Precompile> { if let Some(short_address) = short_address(address) { return self.optimized_access[short_address].as_ref(); } @@ -241,7 +243,7 @@ impl Precompiles { /// Returns the precompile for the given address. #[inline] - pub fn get_mut(&mut self, address: &Address) -> Option<&mut PrecompileFn> { + pub fn get_mut(&mut self, address: &Address) -> Option<&mut Precompile> { self.inner.get_mut(address) } @@ -264,18 +266,19 @@ impl Precompiles { /// /// Other precompiles with overwrite existing precompiles. #[inline] - pub fn extend(&mut self, other: impl IntoIterator) { - let items: Vec = other.into_iter().collect::>(); + 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.0) { - self.optimized_access[short_address] = Some(item.1); + if let Some(short_address) = short_address(item.address()) { + self.optimized_access[short_address] = Some(item.clone()); } else { self.all_short_addresses = false; } } self.addresses.extend(items.iter().map(|p| *p.address())); - self.inner.extend(items.into_iter().map(|p| (p.0, p.1))); + self.inner + .extend(items.into_iter().map(|p| (*p.address(), p.clone()))); } /// Returns complement of `other` in `self`. @@ -287,11 +290,11 @@ impl Precompiles { let inner = inner .iter() .filter(|(a, _)| !other.inner.contains_key(*a)) - .map(|(a, p)| (*a, *p)) + .map(|(a, p)| (*a, p.clone())) .collect::>(); let mut precompiles = Self::default(); - precompiles.extend(inner.into_iter().map(|p| PrecompileWithAddress(p.0, p.1))); + precompiles.extend(inner.into_iter().map(|p| p.1)); precompiles } @@ -304,42 +307,66 @@ impl Precompiles { let inner = inner .iter() .filter(|(a, _)| other.inner.contains_key(*a)) - .map(|(a, p)| (*a, *p)) + .map(|(a, p)| (*a, p.clone())) .collect::>(); let mut precompiles = Self::default(); - precompiles.extend(inner.into_iter().map(|p| PrecompileWithAddress(p.0, p.1))); + precompiles.extend(inner.into_iter().map(|p| p.1)); precompiles } } -/// Precompile with address and function. +/// Precompile. #[derive(Clone, Debug)] -pub struct PrecompileWithAddress(pub Address, pub PrecompileFn); +pub struct Precompile { + /// Unique identifier. + id: PrecompileId, + /// Precompile address. + address: Address, + /// Precompile implementation. + fn_: PrecompileFn, +} -impl From<(Address, PrecompileFn)> for PrecompileWithAddress { - fn from(value: (Address, PrecompileFn)) -> Self { - PrecompileWithAddress(value.0, value.1) +impl From<(PrecompileId, Address, PrecompileFn)> for Precompile { + fn from((id, address, fn_): (PrecompileId, Address, PrecompileFn)) -> Self { + Precompile { id, address, fn_ } } } -impl From for (Address, PrecompileFn) { - fn from(value: PrecompileWithAddress) -> Self { - (value.0, value.1) +impl From for (PrecompileId, Address, PrecompileFn) { + fn from(value: Precompile) -> Self { + (value.id, value.address, value.fn_) } } -impl PrecompileWithAddress { - /// Returns reference of address. +impl Precompile { + /// Create new precompile. + pub const fn new(id: PrecompileId, address: Address, fn_: PrecompileFn) -> Self { + Self { id, address, fn_ } + } + + /// Returns reference to precompile identifier. + #[inline] + pub fn id(&self) -> &PrecompileId { + &self.id + } + + /// Returns reference to address. #[inline] pub fn address(&self) -> &Address { - &self.0 + &self.address } - /// Returns reference of precompile. + /// Returns reference to precompile implementation. #[inline] pub fn precompile(&self) -> &PrecompileFn { - &self.1 + &self.fn_ + } + + /// Executes the precompile. + #[inline] + pub fn execute(&self, input: &[u8], gas_limit: u64) -> PrecompileResult { + (self.fn_)(input, gas_limit) } } @@ -430,18 +457,30 @@ mod test { assert!(precompiles.optimized_access[9].is_some()); assert!(precompiles.optimized_access[10].is_none()); - precompiles.extend([PrecompileWithAddress(u64_to_address(100), temp_precompile)]); - precompiles.extend([PrecompileWithAddress(u64_to_address(101), temp_precompile)]); + precompiles.extend([Precompile::new( + PrecompileId::Custom("test".into()), + u64_to_address(100), + temp_precompile, + )]); + precompiles.extend([Precompile::new( + PrecompileId::Custom("test".into()), + u64_to_address(101), + temp_precompile, + )]); assert_eq!( - precompiles.optimized_access[100].unwrap()(&[], u64::MAX), + precompiles.optimized_access[100] + .as_ref() + .unwrap() + .execute(&[], u64::MAX), PrecompileResult::Err(PrecompileError::OutOfGas) ); assert_eq!( precompiles .get(&Address::left_padding_from(&[101])) - .unwrap()(&[], u64::MAX), + .unwrap() + .execute(&[], u64::MAX), PrecompileResult::Err(PrecompileError::OutOfGas) ); } diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index 9a7c170381..3107837228 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -3,22 +3,26 @@ use crate::{ crypto, utilities::{left_pad, left_pad_vec, right_pad_vec, right_pad_with_offset}, - PrecompileError, PrecompileOutput, PrecompileResult, PrecompileWithAddress, + Precompile, PrecompileError, PrecompileId, PrecompileOutput, PrecompileResult, }; use core::cmp::{max, min}; use primitives::{eip7823, Bytes, U256}; use std::vec::Vec; /// `modexp` precompile with BYZANTIUM gas rules. -pub const BYZANTIUM: PrecompileWithAddress = - PrecompileWithAddress(crate::u64_to_address(5), byzantium_run); +pub const BYZANTIUM: Precompile = Precompile::new( + PrecompileId::ModExp, + crate::u64_to_address(5), + byzantium_run, +); /// `modexp` precompile with BERLIN gas rules. -pub const BERLIN: PrecompileWithAddress = - PrecompileWithAddress(crate::u64_to_address(5), berlin_run); +pub const BERLIN: Precompile = + Precompile::new(PrecompileId::ModExp, crate::u64_to_address(5), berlin_run); /// `modexp` precompile with OSAKA gas rules. -pub const OSAKA: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_address(5), osaka_run); +pub const OSAKA: Precompile = + Precompile::new(PrecompileId::ModExp, crate::u64_to_address(5), osaka_run); #[cfg(feature = "gmp")] /// GMP-based modular exponentiation implementation diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 5d412f649a..314ae2bd19 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -20,14 +20,17 @@ pub mod k256; pub mod parity_libsecp256k1; use crate::{ - crypto, utilities::right_pad, PrecompileError, PrecompileOutput, PrecompileResult, - PrecompileWithAddress, + crypto, utilities::right_pad, Precompile, PrecompileError, PrecompileId, PrecompileOutput, + PrecompileResult, }; use primitives::{alloy_primitives::B512, Bytes, B256}; /// `ecrecover` precompile, containing address and function to run. -pub const ECRECOVER: PrecompileWithAddress = - PrecompileWithAddress(crate::u64_to_address(1), ec_recover_run); +pub const ECRECOVER: Precompile = Precompile::new( + PrecompileId::EcRec, + crate::u64_to_address(1), + ec_recover_run, +); /// `ecrecover` precompile function. Read more about input and output format in [this module docs](self). pub fn ec_recover_run(input: &[u8], gas_limit: u64) -> PrecompileResult { diff --git a/crates/precompile/src/secp256r1.rs b/crates/precompile/src/secp256r1.rs index b421a623e6..262a2d0889 100644 --- a/crates/precompile/src/secp256r1.rs +++ b/crates/precompile/src/secp256r1.rs @@ -7,8 +7,8 @@ //! P256 elliptic curve. The [`P256VERIFY`] const represents the implementation of this precompile, //! with the address that it is currently deployed at. use crate::{ - crypto, u64_to_address, PrecompileError, PrecompileOutput, PrecompileResult, - PrecompileWithAddress, + crypto, u64_to_address, Precompile, PrecompileError, PrecompileId, PrecompileOutput, + PrecompileResult, }; use p256::{ ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey}, @@ -26,17 +26,23 @@ pub const P256VERIFY_BASE_GAS_FEE: u64 = 3450; pub const P256VERIFY_BASE_GAS_FEE_OSAKA: u64 = 6900; /// Returns the secp256r1 precompile with its address. -pub fn precompiles() -> impl Iterator { +pub fn precompiles() -> impl Iterator { [P256VERIFY].into_iter() } /// [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md#specification) secp256r1 precompile. -pub const P256VERIFY: PrecompileWithAddress = - PrecompileWithAddress(u64_to_address(P256VERIFY_ADDRESS), p256_verify); +pub const P256VERIFY: Precompile = Precompile::new( + PrecompileId::P256Verify, + u64_to_address(P256VERIFY_ADDRESS), + p256_verify, +); /// [RIP-7212](https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md#specification) secp256r1 precompile. -pub const P256VERIFY_OSAKA: PrecompileWithAddress = - PrecompileWithAddress(u64_to_address(P256VERIFY_ADDRESS), p256_verify_osaka); +pub const P256VERIFY_OSAKA: Precompile = Precompile::new( + PrecompileId::P256Verify, + u64_to_address(P256VERIFY_ADDRESS), + p256_verify_osaka, +); /// secp256r1 precompile logic. It takes the input bytes sent to the precompile /// and the gas limit. The output represents the result of verifying the From d58eb2ec50274c937108fb6f13ba87266db9a881 Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 23 Aug 2025 22:54:15 +0200 Subject: [PATCH 76/78] chore: skip drain if checkpoing is inconsistent (#2911) --- crates/context/src/journal/inner.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/crates/context/src/journal/inner.rs b/crates/context/src/journal/inner.rs index a7cefb75a3..ad33850471 100644 --- a/crates/context/src/journal/inner.rs +++ b/crates/context/src/journal/inner.rs @@ -466,12 +466,14 @@ impl JournalInner { self.logs.truncate(checkpoint.log_i); // iterate over last N journals sets and revert our global state - self.journal - .drain(checkpoint.journal_i..) - .rev() - .for_each(|entry| { - entry.revert(state, Some(transient_storage), is_spurious_dragon_enabled); - }); + if checkpoint.journal_i < self.journal.len() { + self.journal + .drain(checkpoint.journal_i..) + .rev() + .for_each(|entry| { + entry.revert(state, Some(transient_storage), is_spurious_dragon_enabled); + }); + } } /// Performs selfdestruct action. From d0c8b255cb1d0145b96688ee3b1278123f8ac047 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 24 Aug 2025 17:34:43 +0200 Subject: [PATCH 77/78] chore: release (#2899) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 28 +++++++++++++------------- Cargo.toml | 26 ++++++++++++------------ bins/revme/CHANGELOG.md | 6 ++++++ bins/revme/Cargo.toml | 2 +- crates/bytecode/CHANGELOG.md | 6 ++++++ crates/bytecode/Cargo.toml | 2 +- crates/context/CHANGELOG.md | 10 +++++++++ crates/context/Cargo.toml | 2 +- crates/context/interface/CHANGELOG.md | 6 ++++++ crates/context/interface/Cargo.toml | 2 +- crates/database/CHANGELOG.md | 7 +++++++ 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 | 10 +++++++++ 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, 134 insertions(+), 41 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37b1048622..f661288c42 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3034,7 +3034,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "9.0.1" +version = "9.1.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3772,7 +3772,7 @@ dependencies = [ [[package]] name = "revm" -version = "28.0.1" +version = "28.0.2" dependencies = [ "revm-bytecode", "revm-context", @@ -3791,7 +3791,7 @@ dependencies = [ [[package]] name = "revm-bytecode" -version = "6.2.1" +version = "6.2.2" dependencies = [ "bitvec", "paste", @@ -3802,7 +3802,7 @@ dependencies = [ [[package]] name = "revm-context" -version = "9.0.1" +version = "9.0.2" dependencies = [ "bitvec", "cfg-if", @@ -3818,7 +3818,7 @@ dependencies = [ [[package]] name = "revm-context-interface" -version = "10.0.1" +version = "10.1.0" dependencies = [ "alloy-eip2930", "alloy-eip7702", @@ -3832,7 +3832,7 @@ dependencies = [ [[package]] name = "revm-database" -version = "7.0.4" +version = "7.0.5" dependencies = [ "alloy-eips", "alloy-provider", @@ -3848,7 +3848,7 @@ dependencies = [ [[package]] name = "revm-database-interface" -version = "7.0.4" +version = "7.0.5" dependencies = [ "auto_impl", "either", @@ -3874,7 +3874,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "9.0.1" +version = "9.1.0" dependencies = [ "alloy-eip7702", "alloy-provider", @@ -3896,7 +3896,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "9.1.0" +version = "9.1.1" dependencies = [ "auto_impl", "either", @@ -3913,7 +3913,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "25.0.1" +version = "25.0.2" dependencies = [ "bincode 2.0.1", "revm-bytecode", @@ -3924,7 +3924,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "26.0.1" +version = "27.0.0" dependencies = [ "ark-bls12-381", "ark-bn254", @@ -3964,7 +3964,7 @@ dependencies = [ [[package]] name = "revm-state" -version = "7.0.4" +version = "7.0.5" dependencies = [ "bitflags", "revm-bytecode", @@ -3974,7 +3974,7 @@ dependencies = [ [[package]] name = "revm-statetest-types" -version = "9.0.1" +version = "9.0.2" dependencies = [ "k256", "revm", @@ -3985,7 +3985,7 @@ dependencies = [ [[package]] name = "revme" -version = "7.2.1" +version = "7.2.2" dependencies = [ "alloy-rlp", "alloy-sol-types", diff --git a/Cargo.toml b/Cargo.toml index 4a0e5b44fe..9a2007a2af 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "28.0.1", default-features = false } +revm = { path = "crates/revm", version = "28.0.2", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.2.1", default-features = false } -bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.1", default-features = false } -database = { path = "crates/database", package = "revm-database", version = "7.0.4", default-features = false } -database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.4", default-features = false } -state = { path = "crates/state", package = "revm-state", version = "7.0.4", default-features = false } -interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.1", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "9.1.0", default-features = false } -precompile = { path = "crates/precompile", package = "revm-precompile", version = "26.0.1", default-features = false } -statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "9.0.1", default-features = false } -context = { path = "crates/context", package = "revm-context", version = "9.0.1", default-features = false } -context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.0.1", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "9.0.1", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "9.0.1", default-features = false } +bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.2", default-features = false } +database = { path = "crates/database", package = "revm-database", version = "7.0.5", default-features = false } +database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.5", default-features = false } +state = { path = "crates/state", package = "revm-state", version = "7.0.5", default-features = false } +interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.2", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "9.1.1", default-features = false } +precompile = { path = "crates/precompile", package = "revm-precompile", version = "27.0.0", default-features = false } +statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "9.0.2", default-features = false } +context = { path = "crates/context", package = "revm-context", version = "9.0.2", default-features = false } +context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.1.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "9.1.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "9.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 21cfe2711e..907105d190 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] +## [7.2.2](https://github.com/bluealloy/revm/compare/revme-v7.2.1...revme-v7.2.2) - 2025-08-23 + +### Other + +- updated the following local packages: revm-bytecode, revm-database-interface, revm-context-interface, revm-context, revm-database, revm-state, revm-inspector, revm, revm-statetest-types + ## [7.2.1](https://github.com/bluealloy/revm/compare/revme-v7.2.0...revme-v7.2.1) - 2025-08-12 ### Other diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 5fd519ff82..1e4b918970 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 = "7.2.1" +version = "7.2.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/bytecode/CHANGELOG.md b/crates/bytecode/CHANGELOG.md index 1a20ca601d..5aabf75f0e 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] +## [6.2.2](https://github.com/bluealloy/revm/compare/revm-bytecode-v6.2.1...revm-bytecode-v6.2.2) - 2025-08-23 + +### Other + +- use core::fmt and remove unused Debug import ([#2887](https://github.com/bluealloy/revm/pull/2887)) + ## [6.2.1](https://github.com/bluealloy/revm/compare/revm-bytecode-v6.2.0...revm-bytecode-v6.2.1) - 2025-08-12 ### Other diff --git a/crates/bytecode/Cargo.toml b/crates/bytecode/Cargo.toml index 39af599e6f..b35526c1c0 100644 --- a/crates/bytecode/Cargo.toml +++ b/crates/bytecode/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-bytecode" description = "EVM Bytecodes" -version = "6.2.1" +version = "6.2.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/context/CHANGELOG.md b/crates/context/CHANGELOG.md index fd85a9bd89..377e80b0c9 100644 --- a/crates/context/CHANGELOG.md +++ b/crates/context/CHANGELOG.md @@ -7,6 +7,16 @@ 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-context-v9.0.1...revm-context-v9.0.2) - 2025-08-23 + +### Fixed + +- EIP-7702 target check to return correct error ([#2896](https://github.com/bluealloy/revm/pull/2896)) + +### Other + +- skip drain if checkpoing is inconsistent ([#2911](https://github.com/bluealloy/revm/pull/2911)) + ## [9.0.1](https://github.com/bluealloy/revm/compare/revm-context-v9.0.0...revm-context-v9.0.1) - 2025-08-12 ### Other diff --git a/crates/context/Cargo.toml b/crates/context/Cargo.toml index 443a6aa532..4a1ae51caf 100644 --- a/crates/context/Cargo.toml +++ b/crates/context/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-context" description = "Revm context crates" -version = "9.0.1" +version = "9.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 e384ec6c67..0c2ec479a3 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] +## [10.1.0](https://github.com/bluealloy/revm/compare/revm-context-interface-v10.0.1...revm-context-interface-v10.1.0) - 2025-08-23 + +### Added + +- add generic state to ResultAndState ([#2897](https://github.com/bluealloy/revm/pull/2897)) + ## [10.0.1](https://github.com/bluealloy/revm/compare/revm-context-interface-v10.0.0...revm-context-interface-v10.0.1) - 2025-08-12 ### Other diff --git a/crates/context/interface/Cargo.toml b/crates/context/interface/Cargo.toml index f704454a56..82a8e8a5f8 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 = "10.0.1" +version = "10.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/database/CHANGELOG.md b/crates/database/CHANGELOG.md index 3ddba63d80..a5dcf17337 100644 --- a/crates/database/CHANGELOG.md +++ b/crates/database/CHANGELOG.md @@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [7.0.5](https://github.com/bluealloy/revm/compare/revm-database-v7.0.4...revm-database-v7.0.5) - 2025-08-23 + +### Other + +- *(database)* remove unused dependencies ([#2885](https://github.com/bluealloy/revm/pull/2885)) +- add AccountStatus unit test ([#2869](https://github.com/bluealloy/revm/pull/2869)) + ## [7.0.4](https://github.com/bluealloy/revm/compare/revm-database-v7.0.3...revm-database-v7.0.4) - 2025-08-12 ### Other diff --git a/crates/database/Cargo.toml b/crates/database/Cargo.toml index 73091d089a..099e5c6caf 100644 --- a/crates/database/Cargo.toml +++ b/crates/database/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-database" description = "Revm Database implementations" -version = "7.0.4" +version = "7.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 ebf4f3b5af..e308ef5bf3 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] +## [7.0.5](https://github.com/bluealloy/revm/compare/revm-database-interface-v7.0.4...revm-database-interface-v7.0.5) - 2025-08-23 + +### Other + +- *(database)* remove unused dependencies ([#2885](https://github.com/bluealloy/revm/pull/2885)) + ## [7.0.4](https://github.com/bluealloy/revm/compare/revm-database-interface-v7.0.3...revm-database-interface-v7.0.4) - 2025-08-12 ### Other diff --git a/crates/database/interface/Cargo.toml b/crates/database/interface/Cargo.toml index bd37356942..b6e19704e0 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 = "7.0.4" +version = "7.0.5" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 2300934602..477b763a27 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] +## [9.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v9.0.1...revm-handler-v9.1.0) - 2025-08-23 + +### Added + +- *(fusaka)* Add PrecompileId ([#2904](https://github.com/bluealloy/revm/pull/2904)) + ## [9.0.1](https://github.com/bluealloy/revm/compare/revm-handler-v9.0.0...revm-handler-v9.0.1) - 2025-08-12 ### Other diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index e82763dace..9e618085fc 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "9.0.1" +version = "9.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 668f4180b3..929db9d4e4 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] +## [9.1.1](https://github.com/bluealloy/revm/compare/revm-inspector-v9.1.0...revm-inspector-v9.1.1) - 2025-08-23 + +### Other + +- updated the following local packages: revm-database-interface, revm-context, revm-database, revm-interpreter, revm-handler, revm-state + ## [9.1.0](https://github.com/bluealloy/revm/compare/revm-inspector-v9.0.0...revm-inspector-v9.1.0) - 2025-08-12 ### Added diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index feb4c5a6af..150e7bf9ba 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "9.1.0" +version = "9.1.1" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index 7b16ab2694..0d6561a73a 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] +## [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 diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index fdc779ba44..4e3ccca73d 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 = "25.0.1" +version = "25.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 0639417411..48cf6060ea 100644 --- a/crates/op-revm/CHANGELOG.md +++ b/crates/op-revm/CHANGELOG.md @@ -7,6 +7,16 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [9.1.0](https://github.com/bluealloy/revm/compare/op-revm-v9.0.1...op-revm-v9.1.0) - 2025-08-23 + +### Added + +- *(fusaka)* Add PrecompileId ([#2904](https://github.com/bluealloy/revm/pull/2904)) + +### Fixed + +- *(handler)* correct transaction ID decrement logic ([#2892](https://github.com/bluealloy/revm/pull/2892)) + ## [9.0.1](https://github.com/bluealloy/revm/compare/op-revm-v9.0.0...op-revm-v9.0.1) - 2025-08-12 ### Other diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index 39557efcd1..c92eb4b466 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 = "9.0.1" +version = "9.1.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index ccbe8633c0..e58f0a4933 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] +## [27.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v26.0.1...revm-precompile-v27.0.0) - 2025-08-23 + +### Added + +- *(fusaka)* Add PrecompileId ([#2904](https://github.com/bluealloy/revm/pull/2904)) + ## [26.0.1](https://github.com/bluealloy/revm/compare/revm-precompile-v26.0.0...revm-precompile-v26.0.1) - 2025-08-12 ### Fixed diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 532e86723b..e5a9ff5a86 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 = "26.0.1" +version = "27.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 52c94eb72d..87cc93ab4e 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] +## [28.0.2](https://github.com/bluealloy/revm/compare/revm-v28.0.1...revm-v28.0.2) - 2025-08-23 + +### Other + +- updated the following local packages: revm-bytecode, revm-database-interface, revm-context-interface, revm-context, revm-database, revm-interpreter, revm-precompile, revm-handler, revm-state, revm-inspector + ## [28.0.1](https://github.com/bluealloy/revm/compare/revm-v28.0.0...revm-v28.0.1) - 2025-08-12 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index b44630da84..3a5f2c72e6 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 = "28.0.1" +version = "28.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/state/CHANGELOG.md b/crates/state/CHANGELOG.md index dcb663e857..94d8d0adff 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] +## [7.0.5](https://github.com/bluealloy/revm/compare/revm-state-v7.0.4...revm-state-v7.0.5) - 2025-08-23 + +### Other + +- updated the following local packages: revm-bytecode + ## [7.0.4](https://github.com/bluealloy/revm/compare/revm-state-v7.0.3...revm-state-v7.0.4) - 2025-08-12 ### Other diff --git a/crates/state/Cargo.toml b/crates/state/Cargo.toml index 070248bf77..a9f930af7d 100644 --- a/crates/state/Cargo.toml +++ b/crates/state/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-state" description = "Revm state types" -version = "7.0.4" +version = "7.0.5" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/statetest-types/CHANGELOG.md b/crates/statetest-types/CHANGELOG.md index aedf5b0076..c89d542d84 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] +## [9.0.2](https://github.com/bluealloy/revm/compare/revm-statetest-types-v9.0.1...revm-statetest-types-v9.0.2) - 2025-08-23 + +### Other + +- updated the following local packages: revm + ## [9.0.1](https://github.com/bluealloy/revm/compare/revm-statetest-types-v9.0.0...revm-statetest-types-v9.0.1) - 2025-08-12 ### Other diff --git a/crates/statetest-types/Cargo.toml b/crates/statetest-types/Cargo.toml index 5dce5eed34..5b8950c772 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 = "9.0.1" +version = "9.0.2" authors.workspace = true edition.workspace = true keywords.workspace = true From 191fa780c76e452b2eae482f9a08873056590fbe Mon Sep 17 00:00:00 2001 From: rakita Date: Sun, 24 Aug 2025 17:59:20 +0200 Subject: [PATCH 78/78] bump: tag v86 revm v29.0.0 (#2912) --- CHANGELOG.md | 20 ++++++++++++++++++++ Cargo.lock | 8 ++++---- Cargo.toml | 8 ++++---- MIGRATION_GUIDE.md | 6 ++++++ crates/handler/CHANGELOG.md | 2 +- crates/handler/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 +- 12 files changed, 42 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd21bb4f94..83f3a8d3b3 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. +# v86 +date: 24.08.2025 + +Maintainance release. PrecompileId added + +* `revm-bytecode`: 6.2.1 -> 6.2.2 (✓ API compatible changes) +* `revm-database-interface`: 7.0.4 -> 7.0.5 (✓ API compatible changes) +* `revm-context-interface`: 10.0.1 -> 10.1.0 (✓ API compatible changes) +* `revm-context`: 9.0.1 -> 9.0.2 (✓ API compatible changes) +* `revm-database`: 7.0.4 -> 7.0.5 (✓ API compatible changes) +* `revm-interpreter`: 25.0.1 -> 25.0.2 (✓ API compatible changes) +* `revm-precompile`: 26.0.1 -> 27.0.0 (⚠ API breaking changes) +* `revm-handler`: 9.0.1 -> 10.0.0 (✓ API compatible changes) +* `op-revm`: 9.0.1 -> 10.0.0 (✓ API compatible changes) +* `revm-state`: 7.0.4 -> 7.0.5 +* `revm-inspector`: 9.1.0 -> 10.0.0 +* `revm`: 28.0.1 -> 29.0.0 +* `revm-statetest-types`: 9.0.1 -> 9.0.2 +* `revme`: 7.2.1 -> 7.2.2 + # v85 date: 12.08.2025 diff --git a/Cargo.lock b/Cargo.lock index f661288c42..dfba341dae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3034,7 +3034,7 @@ checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e" [[package]] name = "op-revm" -version = "9.1.0" +version = "10.0.0" dependencies = [ "alloy-primitives", "alloy-sol-types", @@ -3772,7 +3772,7 @@ dependencies = [ [[package]] name = "revm" -version = "28.0.2" +version = "29.0.0" dependencies = [ "revm-bytecode", "revm-context", @@ -3874,7 +3874,7 @@ dependencies = [ [[package]] name = "revm-handler" -version = "9.1.0" +version = "10.0.0" dependencies = [ "alloy-eip7702", "alloy-provider", @@ -3896,7 +3896,7 @@ dependencies = [ [[package]] name = "revm-inspector" -version = "9.1.1" +version = "10.0.0" dependencies = [ "auto_impl", "either", diff --git a/Cargo.toml b/Cargo.toml index 9a2007a2af..dd4f8aaf67 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -41,20 +41,20 @@ default-members = ["crates/revm"] [workspace.dependencies] # revm -revm = { path = "crates/revm", version = "28.0.2", default-features = false } +revm = { path = "crates/revm", version = "29.0.0", default-features = false } primitives = { path = "crates/primitives", package = "revm-primitives", version = "20.2.1", default-features = false } bytecode = { path = "crates/bytecode", package = "revm-bytecode", version = "6.2.2", default-features = false } database = { path = "crates/database", package = "revm-database", version = "7.0.5", default-features = false } database-interface = { path = "crates/database/interface", package = "revm-database-interface", version = "7.0.5", default-features = false } state = { path = "crates/state", package = "revm-state", version = "7.0.5", default-features = false } interpreter = { path = "crates/interpreter", package = "revm-interpreter", version = "25.0.2", default-features = false } -inspector = { path = "crates/inspector", package = "revm-inspector", version = "9.1.1", default-features = false } +inspector = { path = "crates/inspector", package = "revm-inspector", version = "10.0.0", default-features = false } precompile = { path = "crates/precompile", package = "revm-precompile", version = "27.0.0", default-features = false } statetest-types = { path = "crates/statetest-types", package = "revm-statetest-types", version = "9.0.2", default-features = false } context = { path = "crates/context", package = "revm-context", version = "9.0.2", default-features = false } context-interface = { path = "crates/context/interface", package = "revm-context-interface", version = "10.1.0", default-features = false } -handler = { path = "crates/handler", package = "revm-handler", version = "9.1.0", default-features = false } -op-revm = { path = "crates/op-revm", package = "op-revm", version = "9.1.0", default-features = false } +handler = { path = "crates/handler", package = "revm-handler", version = "10.0.0", default-features = false } +op-revm = { path = "crates/op-revm", package = "op-revm", version = "10.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 573a9154f1..9b638a86ba 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -1,3 +1,9 @@ +# v86 tag (revm v29.0.0) + +* `PrecompileWithAddress` is renamed to `Precompile` and it became a struct. + * `Precompile` contains`PrecompileId`, `Address` and function. + * The reason is adding `PrecompileId` as it is needed for fusaka hardfork + # v85 tag (revm v28.0.1) from v84 tag (revm v28.0.0) Forward compatible version. diff --git a/crates/handler/CHANGELOG.md b/crates/handler/CHANGELOG.md index 477b763a27..8cb93f8356 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] -## [9.1.0](https://github.com/bluealloy/revm/compare/revm-handler-v9.0.1...revm-handler-v9.1.0) - 2025-08-23 +## [10.0.0](https://github.com/bluealloy/revm/compare/revm-handler-v9.0.1...revm-handler-v10.0.0) - 2025-08-23 ### Added diff --git a/crates/handler/Cargo.toml b/crates/handler/Cargo.toml index 9e618085fc..6cae72e6f1 100644 --- a/crates/handler/Cargo.toml +++ b/crates/handler/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-handler" description = "Revm handler crates" -version = "9.1.0" +version = "10.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/inspector/CHANGELOG.md b/crates/inspector/CHANGELOG.md index 929db9d4e4..a05acf056d 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] -## [9.1.1](https://github.com/bluealloy/revm/compare/revm-inspector-v9.1.0...revm-inspector-v9.1.1) - 2025-08-23 +## [10.0.0](https://github.com/bluealloy/revm/compare/revm-inspector-v9.1.0...revm-inspector-v10.0.0) - 2025-08-23 ### Other diff --git a/crates/inspector/Cargo.toml b/crates/inspector/Cargo.toml index 150e7bf9ba..519b30dcc9 100644 --- a/crates/inspector/Cargo.toml +++ b/crates/inspector/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "revm-inspector" description = "Revm inspector interface" -version = "9.1.1" +version = "10.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 48cf6060ea..3486bf1404 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] -## [9.1.0](https://github.com/bluealloy/revm/compare/op-revm-v9.0.1...op-revm-v9.1.0) - 2025-08-23 +## [10.0.0](https://github.com/bluealloy/revm/compare/op-revm-v9.0.1...op-revm-v10.0.0) - 2025-08-23 ### Added diff --git a/crates/op-revm/Cargo.toml b/crates/op-revm/Cargo.toml index c92eb4b466..9565a3beca 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 = "9.1.0" +version = "10.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index 87cc93ab4e..cd72a23e7c 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] -## [28.0.2](https://github.com/bluealloy/revm/compare/revm-v28.0.1...revm-v28.0.2) - 2025-08-23 +## [29.0.0](https://github.com/bluealloy/revm/compare/revm-v28.0.1...revm-v29.0.0) - 2025-08-23 ### Other diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 3a5f2c72e6..744585d21a 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 = "28.0.2" +version = "29.0.0" authors.workspace = true edition.workspace = true keywords.workspace = true