From 919aae566de2d67256fb324a240a76aebd67cd03 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 13 May 2024 10:31:56 +0300 Subject: [PATCH 01/88] chore: Remove Host constrain from calc_call_gas (#1409) * chore: Remove Host constrain from calc_call_gas * make it build --- crates/interpreter/src/instructions/contract.rs | 8 ++++---- .../interpreter/src/instructions/contract/call_helpers.rs | 3 +-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index acb896f4a0..c3f701f28a 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -469,7 +469,7 @@ pub fn call(interpreter: &mut Interpreter, host: & interpreter.instruction_result = InstructionResult::FatalExternalError; return; }; - let Some(mut gas_limit) = calc_call_gas::( + let Some(mut gas_limit) = calc_call_gas::( interpreter, is_cold, has_transfer, @@ -520,7 +520,7 @@ pub fn call_code(interpreter: &mut Interpreter, ho return; }; - let Some(mut gas_limit) = calc_call_gas::( + let Some(mut gas_limit) = calc_call_gas::( interpreter, is_cold, value != U256::ZERO, @@ -571,7 +571,7 @@ pub fn delegate_call(interpreter: &mut Interpreter return; }; let Some(gas_limit) = - calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) + calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) else { return; }; @@ -613,7 +613,7 @@ pub fn static_call(interpreter: &mut Interpreter, }; let Some(gas_limit) = - calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) + calc_call_gas::(interpreter, is_cold, false, false, local_gas_limit) else { return; }; diff --git a/crates/interpreter/src/instructions/contract/call_helpers.rs b/crates/interpreter/src/instructions/contract/call_helpers.rs index 8746f2ec48..5570efe3ac 100644 --- a/crates/interpreter/src/instructions/contract/call_helpers.rs +++ b/crates/interpreter/src/instructions/contract/call_helpers.rs @@ -2,7 +2,6 @@ use crate::{ gas, interpreter::Interpreter, primitives::{Bytes, Spec, SpecId::*, U256}, - Host, }; use core::{cmp::min, ops::Range}; @@ -43,7 +42,7 @@ pub fn resize_memory_and_return_range( } #[inline] -pub fn calc_call_gas( +pub fn calc_call_gas( interpreter: &mut Interpreter, is_cold: bool, has_transfer: bool, From 4666bd3432aed18a5c89789fedd27bfdbd26c664 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 13 May 2024 10:32:16 +0300 Subject: [PATCH 02/88] chore: pop_address should use crate scope (#1410) --- crates/interpreter/src/instructions/macros.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index abac40bc27..a4ee4f4b3e 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -138,10 +138,10 @@ macro_rules! resize_memory { #[macro_export] macro_rules! pop_address { ($interp:expr, $x1:ident) => { - pop_address_ret!($interp, $x1, ()) + $crate::pop_address_ret!($interp, $x1, ()) }; ($interp:expr, $x1:ident, $x2:ident) => { - pop_address_ret!($interp, $x1, $x2, ()) + $crate::pop_address_ret!($interp, $x1, $x2, ()) }; } From db7b3cf3e77845d0fea6695919e1cb8b144f5381 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 09:32:39 +0200 Subject: [PATCH 03/88] chore(deps): bump serde from 1.0.200 to 1.0.201 (#1407) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.200 to 1.0.201. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.200...v1.0.201) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c08fc32083..73b2072b08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3396,18 +3396,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.200" +version = "1.0.201" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" dependencies = [ "proc-macro2", "quote", From a2e3d395a3087a6f9372a2ab0f825d8f9a983038 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 09:32:46 +0200 Subject: [PATCH 04/88] chore(deps): bump serde_json from 1.0.115 to 1.0.117 (#1406) Bumps [serde_json](https://github.com/serde-rs/json) from 1.0.115 to 1.0.117. - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/v1.0.115...v1.0.117) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 73b2072b08..f07a30a1f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3416,9 +3416,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.115" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" +checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" dependencies = [ "indexmap", "itoa", From fa99b9076861d53d6190b07a211c6cd81a2fbd69 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 09:32:55 +0200 Subject: [PATCH 05/88] chore(deps): bump paste from 1.0.14 to 1.0.15 (#1405) Bumps [paste](https://github.com/dtolnay/paste) from 1.0.14 to 1.0.15. - [Release notes](https://github.com/dtolnay/paste/releases) - [Commits](https://github.com/dtolnay/paste/compare/1.0.14...1.0.15) --- updated-dependencies: - dependency-name: paste dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f07a30a1f7..8b92f82a0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2427,9 +2427,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" [[package]] name = "pem" From 4ac1e6619d1bf95e0974b010157029b8222a8aad Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 09:33:04 +0200 Subject: [PATCH 06/88] chore(deps): bump anyhow from 1.0.82 to 1.0.83 (#1404) Bumps [anyhow](https://github.com/dtolnay/anyhow) from 1.0.82 to 1.0.83. - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.82...1.0.83) --- updated-dependencies: - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/revm/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8b92f82a0c..00264cd434 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -360,9 +360,9 @@ checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anyhow" -version = "1.0.82" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519" +checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" [[package]] name = "arbitrary" diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 9f9c9db9f0..9c1830e438 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -58,7 +58,7 @@ alloy-sol-types = { version = "0.7.0", default-features = false, features = [ "std", ] } ethers-contract = { version = "2.0.14", default-features = false } -anyhow = "1.0.82" +anyhow = "1.0.83" criterion = "0.5" indicatif = "0.17" reqwest = { version = "0.12" } From 29b22246f7e1bb13361c3d0ac3129c0316c15742 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 May 2024 09:33:12 +0200 Subject: [PATCH 07/88] chore(deps): bump thiserror from 1.0.59 to 1.0.60 (#1403) Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.59 to 1.0.60. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.59...1.0.60) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00264cd434..578b26349e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3722,18 +3722,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" dependencies = [ "proc-macro2", "quote", From 287ae36260646120f0007485afe17c222579ea9e Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 13 May 2024 11:01:19 +0300 Subject: [PATCH 08/88] docs: point to gas! in Gas::record_cost (#1413) --- crates/interpreter/src/gas.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index 192dcc7bc0..ac0af3079d 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -121,7 +121,7 @@ impl Gas { /// /// Returns `false` if the gas limit is exceeded. #[inline] - #[must_use] + #[must_use = "prefer using `gas!` instead to return an out-of-gas error on failure"] pub fn record_cost(&mut self, cost: u64) -> bool { let (remaining, overflow) = self.remaining.overflowing_sub(cost); let success = !overflow; From 38c4d3e756291b8a11f48bdce6f4248582824890 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 13 May 2024 11:03:59 +0300 Subject: [PATCH 09/88] fix(primitives): specify the optimism cfg on spec_to_generic (#1412) --- crates/primitives/src/specification.rs | 73 ++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index fbd8d22abc..52abf9ecba 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -208,10 +208,77 @@ spec!(CANYON, CanyonSpec); #[cfg(feature = "optimism")] spec!(ECOTONE, EcotoneSpec); +#[cfg(not(feature = "optimism"))] +#[macro_export] +macro_rules! spec_to_generic { + ($spec_id:expr, $e:expr) => {{ + match $spec_id { + $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => { + use $crate::FrontierSpec as SPEC; + $e + } + $crate::SpecId::HOMESTEAD | SpecId::DAO_FORK => { + use $crate::HomesteadSpec as SPEC; + $e + } + $crate::SpecId::TANGERINE => { + use $crate::TangerineSpec as SPEC; + $e + } + $crate::SpecId::SPURIOUS_DRAGON => { + use $crate::SpuriousDragonSpec as SPEC; + $e + } + $crate::SpecId::BYZANTIUM => { + use $crate::ByzantiumSpec as SPEC; + $e + } + $crate::SpecId::PETERSBURG | $crate::SpecId::CONSTANTINOPLE => { + use $crate::PetersburgSpec as SPEC; + $e + } + $crate::SpecId::ISTANBUL | $crate::SpecId::MUIR_GLACIER => { + use $crate::IstanbulSpec as SPEC; + $e + } + $crate::SpecId::BERLIN => { + use $crate::BerlinSpec as SPEC; + $e + } + $crate::SpecId::LONDON + | $crate::SpecId::ARROW_GLACIER + | $crate::SpecId::GRAY_GLACIER => { + use $crate::LondonSpec as SPEC; + $e + } + $crate::SpecId::MERGE => { + use $crate::MergeSpec as SPEC; + $e + } + $crate::SpecId::SHANGHAI => { + use $crate::ShanghaiSpec as SPEC; + $e + } + $crate::SpecId::CANCUN => { + use $crate::CancunSpec as SPEC; + $e + } + $crate::SpecId::LATEST => { + use $crate::LatestSpec as SPEC; + $e + } + $crate::SpecId::PRAGUE => { + use $crate::PragueSpec as SPEC; + $e + } + } + }}; +} + +#[cfg(feature = "optimism")] #[macro_export] macro_rules! spec_to_generic { ($spec_id:expr, $e:expr) => {{ - // We are transitioning from var to generic spec. match $spec_id { $crate::SpecId::FRONTIER | SpecId::FRONTIER_THAWING => { use $crate::FrontierSpec as SPEC; @@ -271,22 +338,18 @@ macro_rules! spec_to_generic { use $crate::PragueSpec as SPEC; $e } - #[cfg(feature = "optimism")] $crate::SpecId::BEDROCK => { use $crate::BedrockSpec as SPEC; $e } - #[cfg(feature = "optimism")] $crate::SpecId::REGOLITH => { use $crate::RegolithSpec as SPEC; $e } - #[cfg(feature = "optimism")] $crate::SpecId::CANYON => { use $crate::CanyonSpec as SPEC; $e } - #[cfg(feature = "optimism")] $crate::SpecId::ECOTONE => { use $crate::EcotoneSpec as SPEC; $e From a67c30e34acbbe728e5298c183d27b31cd6d8b24 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 13 May 2024 17:23:08 +0300 Subject: [PATCH 10/88] feat(EOF): remove TXCREATE (#1415) --- crates/interpreter/src/gas/calc.rs | 16 +--- .../interpreter/src/instructions/contract.rs | 84 +------------------ crates/interpreter/src/opcode.rs | 2 +- crates/primitives/src/env.rs | 55 +----------- crates/primitives/src/result.rs | 9 -- crates/revm/src/handler/mainnet/validation.rs | 3 +- 6 files changed, 10 insertions(+), 159 deletions(-) diff --git a/crates/interpreter/src/gas/calc.rs b/crates/interpreter/src/gas/calc.rs index 828e6112f8..dd434fcd27 100644 --- a/crates/interpreter/src/gas/calc.rs +++ b/crates/interpreter/src/gas/calc.rs @@ -1,7 +1,7 @@ use super::constants::*; use crate::{ num_words, - primitives::{Address, Bytes, SpecId, U256}, + primitives::{Address, SpecId, U256}, SelfDestructResult, }; use std::vec::Vec; @@ -358,18 +358,10 @@ pub fn validate_initial_tx_gas( input: &[u8], is_create: bool, access_list: &[(Address, Vec)], - initcodes: &[Bytes], ) -> u64 { let mut initial_gas = 0; - let mut zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; - let mut non_zero_data_len = input.len() as u64 - zero_data_len; - - // Enabling of initcode is checked in `validate_env` handler. - for initcode in initcodes { - let zeros = initcode.iter().filter(|v| **v == 0).count() as u64; - zero_data_len += zeros; - non_zero_data_len += initcode.len() as u64 - zeros; - } + let zero_data_len = input.iter().filter(|v| **v == 0).count() as u64; + let non_zero_data_len = input.len() as u64 - zero_data_len; // initdate stipend initial_gas += zero_data_len * TRANSACTION_ZERO_DATA; @@ -403,7 +395,7 @@ pub fn validate_initial_tx_gas( }; // EIP-3860: Limit and meter initcode - // Initcode stipend for bytecode analysis + // Init code stipend for bytecode analysis if spec_id.is_enabled_in(SpecId::SHANGHAI) && is_create { initial_gas += initcode_cost(input.len() as u64) } diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index c3f701f28a..c0cc0cf0bd 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -6,11 +6,10 @@ pub use call_helpers::{ use revm_primitives::{keccak256, BerlinSpec}; use crate::{ - analysis::validate_eof, - gas::{self, cost_per_word, BASE, EOF_CREATE_GAS, KECCAK256WORD}, + gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD}, instructions::utility::read_u16, interpreter::Interpreter, - primitives::{Address, Bytes, Eof, Spec, SpecId::*, B256, U256}, + primitives::{Address, Bytes, Eof, Spec, SpecId::*, U256}, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInput, Host, InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE, }; @@ -91,85 +90,6 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.offset(1) }; } -pub fn txcreate(interpreter: &mut Interpreter, host: &mut H) { - require_eof!(interpreter); - gas!(interpreter, EOF_CREATE_GAS); - pop!( - interpreter, - tx_initcode_hash, - value, - salt, - data_offset, - data_size - ); - let tx_initcode_hash = B256::from(tx_initcode_hash); - - // resize memory and get return range. - let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else { - return; - }; - - // fetch initcode, if not found push ZERO. - let Some(initcode) = host - .env() - .tx - .eof_initcodes_hashed - .get(&tx_initcode_hash) - .cloned() - else { - push!(interpreter, U256::ZERO); - return; - }; - - // deduct gas for validation - gas_or_fail!(interpreter, cost_per_word(initcode.len() as u64, BASE)); - - // deduct gas for hash. TODO check order of actions. - gas_or_fail!( - interpreter, - cost_per_word(initcode.len() as u64, KECCAK256WORD) - ); - - let Ok(eof) = Eof::decode(initcode.clone()) else { - push!(interpreter, U256::ZERO); - return; - }; - - // Data section should be full, push zero to stack and return if not. - if !eof.body.is_data_filled { - push!(interpreter, U256::ZERO); - return; - } - - // Validate initcode - if validate_eof(&eof).is_err() { - push!(interpreter, U256::ZERO); - return; - } - - // Create new address. Gas for it is already deducted. - let created_address = interpreter - .contract - .caller - .create2(salt.to_be_bytes(), tx_initcode_hash); - - let gas_limit = interpreter.gas().remaining(); - // spend all gas. It will be reimbursed after frame returns. - gas!(interpreter, gas_limit); - - interpreter.next_action = InterpreterAction::EOFCreate { - inputs: Box::new(EOFCreateInput::new( - interpreter.contract.target_address, - created_address, - value, - eof, - gas_limit, - return_range, - )), - }; - interpreter.instruction_result = InstructionResult::CallOrCreate; -} - pub fn return_contract(interpreter: &mut Interpreter, _host: &mut H) { require_init_eof!(interpreter); let deploy_container_index = unsafe { read_u16(interpreter.instruction_pointer) }; diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index 5114c2ae19..1bed9cb415 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -759,7 +759,7 @@ opcodes! { // 0xEA // 0xEB 0xEC => EOFCREATE => contract::eofcreate => stack_io(4, 1), immediate_size(1); - 0xED => TXCREATE => contract::txcreate => stack_io(5, 1); + // 0xED 0xEE => RETURNCONTRACT => contract::return_contract => stack_io(2, 0), immediate_size(1), terminating; // 0xEF 0xF0 => CREATE => contract::create:: => stack_io(3, 1), not_eof; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 99b5557149..44b0736977 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -3,8 +3,8 @@ pub mod handler_cfg; pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg}; use crate::{ - calc_blob_gasprice, Account, Address, Bytes, HashMap, InvalidHeader, InvalidTransaction, Spec, - SpecId, B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, + calc_blob_gasprice, Account, Address, Bytes, InvalidHeader, InvalidTransaction, Spec, SpecId, + B256, GAS_PER_BLOB, KECCAK_EMPTY, MAX_BLOB_NUMBER_PER_BLOCK, MAX_INITCODE_SIZE, U256, VERSIONED_HASH_VERSION_KZG, }; use core::cmp::{min, Ordering}; @@ -189,41 +189,6 @@ impl Env { } } - if SPEC::enabled(SpecId::PRAGUE) { - if !self.tx.eof_initcodes.is_empty() { - // If initcode is set other fields must be empty - if !self.tx.blob_hashes.is_empty() { - return Err(InvalidTransaction::BlobVersionedHashesNotSupported); - } - // EOF Create tx extends EIP-1559 tx. It must have max_fee_per_blob_gas - if self.tx.max_fee_per_blob_gas.is_some() { - return Err(InvalidTransaction::MaxFeePerBlobGasNotSupported); - } - // EOF Create must have a to address - if matches!(self.tx.transact_to, TransactTo::Call(_)) { - return Err(InvalidTransaction::EofCrateShouldHaveToAddress); - } - } else { - // If initcode is set check its bounds. - if self.tx.eof_initcodes.len() > 256 { - return Err(InvalidTransaction::EofInitcodesNumberLimit); - } - if self - .tx - .eof_initcodes_hashed - .iter() - .any(|(_, i)| i.len() >= MAX_INITCODE_SIZE) - { - return Err(InvalidTransaction::EofInitcodesSizeLimit); - } - } - } else { - // Initcode set when not supported. - if !self.tx.eof_initcodes.is_empty() { - return Err(InvalidTransaction::EofInitcodesNotSupported); - } - } - Ok(()) } @@ -584,20 +549,6 @@ pub struct TxEnv { /// [EIP-4844]: https://eips.ethereum.org/EIPS/eip-4844 pub max_fee_per_blob_gas: Option, - /// EOF Initcodes for EOF CREATE transaction - /// - /// Incorporated as part of the Prague upgrade via [EOF] - /// - /// [EOF]: https://eips.ethereum.org/EIPS/eip-4844 - pub eof_initcodes: Vec, - - /// Internal Temporary field that stores the hashes of the EOF initcodes. - /// - /// Those are always cleared after the transaction is executed. - /// And calculated/overwritten every time transaction starts. - /// They are calculated from the [`Self::eof_initcodes`] field. - pub eof_initcodes_hashed: HashMap, - #[cfg_attr(feature = "serde", serde(flatten))] #[cfg(feature = "optimism")] /// Optimism fields. @@ -642,8 +593,6 @@ impl Default for TxEnv { access_list: Vec::new(), blob_hashes: Vec::new(), max_fee_per_blob_gas: None, - eof_initcodes: Vec::new(), - eof_initcodes_hashed: HashMap::new(), #[cfg(feature = "optimism")] optimism: OptimismFields::default(), } diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 659c4fe357..d5a0f90fa9 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -248,12 +248,6 @@ pub enum InvalidTransaction { }, /// Blob transaction contains a versioned hash with an incorrect version BlobVersionNotSupported, - /// EOF TxCreate transaction is not supported before Prague hardfork. - EofInitcodesNotSupported, - /// EOF TxCreate transaction max initcode number reached. - EofInitcodesNumberLimit, - /// EOF initcode in TXCreate is too large. - EofInitcodesSizeLimit, /// EOF crate should have `to` address EofCrateShouldHaveToAddress, /// System transactions are not supported post-regolith hardfork. @@ -346,10 +340,7 @@ impl fmt::Display for InvalidTransaction { write!(f, "too many blobs, have {have}, max {max}") } Self::BlobVersionNotSupported => write!(f, "blob version not supported"), - Self::EofInitcodesNotSupported => write!(f, "EOF initcodes not supported"), Self::EofCrateShouldHaveToAddress => write!(f, "EOF crate should have `to` address"), - Self::EofInitcodesSizeLimit => write!(f, "EOF initcodes size limit"), - Self::EofInitcodesNumberLimit => write!(f, "EOF initcodes number limit"), #[cfg(feature = "optimism")] Self::DepositSystemTxPostRegolith => { write!( diff --git a/crates/revm/src/handler/mainnet/validation.rs b/crates/revm/src/handler/mainnet/validation.rs index 22dfb5f4bc..176e0e8282 100644 --- a/crates/revm/src/handler/mainnet/validation.rs +++ b/crates/revm/src/handler/mainnet/validation.rs @@ -42,10 +42,9 @@ pub fn validate_initial_tx_gas( let input = &env.tx.data; let is_create = env.tx.transact_to.is_create(); let access_list = &env.tx.access_list; - let initcodes = &env.tx.eof_initcodes; let initial_gas_spend = - gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list, initcodes); + gas::validate_initial_tx_gas(SPEC::SPEC_ID, input, is_create, access_list); // Additional check to see if limit is big enough to cover initial gas. if initial_gas_spend > env.tx.gas_limit { From d185018d33fd73a880eaa54bdcd6e463f8a6d11a Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 13 May 2024 18:20:57 +0300 Subject: [PATCH 11/88] chore(EOF): rename extcall opcode/names (#1416) * fix(primitives): specify the optimism cfg on spec_to_generic (#1412) * chore(EOF): rename extcall opcode/names --- crates/interpreter/src/instructions/contract.rs | 4 ++-- crates/interpreter/src/opcode.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index c0cc0cf0bd..9e2cd81d2c 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -234,7 +234,7 @@ pub fn extcall(interpreter: &mut Interpreter, host interpreter.instruction_result = InstructionResult::CallOrCreate; } -pub fn extdcall(interpreter: &mut Interpreter, host: &mut H) { +pub fn extdelegatecall(interpreter: &mut Interpreter, host: &mut H) { require_eof!(interpreter); pop_address!(interpreter, target_address); @@ -267,7 +267,7 @@ pub fn extdcall(interpreter: &mut Interpreter, hos interpreter.instruction_result = InstructionResult::CallOrCreate; } -pub fn extscall(interpreter: &mut Interpreter, host: &mut H) { +pub fn extstaticcall(interpreter: &mut Interpreter, host: &mut H) { require_eof!(interpreter); pop_address!(interpreter, target_address); diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index 1bed9cb415..28483a1a9f 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -769,11 +769,11 @@ opcodes! { 0xF4 => DELEGATECALL => contract::delegate_call:: => stack_io(6, 1), not_eof; 0xF5 => CREATE2 => contract::create:: => stack_io(4, 1), not_eof; // 0xF6 - 0xF7 => RETURNDATALOAD => system::returndataload => stack_io(1, 1); - 0xF8 => EXTCALL => contract::extcall:: => stack_io(4, 1); - 0xF9 => EXFCALL => contract::extdcall:: => stack_io(3, 1); - 0xFA => STATICCALL => contract::static_call:: => stack_io(6, 1), not_eof; - 0xFB => EXTSCALL => contract::extscall => stack_io(3, 1); + 0xF7 => RETURNDATALOAD => system::returndataload => stack_io(1, 1); + 0xF8 => EXTCALL => contract::extcall:: => stack_io(4, 1); + 0xF9 => EXTDELEGATECALL => contract::extdelegatecall:: => stack_io(3, 1); + 0xFA => STATICCALL => contract::static_call:: => stack_io(6, 1), not_eof; + 0xFB => EXTSTATICCALL => contract::extstaticcall => stack_io(3, 1); // 0xFC 0xFD => REVERT => control::revert:: => stack_io(2, 0), terminating; 0xFE => INVALID => control::invalid => stack_io(0, 0), terminating; From 84d1372e072564ae4f3334a60e9074d2790f6293 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 14 May 2024 16:36:59 +0300 Subject: [PATCH 12/88] feat(EOF): Add CALLF/JUMPF stack checks (#1417) * feat(EOF): Add CALLF stack check * fix tests * jump stack check --- .../interpreter/src/instructions/control.rs | 138 ++++++++++++++++-- crates/interpreter/src/interpreter.rs | 2 +- .../src/bytecode/eof/types_section.rs | 8 + 3 files changed, 132 insertions(+), 16 deletions(-) diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index f1c5417a3d..db2bc70adf 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -87,13 +87,24 @@ pub fn callf(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::LOW); let idx = unsafe { read_u16(interpreter.instruction_pointer) } as usize; - // TODO Check stack with EOF types. - if interpreter.function_stack.return_stack_len() == 1024 { + if interpreter.function_stack.return_stack_len() >= 1024 { interpreter.instruction_result = InstructionResult::EOFFunctionStackOverflow; return; } + // get target types + let Some(types) = interpreter.eof().unwrap().body.types_section.get(idx) else { + panic!("Invalid EOF in execution, expecting correct intermediate in callf") + }; + + // Check max stack height for target code section. + // safe to subtract as max_stack_height is always more than inputs. + if interpreter.stack.len() + (types.max_stack_size - types.inputs as u16) as usize > 1024 { + interpreter.instruction_result = InstructionResult::StackOverflow; + return; + } + // push current idx and PC to the callf stack. // PC is incremented by 2 to point to the next instruction after callf. interpreter @@ -120,7 +131,17 @@ pub fn jumpf(interpreter: &mut Interpreter, _host: &mut H) { let idx = unsafe { read_u16(interpreter.instruction_pointer) } as usize; - // TODO(EOF) do types stack checks + // get target types + let Some(types) = interpreter.eof().unwrap().body.types_section.get(idx) else { + panic!("Invalid EOF in execution, expecting correct intermediate in jumpf") + }; + + // Check max stack height for target code section. + // safe to subtract as max_stack_height is always more than inputs. + if interpreter.stack.len() + (types.max_stack_size - types.inputs as u16) as usize > 1024 { + interpreter.instruction_result = InstructionResult::StackOverflow; + return; + } interpreter.function_stack.set_current_code_idx(idx); interpreter.load_eof_code(idx, 0) @@ -183,7 +204,7 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { #[cfg(test)] mod test { - use revm_primitives::{bytes, Bytecode, Eof, PragueSpec}; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, PragueSpec}; use super::*; use crate::{ @@ -281,27 +302,39 @@ mod test { Eof::decode(bytes).unwrap() } - #[test] - fn callf_retf_jumpf() { - let table = make_instruction_table::<_, PragueSpec>(); - let mut host = DummyHost::default(); + fn eof_setup(bytes1: Bytes, bytes2: Bytes) -> Interpreter { + eof_setup_with_types(bytes1, bytes2, TypesSection::default()) + } + + /// Two code section and types section is for last code. + fn eof_setup_with_types(bytes1: Bytes, bytes2: Bytes, types: TypesSection) -> Interpreter { let mut eof = dummy_eof(); eof.body.code_section.clear(); + eof.body.types_section.clear(); eof.header.code_sizes.clear(); - let bytes1 = Bytes::from([CALLF, 0x00, 0x01, JUMPF, 0x00, 0x01]); eof.header.code_sizes.push(bytes1.len() as u16); eof.body.code_section.push(bytes1.clone()); - let bytes2 = Bytes::from([STOP, RETF]); + eof.body.types_section.push(TypesSection::new(0, 0, 11)); + eof.header.code_sizes.push(bytes2.len() as u16); eof.body.code_section.push(bytes2.clone()); + eof.body.types_section.push(types); let mut interp = Interpreter::new_bytecode(Bytecode::Eof(eof)); interp.gas = Gas::new(10000); + interp + } - assert_eq!(interp.function_stack.current_code_idx, 0); - assert!(interp.function_stack.return_stack.is_empty()); + #[test] + fn callf_retf_stop() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let bytes1 = Bytes::from([CALLF, 0x00, 0x01, STOP]); + let bytes2 = Bytes::from([RETF]); + let mut interp = eof_setup(bytes1, bytes2.clone()); // CALLF interp.step(&table, &mut host); @@ -313,8 +346,6 @@ mod test { ); assert_eq!(interp.instruction_pointer, bytes2.as_ptr()); - // STOP - interp.step(&table, &mut host); // RETF interp.step(&table, &mut host); @@ -322,10 +353,87 @@ mod test { assert_eq!(interp.function_stack.return_stack, Vec::new()); assert_eq!(interp.program_counter(), 3); + // STOP + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Stop); + } + + #[test] + fn callf_stop() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); + let bytes2 = Bytes::from([STOP]); + let mut interp = eof_setup(bytes1, bytes2.clone()); + + // CALLF + interp.step(&table, &mut host); + + assert_eq!(interp.function_stack.current_code_idx, 1); + assert_eq!( + interp.function_stack.return_stack[0], + FunctionReturnFrame::new(0, 3) + ); + assert_eq!(interp.instruction_pointer, bytes2.as_ptr()); + + // STOP + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Stop); + } + + #[test] + fn callf_stack_overflow() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let bytes1 = Bytes::from([CALLF, 0x00, 0x01]); + let bytes2 = Bytes::from([STOP]); + let mut interp = + eof_setup_with_types(bytes1, bytes2.clone(), TypesSection::new(0, 0, 1025)); + + // CALLF + interp.step(&table, &mut host); + + // stack overflow + assert_eq!(interp.instruction_result, InstructionResult::StackOverflow); + } + + #[test] + fn jumpf_stop() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); + let bytes2 = Bytes::from([STOP]); + let mut interp = eof_setup(bytes1, bytes2.clone()); + // JUMPF interp.step(&table, &mut host); + assert_eq!(interp.function_stack.current_code_idx, 1); - assert_eq!(interp.function_stack.return_stack, Vec::new()); + assert!(interp.function_stack.return_stack.is_empty()); assert_eq!(interp.instruction_pointer, bytes2.as_ptr()); + + // STOP + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Stop); + } + + #[test] + fn jumpf_stack_overflow() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let bytes1 = Bytes::from([JUMPF, 0x00, 0x01]); + let bytes2 = Bytes::from([STOP]); + let mut interp = + eof_setup_with_types(bytes1, bytes2.clone(), TypesSection::new(0, 0, 1025)); + + // JUMPF + interp.step(&table, &mut host); + + // stack overflow + assert_eq!(interp.instruction_result, InstructionResult::StackOverflow); } } diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 3546e48d56..a27752b2e8 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -137,7 +137,7 @@ impl Interpreter { pub(crate) fn load_eof_code(&mut self, idx: usize, pc: usize) { // SAFETY: eof flag is true only if bytecode is Eof. let Bytecode::Eof(eof) = &self.contract.bytecode else { - panic!("Expected EOF bytecode") + panic!("Expected EOF code section") }; let Some(code) = eof.body.code(idx) else { panic!("Code not found") diff --git a/crates/primitives/src/bytecode/eof/types_section.rs b/crates/primitives/src/bytecode/eof/types_section.rs index 7695dc97ff..5acc3b7138 100644 --- a/crates/primitives/src/bytecode/eof/types_section.rs +++ b/crates/primitives/src/bytecode/eof/types_section.rs @@ -20,6 +20,14 @@ pub struct TypesSection { } impl TypesSection { + /// Returns new `TypesSection` with the given inputs, outputs, and max_stack_size. + pub fn new(inputs: u8, outputs: u8, max_stack_size: u16) -> Self { + Self { + inputs, + outputs, + max_stack_size, + } + } /// Calculates the difference between the number of input and output stack elements. #[inline] pub const fn io_diff(&self) -> i32 { From 4763c8b1af5e0422f3c55dadbd86bc755399f8d9 Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Wed, 15 May 2024 11:23:37 +0200 Subject: [PATCH 13/88] feat: add Opcode::modifies_memory back (#1421) --- crates/interpreter/src/opcode.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index 28483a1a9f..b5b6ffd17c 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -313,6 +313,28 @@ impl OpCode { pub const fn get(self) -> u8 { self.0 } + + /// Returns true if the opcode modifies memory. + /// + /// + #[inline] + pub const fn modifies_memory(&self) -> bool { + matches!( + *self, + OpCode::EXTCODECOPY + | OpCode::MLOAD + | OpCode::MSTORE + | OpCode::MSTORE8 + | OpCode::MCOPY + | OpCode::CODECOPY + | OpCode::CALLDATACOPY + | OpCode::RETURNDATACOPY + | OpCode::CALL + | OpCode::CALLCODE + | OpCode::DELEGATECALL + | OpCode::STATICCALL + ) + } } /// Information about opcode, such as name, and stack inputs and outputs. From 6e81b880c928a008cab16621b090c657014979e8 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 16 May 2024 16:41:22 +0300 Subject: [PATCH 14/88] feat: adjust gas-costs for EIP-2935 BLOCKHASH (#1422) --- crates/interpreter/src/instructions/host.rs | 24 +++++++++---------- crates/interpreter/src/instructions/macros.rs | 24 ------------------- 2 files changed, 11 insertions(+), 37 deletions(-) diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 43cba873b0..eea5dc20a5 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -110,17 +110,16 @@ pub fn blockhash(interpreter: &mut Interpreter, ho let block_number = host.env().block.number; match block_number.checked_sub(*number) { + // blockhash should push zero if number is same as current block number. Some(diff) if !diff.is_zero() => { let diff = as_usize_saturated!(diff); - // blockhash should push zero if number is same as current block number. if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { - let value = sload!( - interpreter, - host, - BLOCKHASH_STORAGE_ADDRESS, - number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)) - ); + let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); + let Some((value, _)) = host.sload(BLOCKHASH_STORAGE_ADDRESS, index) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; *number = value; return; } else if diff <= BLOCK_HASH_HISTORY { @@ -143,12 +142,11 @@ pub fn blockhash(interpreter: &mut Interpreter, ho pub fn sload(interpreter: &mut Interpreter, host: &mut H) { pop_top!(interpreter, index); - let value = sload!( - interpreter, - host, - interpreter.contract.target_address, - *index - ); + let Some((value, is_cold)) = host.sload(interpreter.contract.target_address, *index) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + gas!(interpreter, gas::sload_cost(SPEC::SPEC_ID, is_cold)); *index = value; } diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index a4ee4f4b3e..2592956ec7 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -45,30 +45,6 @@ macro_rules! check { }; } -/// Performs an `SLOAD` on the target account and storage index. -/// -/// If the slot could not be loaded, or if the gas cost could not be charged, the expanded code -/// sets the instruction result and returns accordingly. -/// -/// # Note -/// -/// This macro charges gas. -/// -/// # Returns -/// -/// Expands to the value of the storage slot. -#[macro_export] -macro_rules! sload { - ($interp:expr, $host:expr, $address:expr, $index:expr) => {{ - let Some((value, is_cold)) = $host.sload($address, $index) else { - $interp.instruction_result = $crate::InstructionResult::FatalExternalError; - return; - }; - $crate::gas!($interp, $crate::gas::sload_cost(SPEC::SPEC_ID, is_cold)); - value - }}; -} - /// Records a `gas` cost and fails the instruction if it would exceed the available gas. #[macro_export] macro_rules! gas { From f07c0ef1c27d7a7a6b160849f4f2c88dcd843cfe Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 16 May 2024 16:47:41 +0300 Subject: [PATCH 15/88] Revert "feat: implement EIP-2935 (#1354)" (#1424) * Revert "feat: implement EIP-2935 (#1354)" This reverts commit 3e089f35ed2a98278ddbae8f5dd816ccc373fa31. * dont revert some commend changes * Revert "fix(eip2935): Preload blockchash storage address (#1395)" This reverts commit aeefcda7fa124a8695228e5b8ab4118083f80a03. --- crates/interpreter/src/instructions/host.rs | 38 +++++-------------- crates/interpreter/src/opcode.rs | 2 +- crates/primitives/src/constants.rs | 31 +++------------ .../revm/src/handler/mainnet/pre_execution.rs | 14 +------ 4 files changed, 19 insertions(+), 66 deletions(-) diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index eea5dc20a5..bad571de35 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -5,7 +5,7 @@ use crate::{ Host, InstructionResult, SStoreResult, }; use core::cmp::min; -use revm_primitives::{BLOCKHASH_SERVE_WINDOW, BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY}; +use revm_primitives::BLOCK_HASH_HISTORY; use std::vec::Vec; pub fn balance(interpreter: &mut Interpreter, host: &mut H) { @@ -103,40 +103,22 @@ pub fn extcodecopy(interpreter: &mut Interpreter, .set_data(memory_offset, code_offset, len, &code.original_bytes()); } -pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { +pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BLOCKHASH); pop_top!(interpreter, number); - let block_number = host.env().block.number; - - match block_number.checked_sub(*number) { + if let Some(diff) = host.env().block.number.checked_sub(*number) { + let diff = as_usize_saturated!(diff); // blockhash should push zero if number is same as current block number. - Some(diff) if !diff.is_zero() => { - let diff = as_usize_saturated!(diff); - - if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { - let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); - let Some((value, _)) = host.sload(BLOCKHASH_STORAGE_ADDRESS, index) else { - interpreter.instruction_result = InstructionResult::FatalExternalError; - return; - }; - *number = value; - return; - } else if diff <= BLOCK_HASH_HISTORY { - let Some(hash) = host.block_hash(*number) else { - interpreter.instruction_result = InstructionResult::FatalExternalError; - return; - }; - *number = U256::from_be_bytes(hash.0); + if diff <= BLOCK_HASH_HISTORY && diff != 0 { + let Some(hash) = host.block_hash(*number) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; return; - } - } - _ => { - // If blockhash is requested for the current block, the hash should be 0, so we fall - // through. + }; + *number = U256::from_be_bytes(hash.0); + return; } } - *number = U256::ZERO; } diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index b5b6ffd17c..672d1ecd92 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -604,7 +604,7 @@ opcodes! { 0x3D => RETURNDATASIZE => system::returndatasize:: => stack_io(0, 1); 0x3E => RETURNDATACOPY => system::returndatacopy:: => stack_io(3, 0); 0x3F => EXTCODEHASH => host::extcodehash:: => stack_io(1, 1), not_eof; - 0x40 => BLOCKHASH => host::blockhash:: => stack_io(1, 1); + 0x40 => BLOCKHASH => host::blockhash => stack_io(1, 1); 0x41 => COINBASE => host_env::coinbase => stack_io(0, 1); 0x42 => TIMESTAMP => host_env::timestamp => stack_io(0, 1); 0x43 => NUMBER => host_env::block_number => stack_io(0, 1); diff --git a/crates/primitives/src/constants.rs b/crates/primitives/src/constants.rs index c8223300bf..1ad219dca9 100644 --- a/crates/primitives/src/constants.rs +++ b/crates/primitives/src/constants.rs @@ -1,41 +1,22 @@ -use alloy_primitives::{address, Address}; +use crate::Address; /// EIP-170: Contract code size limit -/// -/// By default the limit is `0x6000` (~25kb) +/// By default limit is 0x6000 (~25kb) pub const MAX_CODE_SIZE: usize = 0x6000; -/// Number of block hashes that EVM can access in the past (pre-Prague). +/// Number of block hashes that EVM can access in the past pub const BLOCK_HASH_HISTORY: usize = 256; -/// EIP-2935: Serve historical block hashes from state -/// -/// Number of block hashes the EVM can access in the past (Prague). -/// -/// # Note -/// -/// This is named `HISTORY_SERVE_WINDOW` in the EIP. -pub const BLOCKHASH_SERVE_WINDOW: usize = 8192; - -/// EIP-2935: Serve historical block hashes from state -/// -/// The address where historical blockhashes are available. -/// -/// # Note -/// -/// This is named `HISTORY_STORAGE_ADDRESS` in the EIP. -pub const BLOCKHASH_STORAGE_ADDRESS: Address = address!("25a219378dad9b3503c8268c9ca836a52427a4fb"); - /// EIP-3860: Limit and meter initcode /// -/// Limit of maximum initcode size is `2 * MAX_CODE_SIZE`. +/// Limit of maximum initcode size is 2 * MAX_CODE_SIZE pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE; -/// The address of precompile 3, which is handled specially in a few places. +/// Precompile 3 is special in few places pub const PRECOMPILE3: Address = Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); -// === EIP-4844 constants === +// --- EIP-4844 constants --- /// Gas consumption of a single data blob (== blob byte size). pub const GAS_PER_BLOB: u64 = 1 << 17; diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index c0f4fe7bde..64b41e7045 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -7,8 +7,8 @@ use crate::{ primitives::{ db::Database, Account, EVMError, Env, Spec, - SpecId::{CANCUN, PRAGUE, SHANGHAI}, - TransactTo, BLOCKHASH_STORAGE_ADDRESS, U256, + SpecId::{CANCUN, SHANGHAI}, + TransactTo, U256, }, Context, ContextPrecompiles, }; @@ -39,16 +39,6 @@ pub fn load_accounts( )?; } - // Load blockhash storage address - // EIP-2935: Serve historical block hashes from state - if SPEC::enabled(PRAGUE) { - context.evm.inner.journaled_state.initial_account_load( - BLOCKHASH_STORAGE_ADDRESS, - &[], - &mut context.evm.inner.db, - )?; - } - context.evm.load_access_list()?; Ok(()) } From eed27d92266776d653a1d08c46ffa9699d64d527 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 16 May 2024 17:29:07 +0300 Subject: [PATCH 16/88] Revert "Revert "feat: implement EIP-2935 (#1354)" (#1424)" (#1426) This reverts commit f07c0ef1c27d7a7a6b160849f4f2c88dcd843cfe. --- crates/interpreter/src/instructions/host.rs | 38 ++++++++++++++----- crates/interpreter/src/opcode.rs | 2 +- crates/primitives/src/constants.rs | 31 ++++++++++++--- .../revm/src/handler/mainnet/pre_execution.rs | 14 ++++++- 4 files changed, 66 insertions(+), 19 deletions(-) diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index bad571de35..eea5dc20a5 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -5,7 +5,7 @@ use crate::{ Host, InstructionResult, SStoreResult, }; use core::cmp::min; -use revm_primitives::BLOCK_HASH_HISTORY; +use revm_primitives::{BLOCKHASH_SERVE_WINDOW, BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY}; use std::vec::Vec; pub fn balance(interpreter: &mut Interpreter, host: &mut H) { @@ -103,22 +103,40 @@ pub fn extcodecopy(interpreter: &mut Interpreter, .set_data(memory_offset, code_offset, len, &code.original_bytes()); } -pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { +pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { gas!(interpreter, gas::BLOCKHASH); pop_top!(interpreter, number); - if let Some(diff) = host.env().block.number.checked_sub(*number) { - let diff = as_usize_saturated!(diff); + let block_number = host.env().block.number; + + match block_number.checked_sub(*number) { // blockhash should push zero if number is same as current block number. - if diff <= BLOCK_HASH_HISTORY && diff != 0 { - let Some(hash) = host.block_hash(*number) else { - interpreter.instruction_result = InstructionResult::FatalExternalError; + Some(diff) if !diff.is_zero() => { + let diff = as_usize_saturated!(diff); + + if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { + let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); + let Some((value, _)) = host.sload(BLOCKHASH_STORAGE_ADDRESS, index) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + *number = value; + return; + } else if diff <= BLOCK_HASH_HISTORY { + let Some(hash) = host.block_hash(*number) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + *number = U256::from_be_bytes(hash.0); return; - }; - *number = U256::from_be_bytes(hash.0); - return; + } + } + _ => { + // If blockhash is requested for the current block, the hash should be 0, so we fall + // through. } } + *number = U256::ZERO; } diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index 672d1ecd92..b5b6ffd17c 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -604,7 +604,7 @@ opcodes! { 0x3D => RETURNDATASIZE => system::returndatasize:: => stack_io(0, 1); 0x3E => RETURNDATACOPY => system::returndatacopy:: => stack_io(3, 0); 0x3F => EXTCODEHASH => host::extcodehash:: => stack_io(1, 1), not_eof; - 0x40 => BLOCKHASH => host::blockhash => stack_io(1, 1); + 0x40 => BLOCKHASH => host::blockhash:: => stack_io(1, 1); 0x41 => COINBASE => host_env::coinbase => stack_io(0, 1); 0x42 => TIMESTAMP => host_env::timestamp => stack_io(0, 1); 0x43 => NUMBER => host_env::block_number => stack_io(0, 1); diff --git a/crates/primitives/src/constants.rs b/crates/primitives/src/constants.rs index 1ad219dca9..c8223300bf 100644 --- a/crates/primitives/src/constants.rs +++ b/crates/primitives/src/constants.rs @@ -1,22 +1,41 @@ -use crate::Address; +use alloy_primitives::{address, Address}; /// EIP-170: Contract code size limit -/// By default limit is 0x6000 (~25kb) +/// +/// By default the limit is `0x6000` (~25kb) pub const MAX_CODE_SIZE: usize = 0x6000; -/// Number of block hashes that EVM can access in the past +/// Number of block hashes that EVM can access in the past (pre-Prague). pub const BLOCK_HASH_HISTORY: usize = 256; +/// EIP-2935: Serve historical block hashes from state +/// +/// Number of block hashes the EVM can access in the past (Prague). +/// +/// # Note +/// +/// This is named `HISTORY_SERVE_WINDOW` in the EIP. +pub const BLOCKHASH_SERVE_WINDOW: usize = 8192; + +/// EIP-2935: Serve historical block hashes from state +/// +/// The address where historical blockhashes are available. +/// +/// # Note +/// +/// This is named `HISTORY_STORAGE_ADDRESS` in the EIP. +pub const BLOCKHASH_STORAGE_ADDRESS: Address = address!("25a219378dad9b3503c8268c9ca836a52427a4fb"); + /// EIP-3860: Limit and meter initcode /// -/// Limit of maximum initcode size is 2 * MAX_CODE_SIZE +/// Limit of maximum initcode size is `2 * MAX_CODE_SIZE`. pub const MAX_INITCODE_SIZE: usize = 2 * MAX_CODE_SIZE; -/// Precompile 3 is special in few places +/// The address of precompile 3, which is handled specially in a few places. pub const PRECOMPILE3: Address = Address::new([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3]); -// --- EIP-4844 constants --- +// === EIP-4844 constants === /// Gas consumption of a single data blob (== blob byte size). pub const GAS_PER_BLOB: u64 = 1 << 17; diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index 64b41e7045..c0f4fe7bde 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -7,8 +7,8 @@ use crate::{ primitives::{ db::Database, Account, EVMError, Env, Spec, - SpecId::{CANCUN, SHANGHAI}, - TransactTo, U256, + SpecId::{CANCUN, PRAGUE, SHANGHAI}, + TransactTo, BLOCKHASH_STORAGE_ADDRESS, U256, }, Context, ContextPrecompiles, }; @@ -39,6 +39,16 @@ pub fn load_accounts( )?; } + // Load blockhash storage address + // EIP-2935: Serve historical block hashes from state + if SPEC::enabled(PRAGUE) { + context.evm.inner.journaled_state.initial_account_load( + BLOCKHASH_STORAGE_ADDRESS, + &[], + &mut context.evm.inner.db, + )?; + } + context.evm.load_access_list()?; Ok(()) } From 7046d5e30e08e913ea160de32a5a338868b62e40 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 16 May 2024 18:35:14 +0300 Subject: [PATCH 17/88] fix: blockchash for devnet-0 (#1427) * fix: load blockchash only from serve_window * fix: devnet-0 blockchash behaviour --- crates/interpreter/src/instructions/host.rs | 36 +++-------------- crates/revm/src/context.rs | 44 ++++++++++++++++++--- 2 files changed, 44 insertions(+), 36 deletions(-) diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index eea5dc20a5..20a2bcfe6c 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -5,7 +5,6 @@ use crate::{ Host, InstructionResult, SStoreResult, }; use core::cmp::min; -use revm_primitives::{BLOCKHASH_SERVE_WINDOW, BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY}; use std::vec::Vec; pub fn balance(interpreter: &mut Interpreter, host: &mut H) { @@ -108,36 +107,11 @@ pub fn blockhash(interpreter: &mut Interpreter, ho pop_top!(interpreter, number); let block_number = host.env().block.number; - - match block_number.checked_sub(*number) { - // blockhash should push zero if number is same as current block number. - Some(diff) if !diff.is_zero() => { - let diff = as_usize_saturated!(diff); - - if SPEC::enabled(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { - let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); - let Some((value, _)) = host.sload(BLOCKHASH_STORAGE_ADDRESS, index) else { - interpreter.instruction_result = InstructionResult::FatalExternalError; - return; - }; - *number = value; - return; - } else if diff <= BLOCK_HASH_HISTORY { - let Some(hash) = host.block_hash(*number) else { - interpreter.instruction_result = InstructionResult::FatalExternalError; - return; - }; - *number = U256::from_be_bytes(hash.0); - return; - } - } - _ => { - // If blockhash is requested for the current block, the hash should be 0, so we fall - // through. - } - } - - *number = U256::ZERO; + let Some(hash) = host.block_hash(block_number) else { + interpreter.instruction_result = InstructionResult::FatalExternalError; + return; + }; + *number = U256::from_be_bytes(hash.0); } pub fn sload(interpreter: &mut Interpreter, host: &mut H) { diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 343dfcf985..f3c776a01c 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -8,11 +8,15 @@ pub use context_precompiles::{ }; pub use evm_context::EvmContext; pub use inner_evm_context::InnerEvmContext; +use revm_interpreter::as_usize_saturated; use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, - primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, U256}, + primitives::{ + Address, Bytecode, EVMError, Env, HandlerCfg, Log, B256, BLOCKHASH_SERVE_WINDOW, + BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY, PRAGUE, U256, + }, }; use std::boxed::Box; @@ -106,10 +110,40 @@ impl Host for Context { } fn block_hash(&mut self, number: U256) -> Option { - self.evm - .block_hash(number) - .map_err(|e| self.evm.error = Err(e)) - .ok() + let block_number = self.env().block.number; + + match block_number.checked_sub(number) { + // blockhash should push zero if number is same as current block number. + Some(diff) if !diff.is_zero() => { + let diff = as_usize_saturated!(diff); + + if diff <= BLOCK_HASH_HISTORY { + return self + .evm + .block_hash(number) + .map_err(|e| self.evm.error = Err(e)) + .ok(); + } + + if self.evm.journaled_state.spec.is_enabled_in(PRAGUE) + && diff <= BLOCKHASH_SERVE_WINDOW + { + let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); + return self + .evm + .db + .storage(BLOCKHASH_STORAGE_ADDRESS, index) + .map_err(|e| self.evm.error = Err(EVMError::Database(e))) + .ok() + .map(|v| v.into()); + } + } + _ => { + // If blockhash is requested for the current block, the hash should be 0, so we fall + // through. + } + } + Some(B256::ZERO) } fn load_account(&mut self, address: Address) -> Option { From 05f3c5bdccb3d7c4229a40137dc28ccf4bb0b213 Mon Sep 17 00:00:00 2001 From: grandizzy <38490174+grandizzy@users.noreply.github.com> Date: Fri, 17 May 2024 12:20:47 +0300 Subject: [PATCH 18/88] fix(interpreter): avoid overflow when checking if mem limit reached (#1429) --- crates/interpreter/src/interpreter/shared_memory.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index e76015a58c..cc63e1bf07 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -90,7 +90,7 @@ impl SharedMemory { #[cfg(feature = "memory_limit")] #[inline] pub fn limit_reached(&self, new_size: usize) -> bool { - (self.last_checkpoint + new_size) as u64 > self.memory_limit + self.last_checkpoint.saturating_add(new_size) as u64 > self.memory_limit } /// Prepares the shared memory for a new context. From 22398201c6cf8954a4a497038aa515710650f369 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 17 May 2024 15:51:38 +0300 Subject: [PATCH 19/88] chore: cleanup host blockhash fn (#1430) --- crates/revm/src/context.rs | 62 ++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index f3c776a01c..aa2ae4be9c 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -110,39 +110,37 @@ impl Host for Context { } fn block_hash(&mut self, number: U256) -> Option { - let block_number = self.env().block.number; - - match block_number.checked_sub(number) { - // blockhash should push zero if number is same as current block number. - Some(diff) if !diff.is_zero() => { - let diff = as_usize_saturated!(diff); - - if diff <= BLOCK_HASH_HISTORY { - return self - .evm - .block_hash(number) - .map_err(|e| self.evm.error = Err(e)) - .ok(); - } - - if self.evm.journaled_state.spec.is_enabled_in(PRAGUE) - && diff <= BLOCKHASH_SERVE_WINDOW - { - let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); - return self - .evm - .db - .storage(BLOCKHASH_STORAGE_ADDRESS, index) - .map_err(|e| self.evm.error = Err(EVMError::Database(e))) - .ok() - .map(|v| v.into()); - } - } - _ => { - // If blockhash is requested for the current block, the hash should be 0, so we fall - // through. - } + let block_number = as_usize_saturated!(self.env().block.number); + let requested_number = as_usize_saturated!(number); + + let Some(diff) = block_number.checked_sub(requested_number) else { + return Some(B256::ZERO); + }; + + // blockhash should push zero if number is same as current block number. + if diff == 0 { + return Some(B256::ZERO); + } + + if diff <= BLOCK_HASH_HISTORY { + return self + .evm + .block_hash(number) + .map_err(|e| self.evm.error = Err(e)) + .ok(); } + + if self.evm.journaled_state.spec.is_enabled_in(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { + let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); + return self + .evm + .db + .storage(BLOCKHASH_STORAGE_ADDRESS, index) + .map_err(|e| self.evm.error = Err(EVMError::Database(e))) + .ok() + .map(|v| v.into()); + } + Some(B256::ZERO) } From 8fd85f17c843eb7a112041cee3c477b18d798058 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Fri, 17 May 2024 16:14:25 +0300 Subject: [PATCH 20/88] fix(precompile): BLS G2 MSM (#1428) * test(precompile): add BLS test vectors * fix(gakonst): dont blow up on bls p2_affines * uncomment g1 msm required gas * chore: small refactors * rm artifacts * add new bls test jsons * remove fail-tests these should be added again at some point * fix: perform subgroup checks only on msm, pairing, and scalar multiplications * fix docs --------- Co-authored-by: Georgios Konstantopoulos Co-authored-by: rakita Co-authored-by: Dan Cline <6798349+Rjected@users.noreply.github.com> --- Cargo.lock | 40 ++++++ crates/precompile/Cargo.toml | 5 + crates/precompile/src/bls12_381.rs | 134 ++++++++++++++++++ crates/precompile/src/bls12_381/g1.rs | 47 +++++- crates/precompile/src/bls12_381/g1_add.rs | 9 +- crates/precompile/src/bls12_381/g1_msm.rs | 6 +- crates/precompile/src/bls12_381/g1_mul.rs | 7 +- crates/precompile/src/bls12_381/g2.rs | 46 +++++- crates/precompile/src/bls12_381/g2_add.rs | 9 +- crates/precompile/src/bls12_381/g2_msm.rs | 23 ++- crates/precompile/src/bls12_381/g2_mul.rs | 7 +- .../precompile/src/bls12_381/map_fp2_to_g2.rs | 2 +- .../precompile/src/bls12_381/map_fp_to_g1.rs | 2 +- crates/precompile/src/bls12_381/mod.rs | 31 ---- crates/precompile/src/bls12_381/pairing.rs | 15 +- .../precompile/test-vectors/add_G1_bls.json | 65 +++++++++ .../precompile/test-vectors/add_G2_bls.json | 65 +++++++++ .../test-vectors/map_fp2_to_G2_bls.json | 37 +++++ .../test-vectors/map_fp_to_G1_bls.json | 37 +++++ .../precompile/test-vectors/mul_G1_bls.json | 79 +++++++++++ .../precompile/test-vectors/mul_G2_bls.json | 79 +++++++++++ .../test-vectors/multiexp_G1_bls.json | 79 +++++++++++ .../test-vectors/multiexp_G2_bls.json | 86 +++++++++++ .../test-vectors/pairing_check_bls.json | 44 ++++++ 24 files changed, 893 insertions(+), 61 deletions(-) create mode 100644 crates/precompile/src/bls12_381.rs delete mode 100644 crates/precompile/src/bls12_381/mod.rs create mode 100644 crates/precompile/test-vectors/add_G1_bls.json create mode 100644 crates/precompile/test-vectors/add_G2_bls.json create mode 100644 crates/precompile/test-vectors/map_fp2_to_G2_bls.json create mode 100644 crates/precompile/test-vectors/map_fp_to_G1_bls.json create mode 100644 crates/precompile/test-vectors/mul_G1_bls.json create mode 100644 crates/precompile/test-vectors/mul_G2_bls.json create mode 100644 crates/precompile/test-vectors/multiexp_G1_bls.json create mode 100644 crates/precompile/test-vectors/multiexp_G2_bls.json create mode 100644 crates/precompile/test-vectors/pairing_check_bls.json diff --git a/Cargo.lock b/Cargo.lock index 578b26349e..e6914d008c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2836,6 +2836,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + [[package]] name = "reqwest" version = "0.11.27" @@ -2964,12 +2970,17 @@ dependencies = [ "blst", "c-kzg", "criterion", + "eyre", "k256", "once_cell", "rand", "revm-primitives", "ripemd", + "rstest", "secp256k1", + "serde", + "serde_derive", + "serde_json", "sha2", "substrate-bn", ] @@ -3099,6 +3110,35 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "rstest" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version 0.4.0", +] + +[[package]] +name = "rstest_macros" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version 0.4.0", + "syn 2.0.55", + "unicode-ident", +] + [[package]] name = "ruint" version = "1.12.1" diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index bd145fa9b1..f761e726e1 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -47,6 +47,11 @@ blst = { version = "0.3.11", optional = true } [dev-dependencies] criterion = { version = "0.5" } rand = { version = "0.8", features = ["std"] } +eyre = "0.6.12" +rstest = "0.19.0" +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst"] diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs new file mode 100644 index 0000000000..fd5daae00a --- /dev/null +++ b/crates/precompile/src/bls12_381.rs @@ -0,0 +1,134 @@ +use crate::PrecompileWithAddress; + +mod g1; +pub mod g1_add; +pub mod g1_msm; +pub mod g1_mul; +mod g2; +pub mod g2_add; +pub mod g2_msm; +pub mod g2_mul; +pub mod map_fp2_to_g2; +pub mod map_fp_to_g1; +mod msm; +pub mod pairing; +mod utils; + +/// Returns the BLS12-381 precompiles with their addresses. +pub fn precompiles() -> impl Iterator { + [ + g1_add::PRECOMPILE, + g1_mul::PRECOMPILE, + g1_msm::PRECOMPILE, + g2_add::PRECOMPILE, + g2_mul::PRECOMPILE, + g2_msm::PRECOMPILE, + pairing::PRECOMPILE, + map_fp_to_g1::PRECOMPILE, + map_fp2_to_g2::PRECOMPILE, + ] + .into_iter() +} + +#[cfg(test)] +mod test { + use super::g1_add; + use super::g1_msm; + use super::g1_mul; + use super::g2_add; + use super::g2_msm; + use super::g2_mul; + use super::map_fp2_to_g2; + use super::map_fp_to_g1; + use super::msm::msm_required_gas; + use super::pairing; + use eyre::Result; + use revm_primitives::{hex::FromHex, Bytes, PrecompileResult}; + use rstest::rstest; + use serde_derive::{Deserialize, Serialize}; + use std::{fs, path::Path}; + + #[derive(Serialize, Deserialize, Debug)] + #[serde(rename_all = "PascalCase")] + struct TestVector { + input: String, + expected: String, + name: String, + gas: u64, + error: Option, + } + + #[derive(Serialize, Deserialize, Debug)] + struct TestVectors(Vec); + + fn load_test_vectors>(path: P) -> Result { + let file_contents = fs::read_to_string(path)?; + Ok(serde_json::from_str(&file_contents)?) + } + + #[rstest] + #[case::g1_add(g1_add::g1_add, "add_G1_bls.json")] + #[case::g1_mul(g1_mul::g1_mul, "mul_G1_bls.json")] + #[case::g1_msm(g1_msm::g1_msm, "multiexp_G1_bls.json")] + #[case::g2_add(g2_add::g2_add, "add_G2_bls.json")] + #[case::g2_mul(g2_mul::g2_mul, "mul_G2_bls.json")] + #[case::g2_msm(g2_msm::g2_msm, "multiexp_G2_bls.json")] + #[case::pairing(pairing::pairing, "pairing_check_bls.json")] + #[case::map_fp_to_g1(map_fp_to_g1::map_fp_to_g1, "map_fp_to_G1_bls.json")] + #[case::map_fp2_to_g2(map_fp2_to_g2::map_fp2_to_g2, "map_fp2_to_G2_bls.json")] + fn test_bls( + #[case] precompile: fn(input: &Bytes, gas_limit: u64) -> PrecompileResult, + #[case] file_name: &str, + ) { + let test_vectors = load_test_vectors(format!("test-vectors/{file_name}")) + .unwrap_or_else(|e| panic!("Failed to load test vectors from {file_name}: {e}")); + + for vector in test_vectors.0 { + let test_name = format!("{file_name}/{}", vector.name); + let input = Bytes::from_hex(vector.input.clone()).unwrap_or_else(|e| { + panic!( + "could not deserialize input {} as hex in {test_name}: {e}", + &vector.input + ) + }); + let target_gas: u64 = 30_000_000; + let res = precompile(&input, target_gas); + if vector.error.unwrap_or_default() { + assert!(res.is_err(), "expected error didn't happen in {test_name}"); + } else { + let (actual_gas, actual_output) = + res.unwrap_or_else(|e| panic!("precompile call failed for {test_name}: {e}")); + assert_eq!( + vector.gas, actual_gas, + "expected gas: {}, actual gas: {} in {test_name}", + vector.gas, actual_gas + ); + let expected_output = Bytes::from_hex(vector.expected).unwrap(); + assert_eq!( + expected_output, actual_output, + "expected output: {expected_output}, actual output: {actual_output} in {test_name}"); + } + } + } + + #[rstest] + #[case::g1_empty(0, g1_mul::BASE_GAS_FEE, 0)] + #[case::g1_one_item(160, g1_mul::BASE_GAS_FEE, 14400)] + #[case::g1_two_items(320, g1_mul::BASE_GAS_FEE, 21312)] + #[case::g1_ten_items(1600, g1_mul::BASE_GAS_FEE, 50760)] + #[case::g1_sixty_four_items(10240, g1_mul::BASE_GAS_FEE, 170496)] + #[case::g1_one_hundred_twenty_eight_items(20480, g1_mul::BASE_GAS_FEE, 267264)] + #[case::g1_one_hundred_twenty_nine_items(20640, g1_mul::BASE_GAS_FEE, 269352)] + #[case::g1_two_hundred_fifty_six_items(40960, g1_mul::BASE_GAS_FEE, 534528)] + fn test_g1_msm_required_gas( + #[case] input_len: usize, + #[case] multiplication_cost: u64, + #[case] expected_output: u64, + ) { + let k = input_len / g1_mul::INPUT_LENGTH; + + let actual_output = msm_required_gas(k, multiplication_cost); + + assert_eq!(expected_output, actual_output); + } +} diff --git a/crates/precompile/src/bls12_381/g1.rs b/crates/precompile/src/bls12_381/g1.rs index 163afb3e5b..9d4f630dbf 100644 --- a/crates/precompile/src/bls12_381/g1.rs +++ b/crates/precompile/src/bls12_381/g1.rs @@ -1,5 +1,5 @@ use super::utils::{fp_to_bytes, remove_padding, PADDED_FP_LENGTH}; -use blst::{blst_fp_from_bendian, blst_p1_affine, blst_p1_affine_in_g1}; +use blst::{blst_fp_from_bendian, blst_p1_affine, blst_p1_affine_in_g1, blst_p1_affine_on_curve}; use revm_primitives::{Bytes, PrecompileError}; /// Length of each of the elements in a g1 operation input. @@ -19,7 +19,12 @@ pub(super) fn encode_g1_point(input: *const blst_p1_affine) -> Bytes { } /// Extracts a G1 point in Affine format from a 128 byte slice representation. -pub(super) fn extract_g1_input(input: &[u8]) -> Result { +/// +/// NOTE: This function will perform a G1 subgroup check if `subgroup_check` is set to `true`. +pub(super) fn extract_g1_input( + input: &[u8], + subgroup_check: bool, +) -> Result { if input.len() != G1_INPUT_ITEM_LENGTH { return Err(PrecompileError::Other(format!( "Input should be {G1_INPUT_ITEM_LENGTH} bytes, was {}", @@ -37,9 +42,41 @@ pub(super) fn extract_g1_input(input: &[u8]) -> Result -fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -33,8 +33,11 @@ fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { ))); } - let a_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH])?; - let b_aff = &extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..])?; + // NB: There is no subgroup check for the G1 addition precompile. + // + // So we set the subgroup checks here to `false` + let a_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], false)?; + let b_aff = &extract_g1_input(&input[G1_INPUT_ITEM_LENGTH..], false)?; let mut b = blst_p1::default(); // SAFETY: b and b_aff are blst values. diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index c02f055bb2..503a7b74f9 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 ADDRESS: u64 = 0x0d; /// Output is an encoding of multi-scalar-multiplication operation result - single G1 /// point (`128` bytes). /// See also: -fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % g1_mul::INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( @@ -41,8 +41,12 @@ fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { let mut g1_points: Vec = Vec::with_capacity(k); let mut scalars: Vec = Vec::with_capacity(k * SCALAR_LENGTH); for i in 0..k { + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. + // + // So we set the subgroup_check flag to `true` let p0_aff = &extract_g1_input( &input[i * g1_mul::INPUT_LENGTH..i * g1_mul::INPUT_LENGTH + G1_INPUT_ITEM_LENGTH], + true, )?; let mut p0 = blst_p1::default(); // SAFETY: p0 and p0_aff are blst values. diff --git a/crates/precompile/src/bls12_381/g1_mul.rs b/crates/precompile/src/bls12_381/g1_mul.rs index 8982cb5896..305458e236 100644 --- a/crates/precompile/src/bls12_381/g1_mul.rs +++ b/crates/precompile/src/bls12_381/g1_mul.rs @@ -23,7 +23,7 @@ pub(super) const INPUT_LENGTH: usize = 160; /// Output is an encoding of multiplication operation result - single G1 point /// (`128` bytes). /// See also: -pub fn g1_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn g1_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -34,7 +34,10 @@ pub fn g1_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { ))); } - let p0_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH])?; + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. + // + // So we set the subgroup_check flag to `true` + let p0_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], true)?; let mut p0 = blst_p1::default(); // SAFETY: p0 and p0_aff are blst values. unsafe { blst_p1_from_affine(&mut p0, p0_aff) }; diff --git a/crates/precompile/src/bls12_381/g2.rs b/crates/precompile/src/bls12_381/g2.rs index 538bc5beec..321fc5f69a 100644 --- a/crates/precompile/src/bls12_381/g2.rs +++ b/crates/precompile/src/bls12_381/g2.rs @@ -1,5 +1,5 @@ use super::utils::{fp_to_bytes, remove_padding, FP_LENGTH, PADDED_FP_LENGTH}; -use blst::{blst_fp_from_bendian, blst_p2_affine, blst_p2_affine_in_g2}; +use blst::{blst_fp_from_bendian, blst_p2_affine, blst_p2_affine_in_g2, blst_p2_affine_on_curve}; use revm_primitives::{Bytes, PrecompileError}; /// Length of each of the elements in a g2 operation input. @@ -27,7 +27,12 @@ pub(super) fn encode_g2_point(input: &blst_p2_affine) -> Bytes { } /// Extracts a G2 point in Affine format from a 256 byte slice representation. -pub(super) fn extract_g2_input(input: &[u8]) -> Result { +/// +/// NOTE: This function will perform a G2 subgroup check if `subgroup_check` is set to `true`. +pub(super) fn extract_g2_input( + input: &[u8], + subgroup_check: bool, +) -> Result { if input.len() != G2_INPUT_ITEM_LENGTH { return Err(PrecompileError::Other(format!( "Input should be {G2_INPUT_ITEM_LENGTH} bytes, was {}", @@ -49,9 +54,40 @@ pub(super) fn extract_g2_input(input: &[u8]) -> Result -fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -34,8 +34,11 @@ fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { ))); } - let a_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH])?; - let b_aff = &extract_g2_input(&input[G2_INPUT_ITEM_LENGTH..])?; + // NB: There is no subgroup check for the G2 addition precompile. + // + // So we set the subgroup checks here to `false` + let a_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH], false)?; + let b_aff = &extract_g2_input(&input[G2_INPUT_ITEM_LENGTH..], false)?; let mut b = blst_p2::default(); // SAFETY: b and b_aff are blst values. diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index a17c5c47de..0becd2b5db 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 ADDRESS: u64 = 0x10; /// Output is an encoding of multi-scalar-multiplication operation result - single G2 /// point (`256` bytes). /// See also: -fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % g2_mul::INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( @@ -41,9 +41,19 @@ fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { let mut g2_points: Vec = Vec::with_capacity(k); let mut scalars: Vec = Vec::with_capacity(k * SCALAR_LENGTH); for i in 0..k { - let p0_aff = &extract_g2_input( - &input[i * g2_mul::INPUT_LENGTH..i * g2_mul::INPUT_LENGTH + G2_INPUT_ITEM_LENGTH], - )?; + let slice = + &input[i * g2_mul::INPUT_LENGTH..i * g2_mul::INPUT_LENGTH + G2_INPUT_ITEM_LENGTH]; + // BLST batch API for p2_affines blows up when you pass it a point at infinity and returns point at infinity + // so we just skip the element, and return 256 bytes in the response + if slice.iter().all(|i| *i == 0) { + continue; + } + + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. + // + // So we set the subgroup_check flag to `true` + let p0_aff = &extract_g2_input(slice, true)?; + let mut p0 = blst_p2::default(); // SAFETY: p0 and p0_aff are blst values. unsafe { blst_p2_from_affine(&mut p0, p0_aff) }; @@ -59,6 +69,11 @@ fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { ); } + // return infinity point if all points are infinity + if g2_points.is_empty() { + return Ok((required_gas, vec![0; 256].into())); + } + let points = p2_affines::from(&g2_points); let multiexp = points.mult(&scalars, NBITS); diff --git a/crates/precompile/src/bls12_381/g2_mul.rs b/crates/precompile/src/bls12_381/g2_mul.rs index d7d6883b23..62cb903e9b 100644 --- a/crates/precompile/src/bls12_381/g2_mul.rs +++ b/crates/precompile/src/bls12_381/g2_mul.rs @@ -23,7 +23,7 @@ pub(super) const INPUT_LENGTH: usize = 288; /// Output is an encoding of multiplication operation result - single G2 point /// (`256` bytes). /// See also: -fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { return Err(PrecompileError::OutOfGas); } @@ -34,7 +34,10 @@ fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { ))); } - let p0_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH])?; + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. + // + // So we set the subgroup_check flag to `true` + let p0_aff = &extract_g2_input(&input[..G2_INPUT_ITEM_LENGTH], true)?; let mut p0 = blst_p2::default(); // SAFETY: p0 and p0_aff are blst values. unsafe { blst_p2_from_affine(&mut p0, p0_aff) }; 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 4615ffd862..51a90ac313 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -21,7 +21,7 @@ const BASE_GAS_FEE: u64 = 75000; /// an element of Fp2. Output of this call is 256 bytes and is an encoded G2 /// point. /// See also: -fn map_fp2_to_g2(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn map_fp2_to_g2(input: &Bytes, gas_limit: u64) -> PrecompileResult { if 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 b161f7d397..a6d9f48ecb 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -19,7 +19,7 @@ const MAP_FP_TO_G1_BASE: u64 = 5500; /// 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: -fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { if MAP_FP_TO_G1_BASE > gas_limit { return Err(PrecompileError::OutOfGas); } diff --git a/crates/precompile/src/bls12_381/mod.rs b/crates/precompile/src/bls12_381/mod.rs deleted file mode 100644 index 764c4a50a1..0000000000 --- a/crates/precompile/src/bls12_381/mod.rs +++ /dev/null @@ -1,31 +0,0 @@ -use crate::PrecompileWithAddress; - -mod g1; -pub mod g1_add; -pub mod g1_msm; -pub mod g1_mul; -mod g2; -pub mod g2_add; -pub mod g2_msm; -pub mod g2_mul; -pub mod map_fp2_to_g2; -pub mod map_fp_to_g1; -mod msm; -pub mod pairing; -mod utils; - -/// Returns the BLS12-381 precompiles with their addresses. -pub fn precompiles() -> impl Iterator { - [ - g1_add::PRECOMPILE, - g1_mul::PRECOMPILE, - g1_msm::PRECOMPILE, - g2_add::PRECOMPILE, - g2_mul::PRECOMPILE, - g2_msm::PRECOMPILE, - pairing::PRECOMPILE, - map_fp_to_g1::PRECOMPILE, - map_fp2_to_g2::PRECOMPILE, - ] - .into_iter() -} diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index fb83e44807..2a699a0859 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -29,7 +29,7 @@ const INPUT_LENGTH: usize = 384; /// is 0x01 if pairing result is equal to the multiplicative identity in a pairing /// target field and 0x00 otherwise. /// See also: -fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { +pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_len = input.len(); if input_len == 0 || input_len % INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( @@ -46,12 +46,21 @@ fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { // accumulator for the fp12 multiplications of the miller loops. let mut acc = blst_fp12::default(); for i in 0..k { - let p1_aff = - &extract_g1_input(&input[i * INPUT_LENGTH..i * INPUT_LENGTH + G1_INPUT_ITEM_LENGTH])?; + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. + // + // So we set the subgroup_check flag to `true` + let p1_aff = &extract_g1_input( + &input[i * INPUT_LENGTH..i * INPUT_LENGTH + G1_INPUT_ITEM_LENGTH], + true, + )?; + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. + // + // So we set the subgroup_check flag to `true` let p2_aff = &extract_g2_input( &input[i * INPUT_LENGTH + G1_INPUT_ITEM_LENGTH ..i * INPUT_LENGTH + G1_INPUT_ITEM_LENGTH + G2_INPUT_ITEM_LENGTH], + true, )?; if i > 0 { diff --git a/crates/precompile/test-vectors/add_G1_bls.json b/crates/precompile/test-vectors/add_G1_bls.json new file mode 100644 index 0000000000..a7f44dda86 --- /dev/null +++ b/crates/precompile/test-vectors/add_G1_bls.json @@ -0,0 +1,65 @@ +[ + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "Name": "bls_g1add_g1+p1", + "Expected": "000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a870025", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + "Name": "bls_g1add_p1+g1", + "Expected": "000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a870025", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000000000000000000000000000000193fb7cedb32b2c3adc06ec11a96bc0d661869316f5e4a577a9f7c179593987beb4fb2ee424dbb2f5dd891e228b46c4a0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + "Name": "bls_g1add_g1_wrong_order+g1", + "Expected": "000000000000000000000000000000000abe7ae4ae2b092a5cc1779b1f5605d904fa6ec59b0f084907d1f5e4d2663e117a3810e027210a72186159a21271df3e0000000000000000000000000000000001e1669f00e10205f2e2f1195d65c21022f6a9a6de21f329756309815281a4434b2864d34ebcbc1d7e7cfaaee3feeea2", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1add_(g1+0=g1)", + "Expected": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1add_(p1+0=p1)", + "Expected": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000000114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca", + "Name": "bls_g1add_(g1-g1=0)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca9426000000000000000000000000000000000195e911162921ba5ed055b496420f197693d36569ec34c63d7c0529a097d49e543070afba4b707e878e53c2b779208a", + "Name": "bls_g1add_(p1-p1=0)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + "Name": "bls_g1add_(g1+g1=2*g1)", + "Expected": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28", + "Gas": 500, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "Name": "bls_g1add_(p1+p1=2*p1)", + "Expected": "0000000000000000000000000000000015222cddbabdd764c4bee0b3720322a65ff4712c86fc4b1588d0c209210a0884fa9468e855d261c483091b2bf7de6a630000000000000000000000000000000009f9edb99bc3b75d7489735c98b16ab78b9386c5f7a1f76c7e96ac6eb5bbde30dbca31a74ec6e0f0b12229eecea33c39", + "Gas": 500, + "NoBenchmark": false + } +] diff --git a/crates/precompile/test-vectors/add_G2_bls.json b/crates/precompile/test-vectors/add_G2_bls.json new file mode 100644 index 0000000000..36a7614d3c --- /dev/null +++ b/crates/precompile/test-vectors/add_G2_bls.json @@ -0,0 +1,65 @@ +[ + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "Name": "bls_g2add_g2+p2", + "Expected": "000000000000000000000000000000000b54a8a7b08bd6827ed9a797de216b8c9057b3a9ca93e2f88e7f04f19accc42da90d883632b9ca4dc38d013f71ede4db00000000000000000000000000000000077eba4eecf0bd764dce8ed5f45040dd8f3b3427cb35230509482c14651713282946306247866dfe39a8e33016fcbe520000000000000000000000000000000014e60a76a29ef85cbd69f251b9f29147b67cfe3ed2823d3f9776b3a0efd2731941d47436dc6d2b58d9e65f8438bad073000000000000000000000000000000001586c3c910d95754fef7a732df78e279c3d37431c6a2b77e67a00c7c130a8fcd4d19f159cbeb997a178108fffffcbd20", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d87845100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Name": "bls_g2add_p2+g2", + "Expected": "000000000000000000000000000000000b54a8a7b08bd6827ed9a797de216b8c9057b3a9ca93e2f88e7f04f19accc42da90d883632b9ca4dc38d013f71ede4db00000000000000000000000000000000077eba4eecf0bd764dce8ed5f45040dd8f3b3427cb35230509482c14651713282946306247866dfe39a8e33016fcbe520000000000000000000000000000000014e60a76a29ef85cbd69f251b9f29147b67cfe3ed2823d3f9776b3a0efd2731941d47436dc6d2b58d9e65f8438bad073000000000000000000000000000000001586c3c910d95754fef7a732df78e279c3d37431c6a2b77e67a00c7c130a8fcd4d19f159cbeb997a178108fffffcbd20", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000197bfd0342bbc8bee2beced2f173e1a87be576379b343e93232d6cef98d84b1d696e5612ff283ce2cfdccb2cfb65fa0c00000000000000000000000000000000184e811f55e6f9d84d77d2f79102fd7ea7422f4759df5bf7f6331d550245e3f1bcf6a30e3b29110d85e0ca16f9f6ae7a000000000000000000000000000000000f10e1eb3c1e53d2ad9cf2d398b2dc22c5842fab0a74b174f691a7e914975da3564d835cd7d2982815b8ac57f507348f000000000000000000000000000000000767d1c453890f1b9110fda82f5815c27281aba3f026ee868e4176a0654feea41a96575e0c4d58a14dbfbcc05b5010b100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Name": "bls_g2add_g2_wrong_order+g2", + "Expected": "0000000000000000000000000000000011f00077935238fc57086414804303b20fab5880bc29f35ebda22c13dd44e586c8a889fe2ba799082c8458d861ac10cf0000000000000000000000000000000007318be09b19be000fe5df77f6e664a8286887ad8373005d7f7a203fcc458c28004042780146d3e43fa542d921c69512000000000000000000000000000000001287eab085d6f8a29f1f1aedb5ad9e8546963f0b11865e05454d86b9720c281db567682a233631f63a2794432a5596ae0000000000000000000000000000000012ec87cea1bacb75aa97728bcd64b27c7a42dd2319a2e17fe3837a05f85d089c5ebbfb73c1d08b7007e2b59ec9c8e065", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g2add_(g2+0=g2)", + "Expected": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d87845100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g2add_(p2+0=p2)", + "Expected": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "Name": "bls_g2add_(g2-g2=0)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d87845100000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000a6296409115572426717c73668335a949829d739cff2cb4ab043710d28f8e772f6ef41aac4806c9cb273c490384032d000000000000000000000000000000000cde4e850c721fa94e8890d500e3655b442d5c0dc4fff1b694c6f8dd68f6d8dc1bc3251a37d27e7af96f65a96278265a", + "Name": "bls_g2add_(p2-p2=0)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Name": "bls_g2add_(g2+g2=2*g2)", + "Expected": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3", + "Gas": 800, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d87845100000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "Name": "bls_g2add_(p2+p2=2*p2)", + "Expected": "000000000000000000000000000000000b76fcbb604082a4f2d19858a7befd6053fa181c5119a612dfec83832537f644e02454f2b70d40985ebb08042d1620d40000000000000000000000000000000019a4a02c0ae51365d964c73be7babb719db1c69e0ddbf9a8a335b5bed3b0a4b070d2d5df01d2da4a3f1e56aae2ec106d000000000000000000000000000000000d18322f821ac72d3ca92f92b000483cf5b7d9e5d06873a44071c4e7e81efd904f210208fe0b9b4824f01c65bc7e62080000000000000000000000000000000004e563d53609a2d1e216aaaee5fbc14ef460160db8d1fdc5e1bd4e8b54cd2f39abf6f925969fa405efb9e700b01c7085", + "Gas": 800, + "NoBenchmark": false + } +] diff --git a/crates/precompile/test-vectors/map_fp2_to_G2_bls.json b/crates/precompile/test-vectors/map_fp2_to_G2_bls.json new file mode 100644 index 0000000000..fa96b288df --- /dev/null +++ b/crates/precompile/test-vectors/map_fp2_to_G2_bls.json @@ -0,0 +1,37 @@ +[ + { + "Input": "0000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c", + "Name": "bls_g2map_", + "Expected": "0000000000000000000000000000000000e7f4568a82b4b7dc1f14c6aaa055edf51502319c723c4dc2688c7fe5944c213f510328082396515734b6612c4e7bb700000000000000000000000000000000126b855e9e69b1f691f816e48ac6977664d24d99f8724868a184186469ddfd4617367e94527d4b74fc86413483afb35b000000000000000000000000000000000caead0fd7b6176c01436833c79d305c78be307da5f6af6c133c47311def6ff1e0babf57a0fb5539fce7ee12407b0a42000000000000000000000000000000001498aadcf7ae2b345243e281ae076df6de84455d766ab6fcdaad71fab60abb2e8b980a440043cd305db09d283c895e3d", + "Gas": 75000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000138879a9559e24cecee8697b8b4ad32cced053138ab913b99872772dc753a2967ed50aabc907937aefb2439ba06cc50c000000000000000000000000000000000a1ae7999ea9bab1dcc9ef8887a6cb6e8f1e22566015428d220b7eec90ffa70ad1f624018a9ad11e78d588bd3617f9f2", + "Name": "bls_g2map_616263", + "Expected": "00000000000000000000000000000000108ed59fd9fae381abfd1d6bce2fd2fa220990f0f837fa30e0f27914ed6e1454db0d1ee957b219f61da6ff8be0d6441f000000000000000000000000000000000296238ea82c6d4adb3c838ee3cb2346049c90b96d602d7bb1b469b905c9228be25c627bffee872def773d5b2a2eb57d00000000000000000000000000000000033f90f6057aadacae7963b0a0b379dd46750c1c94a6357c99b65f63b79e321ff50fe3053330911c56b6ceea08fee65600000000000000000000000000000000153606c417e59fb331b7ae6bce4fbf7c5190c33ce9402b5ebe2b70e44fca614f3f1382a3625ed5493843d0b0a652fc3f", + "Gas": 75000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000018c16fe362b7dbdfa102e42bdfd3e2f4e6191d479437a59db4eb716986bf08ee1f42634db66bde97d6c16bbfd342b3b8000000000000000000000000000000000e37812ce1b146d998d5f92bdd5ada2a31bfd63dfe18311aa91637b5f279dd045763166aa1615e46a50d8d8f475f184e", + "Name": "bls_g2map_6162636465663031", + "Expected": "00000000000000000000000000000000038af300ef34c7759a6caaa4e69363cafeed218a1f207e93b2c70d91a1263d375d6730bd6b6509dcac3ba5b567e85bf3000000000000000000000000000000000da75be60fb6aa0e9e3143e40c42796edf15685cafe0279afd2a67c3dff1c82341f17effd402e4f1af240ea90f4b659b0000000000000000000000000000000019b148cbdf163cf0894f29660d2e7bfb2b68e37d54cc83fd4e6e62c020eaa48709302ef8e746736c0e19342cc1ce3df4000000000000000000000000000000000492f4fed741b073e5a82580f7c663f9b79e036b70ab3e51162359cec4e77c78086fe879b65ca7a47d34374c8315ac5e", + "Gas": 75000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000008d4a0997b9d52fecf99427abb721f0fa779479963315fe21c6445250de7183e3f63bfdf86570da8929489e421d4ee950000000000000000000000000000000016cb4ccad91ec95aab070f22043916cd6a59c4ca94097f7f510043d48515526dc8eaaea27e586f09151ae613688d5a89", + "Name": "bls_g2map_713132385f717171", + "Expected": "000000000000000000000000000000000c5ae723be00e6c3f0efe184fdc0702b64588fe77dda152ab13099a3bacd3876767fa7bbad6d6fd90b3642e902b208f90000000000000000000000000000000012c8c05c1d5fc7bfa847f4d7d81e294e66b9a78bc9953990c358945e1f042eedafce608b67fdd3ab0cb2e6e263b9b1ad0000000000000000000000000000000004e77ddb3ede41b5ec4396b7421dd916efc68a358a0d7425bddd253547f2fb4830522358491827265dfc5bcc1928a5690000000000000000000000000000000011c624c56dbe154d759d021eec60fab3d8b852395a89de497e48504366feedd4662d023af447d66926a28076813dd646", + "Gas": 75000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000003f80ce4ff0ca2f576d797a3660e3f65b274285c054feccc3215c879e2c0589d376e83ede13f93c32f05da0f68fd6a1000000000000000000000000000000000006488a837c5413746d868d1efb7232724da10eca410b07d8b505b9363bdccf0a1fc0029bad07d65b15ccfe6dd25e20d", + "Name": "bls_g2map_613531325f616161", + "Expected": "000000000000000000000000000000000ea4e7c33d43e17cc516a72f76437c4bf81d8f4eac69ac355d3bf9b71b8138d55dc10fd458be115afa798b55dac34be1000000000000000000000000000000001565c2f625032d232f13121d3cfb476f45275c303a037faa255f9da62000c2c864ea881e2bcddd111edc4a3c0da3e88d00000000000000000000000000000000043b6f5fe4e52c839148dc66f2b3751e69a0f6ebb3d056d6465d50d4108543ecd956e10fa1640dfd9bc0030cc2558d28000000000000000000000000000000000f8991d2a1ad662e7b6f58ab787947f1fa607fce12dde171bc17903b012091b657e15333e11701edcf5b63ba2a561247", + "Gas": 75000, + "NoBenchmark": false + } +] diff --git a/crates/precompile/test-vectors/map_fp_to_G1_bls.json b/crates/precompile/test-vectors/map_fp_to_G1_bls.json new file mode 100644 index 0000000000..80ca454d82 --- /dev/null +++ b/crates/precompile/test-vectors/map_fp_to_G1_bls.json @@ -0,0 +1,37 @@ +[ + { + "Input": "00000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f03", + "Name": "bls_g1map_", + "Expected": "00000000000000000000000000000000184bb665c37ff561a89ec2122dd343f20e0f4cbcaec84e3c3052ea81d1834e192c426074b02ed3dca4e7676ce4ce48ba0000000000000000000000000000000004407b8d35af4dacc809927071fc0405218f1401a6d15af775810e4e460064bcc9468beeba82fdc751be70476c888bf3", + "Gas": 5500, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000147e1ed29f06e4c5079b9d14fc89d2820d32419b990c1c7bb7dbea2a36a045124b31ffbde7c99329c05c559af1c6cc82", + "Name": "bls_g1map_616263", + "Expected": "00000000000000000000000000000000009769f3ab59bfd551d53a5f846b9984c59b97d6842b20a2c565baa167945e3d026a3755b6345df8ec7e6acb6868ae6d000000000000000000000000000000001532c00cf61aa3d0ce3e5aa20c3b531a2abd2c770a790a2613818303c6b830ffc0ecf6c357af3317b9575c567f11cd2c", + "Gas": 5500, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000004090815ad598a06897dd89bcda860f25837d54e897298ce31e6947378134d3761dc59a572154963e8c954919ecfa82d", + "Name": "bls_g1map_6162636465663031", + "Expected": "000000000000000000000000000000001974dbb8e6b5d20b84df7e625e2fbfecb2cdb5f77d5eae5fb2955e5ce7313cae8364bc2fff520a6c25619739c6bdcb6a0000000000000000000000000000000015f9897e11c6441eaa676de141c8d83c37aab8667173cbe1dfd6de74d11861b961dccebcd9d289ac633455dfcc7013a3", + "Gas": 5500, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000008dccd088ca55b8bfbc96fb50bb25c592faa867a8bb78d4e94a8cc2c92306190244532e91feba2b7fed977e3c3bb5a1f", + "Name": "bls_g1map_713132385f717171", + "Expected": "000000000000000000000000000000000a7a047c4a8397b3446450642c2ac64d7239b61872c9ae7a59707a8f4f950f101e766afe58223b3bff3a19a7f754027c000000000000000000000000000000001383aebba1e4327ccff7cf9912bda0dbc77de048b71ef8c8a81111d71dc33c5e3aa6edee9cf6f5fe525d50cc50b77cc9", + "Gas": 5500, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000dd824886d2123a96447f6c56e3a3fa992fbfefdba17b6673f9f630ff19e4d326529db37e1c1be43f905bf9202e0278d", + "Name": "bls_g1map_613531325f616161", + "Expected": "000000000000000000000000000000000e7a16a975904f131682edbb03d9560d3e48214c9986bd50417a77108d13dc957500edf96462a3d01e62dc6cd468ef11000000000000000000000000000000000ae89e677711d05c30a48d6d75e76ca9fb70fe06c6dd6ff988683d89ccde29ac7d46c53bb97a59b1901abf1db66052db", + "Gas": 5500, + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/mul_G1_bls.json b/crates/precompile/test-vectors/mul_G1_bls.json new file mode 100644 index 0000000000..e67f76f986 --- /dev/null +++ b/crates/precompile/test-vectors/mul_G1_bls.json @@ -0,0 +1,79 @@ +[ + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g1mul_(g1+g1=2*g1)", + "Expected": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g1mul_(p1+p1=2*p1)", + "Expected": "0000000000000000000000000000000015222cddbabdd764c4bee0b3720322a65ff4712c86fc4b1588d0c209210a0884fa9468e855d261c483091b2bf7de6a630000000000000000000000000000000009f9edb99bc3b75d7489735c98b16ab78b9386c5f7a1f76c7e96ac6eb5bbde30dbca31a74ec6e0f0b12229eecea33c39", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g1mul_(1*g1=g1)", + "Expected": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g1mul_(1*p1=p1)", + "Expected": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1mul_(0*g1=inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1mul_(0*p1=inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", + "Name": "bls_g1mul_(x*inf=inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", + "Name": "bls_g1mul_random*g1", + "Expected": "000000000000000000000000000000000491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a0000000000000000000000000000000017cd7061575d3e8034fcea62adaa1a3bc38dca4b50e4c5c01d04dd78037c9cee914e17944ea99e7ad84278e5d49f36c4", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", + "Name": "bls_g1mul_random*p1", + "Expected": "0000000000000000000000000000000006ee9c9331228753bcb148d0ca8623447701bb0aa6eafb0340aa7f81543923474e00f2a225de65c62dd1d8303270220c0000000000000000000000000000000018dd7be47eb4e80985d7a0d2cc96c8b004250b36a5c3ec0217705d453d3ecc6d0d3d1588722da51b40728baba1e93804", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e19a2b64cc58f8992cb21237914262ca9ada6cb13dc7b7d3f11c278fe0462040e4", + "Name": "bls_g1mul_random*g1_unnormalized_scalar", + "Expected": "000000000000000000000000000000000491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a0000000000000000000000000000000017cd7061575d3e8034fcea62adaa1a3bc38dca4b50e4c5c01d04dd78037c9cee914e17944ea99e7ad84278e5d49f36c4", + "Gas": 12000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a219a2b64cc58f8992cb21237914262ca9ada6cb13dc7b7d3f11c278fe0462040e4", + "Name": "bls_g1mul_random*p1_unnormalized_scalar", + "Expected": "0000000000000000000000000000000006ee9c9331228753bcb148d0ca8623447701bb0aa6eafb0340aa7f81543923474e00f2a225de65c62dd1d8303270220c0000000000000000000000000000000018dd7be47eb4e80985d7a0d2cc96c8b004250b36a5c3ec0217705d453d3ecc6d0d3d1588722da51b40728baba1e93804", + "Gas": 12000, + "NoBenchmark": false + } +] diff --git a/crates/precompile/test-vectors/mul_G2_bls.json b/crates/precompile/test-vectors/mul_G2_bls.json new file mode 100644 index 0000000000..1d41f3da52 --- /dev/null +++ b/crates/precompile/test-vectors/mul_G2_bls.json @@ -0,0 +1,79 @@ +[ + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2mul_(g2+g2=2*g2)", + "Expected": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2mul_(p2+p2=2*p2)", + "Expected": "000000000000000000000000000000000b76fcbb604082a4f2d19858a7befd6053fa181c5119a612dfec83832537f644e02454f2b70d40985ebb08042d1620d40000000000000000000000000000000019a4a02c0ae51365d964c73be7babb719db1c69e0ddbf9a8a335b5bed3b0a4b070d2d5df01d2da4a3f1e56aae2ec106d000000000000000000000000000000000d18322f821ac72d3ca92f92b000483cf5b7d9e5d06873a44071c4e7e81efd904f210208fe0b9b4824f01c65bc7e62080000000000000000000000000000000004e563d53609a2d1e216aaaee5fbc14ef460160db8d1fdc5e1bd4e8b54cd2f39abf6f925969fa405efb9e700b01c7085", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g2mul_(1*g2=g2)", + "Expected": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g2mul_(1*p2=p2)", + "Expected": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g2mul_(0*g2=inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g2mul_(0*p2=inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", + "Name": "bls_g2mul_(x*inf=inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", + "Name": "bls_g2mul_random*g2", + "Expected": "0000000000000000000000000000000014856c22d8cdb2967c720e963eedc999e738373b14172f06fc915769d3cc5ab7ae0a1b9c38f48b5585fb09d4bd2733bb000000000000000000000000000000000c400b70f6f8cd35648f5c126cce5417f3be4d8eefbd42ceb4286a14df7e03135313fe5845e3a575faab3e8b949d248800000000000000000000000000000000149a0aacc34beba2beb2f2a19a440166e76e373194714f108e4ab1c3fd331e80f4e73e6b9ea65fe3ec96d7136de81544000000000000000000000000000000000e4622fef26bdb9b1e8ef6591a7cc99f5b73164500c1ee224b6a761e676b8799b09a3fd4fa7e242645cc1a34708285e4", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e3", + "Name": "bls_g2mul_random*p2", + "Expected": "00000000000000000000000000000000036074dcbbd0e987531bfe0e45ddfbe09fd015665990ee0c352e8e403fe6af971d8f42141970d9ab14b4dd04874409e600000000000000000000000000000000019705637f24ba2f398f32c3a3e20d6a1cd0fd63e6f8f071cf603a8334f255744927e7bfdfdb18519e019c49ff6e914500000000000000000000000000000000008e74fcff4c4278c9accfb60809ed69bbcbe3d6213ef2304e078d15ec7d6decb4f462b24b8e7cc38cc11b6f2c9e0486000000000000000000000000000000001331d40100f38c1070afd832445881b47cf4d63894666d9907c85ac66604aab5ad329980938cc3c167ccc5b6bc1b8f30", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be9a2b64cc58f8992cb21237914262ca9ada6cb13dc7b7d3f11c278fe0462040e4", + "Name": "bls_g2mul_random*g2_unnormalized_scalar", + "Expected": "0000000000000000000000000000000014856c22d8cdb2967c720e963eedc999e738373b14172f06fc915769d3cc5ab7ae0a1b9c38f48b5585fb09d4bd2733bb000000000000000000000000000000000c400b70f6f8cd35648f5c126cce5417f3be4d8eefbd42ceb4286a14df7e03135313fe5845e3a575faab3e8b949d248800000000000000000000000000000000149a0aacc34beba2beb2f2a19a440166e76e373194714f108e4ab1c3fd331e80f4e73e6b9ea65fe3ec96d7136de81544000000000000000000000000000000000e4622fef26bdb9b1e8ef6591a7cc99f5b73164500c1ee224b6a761e676b8799b09a3fd4fa7e242645cc1a34708285e4", + "Gas": 45000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784519a2b64cc58f8992cb21237914262ca9ada6cb13dc7b7d3f11c278fe0462040e4", + "Name": "bls_g2mul_random*p2_unnormalized_scalar", + "Expected": "00000000000000000000000000000000036074dcbbd0e987531bfe0e45ddfbe09fd015665990ee0c352e8e403fe6af971d8f42141970d9ab14b4dd04874409e600000000000000000000000000000000019705637f24ba2f398f32c3a3e20d6a1cd0fd63e6f8f071cf603a8334f255744927e7bfdfdb18519e019c49ff6e914500000000000000000000000000000000008e74fcff4c4278c9accfb60809ed69bbcbe3d6213ef2304e078d15ec7d6decb4f462b24b8e7cc38cc11b6f2c9e0486000000000000000000000000000000001331d40100f38c1070afd832445881b47cf4d63894666d9907c85ac66604aab5ad329980938cc3c167ccc5b6bc1b8f30", + "Gas": 45000, + "NoBenchmark": false + } +] diff --git a/crates/precompile/test-vectors/multiexp_G1_bls.json b/crates/precompile/test-vectors/multiexp_G1_bls.json new file mode 100644 index 0000000000..0a1373782f --- /dev/null +++ b/crates/precompile/test-vectors/multiexp_G1_bls.json @@ -0,0 +1,79 @@ +[ + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g1multiexp_(g1+g1=2*g1)", + "Expected": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g1multiexp_(p1+p1=2*p1)", + "Expected": "0000000000000000000000000000000015222cddbabdd764c4bee0b3720322a65ff4712c86fc4b1588d0c209210a0884fa9468e855d261c483091b2bf7de6a630000000000000000000000000000000009f9edb99bc3b75d7489735c98b16ab78b9386c5f7a1f76c7e96ac6eb5bbde30dbca31a74ec6e0f0b12229eecea33c39", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g1multiexp_(1*g1=g1)", + "Expected": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g1multiexp_(1*p1=p1)", + "Expected": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1multiexp_(0*g1=inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1multiexp_(0*p1=inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", + "Name": "bls_g1multiexp_(x*inf=inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 14400, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1multiexp_(2g1+inf)", + "Expected": "000000000000000000000000000000000572cbea904d67468808c8eb50a9450c9721db309128012543902d0ac358a62ae28f75bb8f1c7c42c39a8c5529bf0f4e00000000000000000000000000000000166a9d8cabc673a322fda673779d8e3822ba3ecb8670e461f73bb9021d5fd76a4c56d9d4cd16bd1bba86881979749d28", + "Gas": 21312, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1multiexp_(inf+inf)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 21312, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g1multiexp_(2g1+2p1)", + "Expected": "00000000000000000000000000000000148f92dced907361b4782ab542a75281d4b6f71f65c8abf94a5a9082388c64662d30fd6a01ced724feef3e284752038c0000000000000000000000000000000015c3634c3b67bc18e19150e12bfd8a1769306ed010f59be645a0823acb5b38f39e8e0d86e59b6353fdafc59ca971b769", + "Gas": 21312, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e300000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2147b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff66513800000000000000000000000000000000184bb665c37ff561a89ec2122dd343f20e0f4cbcaec84e3c3052ea81d1834e192c426074b02ed3dca4e7676ce4ce48ba0000000000000000000000000000000004407b8d35af4dacc809927071fc0405218f1401a6d15af775810e4e460064bcc9468beeba82fdc751be70476c888bf3328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d21600000000000000000000000000000000009769f3ab59bfd551d53a5f846b9984c59b97d6842b20a2c565baa167945e3d026a3755b6345df8ec7e6acb6868ae6d000000000000000000000000000000001532c00cf61aa3d0ce3e5aa20c3b531a2abd2c770a790a2613818303c6b830ffc0ecf6c357af3317b9575c567f11cd2c263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e2000000000000000000000000000000001974dbb8e6b5d20b84df7e625e2fbfecb2cdb5f77d5eae5fb2955e5ce7313cae8364bc2fff520a6c25619739c6bdcb6a0000000000000000000000000000000015f9897e11c6441eaa676de141c8d83c37aab8667173cbe1dfd6de74d11861b961dccebcd9d289ac633455dfcc7013a347b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665131000000000000000000000000000000000a7a047c4a8397b3446450642c2ac64d7239b61872c9ae7a59707a8f4f950f101e766afe58223b3bff3a19a7f754027c000000000000000000000000000000001383aebba1e4327ccff7cf9912bda0dbc77de048b71ef8c8a81111d71dc33c5e3aa6edee9cf6f5fe525d50cc50b77cc9328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d211000000000000000000000000000000000e7a16a975904f131682edbb03d9560d3e48214c9986bd50417a77108d13dc957500edf96462a3d01e62dc6cd468ef11000000000000000000000000000000000ae89e677711d05c30a48d6d75e76ca9fb70fe06c6dd6ff988683d89ccde29ac7d46c53bb97a59b1901abf1db66052db55b53c4669f19f0fc7431929bc0363d7d8fb432435fcde2635fdba334424e9f5", + "Name": "bls_g1multiexp_multiple", + "Expected": "00000000000000000000000000000000053fbdb09b6b5faa08bfe7b7069454247ad4d8bd57e90e2d2ebaa04003dcf110aa83072c07f480ab2107cca2ccff6091000000000000000000000000000000001654537b7c96fe64d13906066679c3d45808cb666452b55d1b909c230cc4b423c3f932c58754b9b762dc49fcc825522c", + "Gas": 42000, + "NoBenchmark": false + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/multiexp_G2_bls.json b/crates/precompile/test-vectors/multiexp_G2_bls.json new file mode 100644 index 0000000000..fdf50e0fce --- /dev/null +++ b/crates/precompile/test-vectors/multiexp_G2_bls.json @@ -0,0 +1,86 @@ +[ + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2multiexp_(g2+g2=2*g2)", + "Expected": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2multiexp_(p2+p2=2*p2)", + "Expected": "000000000000000000000000000000000b76fcbb604082a4f2d19858a7befd6053fa181c5119a612dfec83832537f644e02454f2b70d40985ebb08042d1620d40000000000000000000000000000000019a4a02c0ae51365d964c73be7babb719db1c69e0ddbf9a8a335b5bed3b0a4b070d2d5df01d2da4a3f1e56aae2ec106d000000000000000000000000000000000d18322f821ac72d3ca92f92b000483cf5b7d9e5d06873a44071c4e7e81efd904f210208fe0b9b4824f01c65bc7e62080000000000000000000000000000000004e563d53609a2d1e216aaaee5fbc14ef460160db8d1fdc5e1bd4e8b54cd2f39abf6f925969fa405efb9e700b01c7085", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g2multiexp_(1*g2=g2)", + "Expected": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000001", + "Name": "bls_g2multiexp_(1*p2=p2)", + "Expected": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g2multiexp_(0*g2=inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g2multiexp_(0*p2=inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011", + "Name": "bls_g2multiexp_(x*inf=inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 54000, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2multiexp_(2g2+inf)", + "Expected": "000000000000000000000000000000001638533957d540a9d2370f17cc7ed5863bc0b995b8825e0ee1ea1e1e4d00dbae81f14b0bf3611b78c952aacab827a053000000000000000000000000000000000a4edef9c1ed7f729f520e47730a124fd70662a904ba1074728114d1031e1572c6c886f6b57ec72a6178288c47c33577000000000000000000000000000000000468fb440d82b0630aeb8dca2b5256789a66da69bf91009cbfe6bd221e47aa8ae88dece9764bf3bd999d95d71e4c9899000000000000000000000000000000000f6d4552fa65dd2638b361543f887136a43253d9c66c411697003f7a13c308f5422e1aa0a59c8967acdefd8b6e36ccf3", + "Gas": 79920, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2multiexp_(2p2+inf)", + "Expected": "000000000000000000000000000000000b76fcbb604082a4f2d19858a7befd6053fa181c5119a612dfec83832537f644e02454f2b70d40985ebb08042d1620d40000000000000000000000000000000019a4a02c0ae51365d964c73be7babb719db1c69e0ddbf9a8a335b5bed3b0a4b070d2d5df01d2da4a3f1e56aae2ec106d000000000000000000000000000000000d18322f821ac72d3ca92f92b000483cf5b7d9e5d06873a44071c4e7e81efd904f210208fe0b9b4824f01c65bc7e62080000000000000000000000000000000004e563d53609a2d1e216aaaee5fbc14ef460160db8d1fdc5e1bd4e8b54cd2f39abf6f925969fa405efb9e700b01c7085", + "Gas": 79920, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000000", + "Name": "bls_g1multiexp_(inf+inf)", + "Expected": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "Gas": 79920, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "Name": "bls_g2multiexp_(2g2+2p2)", + "Expected": "00000000000000000000000000000000009cc9ed6635623ba19b340cbc1b0eb05c3a58770623986bb7e041645175b0a38d663d929afb9a949f7524656043bccc000000000000000000000000000000000c0fb19d3f083fd5641d22a861a11979da258003f888c59c33005cb4a2df4df9e5a2868832063ac289dfa3e997f21f8a00000000000000000000000000000000168bf7d87cef37cf1707849e0a6708cb856846f5392d205ae7418dd94d94ef6c8aa5b424af2e99d957567654b9dae1d90000000000000000000000000000000017e0fa3c3b2665d52c26c7d4cea9f35443f4f9007840384163d3aa3c7d4d18b21b65ff4380cf3f3b48e94b5eecb221dd", + "Gas": 79920, + "NoBenchmark": false + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e300000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d87845147b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff66513800000000000000000000000000000000108ed59fd9fae381abfd1d6bce2fd2fa220990f0f837fa30e0f27914ed6e1454db0d1ee957b219f61da6ff8be0d6441f000000000000000000000000000000000296238ea82c6d4adb3c838ee3cb2346049c90b96d602d7bb1b469b905c9228be25c627bffee872def773d5b2a2eb57d00000000000000000000000000000000033f90f6057aadacae7963b0a0b379dd46750c1c94a6357c99b65f63b79e321ff50fe3053330911c56b6ceea08fee65600000000000000000000000000000000153606c417e59fb331b7ae6bce4fbf7c5190c33ce9402b5ebe2b70e44fca614f3f1382a3625ed5493843d0b0a652fc3f328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d21600000000000000000000000000000000038af300ef34c7759a6caaa4e69363cafeed218a1f207e93b2c70d91a1263d375d6730bd6b6509dcac3ba5b567e85bf3000000000000000000000000000000000da75be60fb6aa0e9e3143e40c42796edf15685cafe0279afd2a67c3dff1c82341f17effd402e4f1af240ea90f4b659b0000000000000000000000000000000019b148cbdf163cf0894f29660d2e7bfb2b68e37d54cc83fd4e6e62c020eaa48709302ef8e746736c0e19342cc1ce3df4000000000000000000000000000000000492f4fed741b073e5a82580f7c663f9b79e036b70ab3e51162359cec4e77c78086fe879b65ca7a47d34374c8315ac5e263dbd792f5b1be47ed85f8938c0f29586af0d3ac7b977f21c278fe1462040e2000000000000000000000000000000000c5ae723be00e6c3f0efe184fdc0702b64588fe77dda152ab13099a3bacd3876767fa7bbad6d6fd90b3642e902b208f90000000000000000000000000000000012c8c05c1d5fc7bfa847f4d7d81e294e66b9a78bc9953990c358945e1f042eedafce608b67fdd3ab0cb2e6e263b9b1ad0000000000000000000000000000000004e77ddb3ede41b5ec4396b7421dd916efc68a358a0d7425bddd253547f2fb4830522358491827265dfc5bcc1928a5690000000000000000000000000000000011c624c56dbe154d759d021eec60fab3d8b852395a89de497e48504366feedd4662d023af447d66926a28076813dd64647b8192d77bf871b62e87859d653922725724a5c031afeabc60bcef5ff665131000000000000000000000000000000000ea4e7c33d43e17cc516a72f76437c4bf81d8f4eac69ac355d3bf9b71b8138d55dc10fd458be115afa798b55dac34be1000000000000000000000000000000001565c2f625032d232f13121d3cfb476f45275c303a037faa255f9da62000c2c864ea881e2bcddd111edc4a3c0da3e88d00000000000000000000000000000000043b6f5fe4e52c839148dc66f2b3751e69a0f6ebb3d056d6465d50d4108543ecd956e10fa1640dfd9bc0030cc2558d28000000000000000000000000000000000f8991d2a1ad662e7b6f58ab787947f1fa607fce12dde171bc17903b012091b657e15333e11701edcf5b63ba2a561247328388aff0d4a5b7dc9205abd374e7e98f3cd9f3418edb4eafda5fb16473d211", + "Name": "bls_g2multiexp_multiple", + "Expected": "0000000000000000000000000000000016cf5fd2c2f1b2e01cc48a6d03e8e6d7f3ad754d6c7d4000f806c18c28d8d559cf529dd159c74946a7713d1906894718000000000000000000000000000000000628d42142df8d620d1f3709ac01f382ba950eaf14c12863885af5838067deec4bb363ffda427fcbdd2b8ec6cc5784ae0000000000000000000000000000000018168dec2441ef462e9a769c782f81acdc7fa49dffebb996764ba9fa96b9200ceb5edd9e96b33c383bd042b4e6af191a000000000000000000000000000000001065aaea2c4aa1d2bee7f1e82a2138ae7016dbbade8383ad912d81eca5fb260086238f95f8cef8f2f491969d4cefa2c3", + "Gas": 147690, + "NoBenchmark": false + } +] diff --git a/crates/precompile/test-vectors/pairing_check_bls.json b/crates/precompile/test-vectors/pairing_check_bls.json new file mode 100644 index 0000000000..a74d848920 --- /dev/null +++ b/crates/precompile/test-vectors/pairing_check_bls.json @@ -0,0 +1,44 @@ +[ + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Name": "bls_pairing_e(G1,0)=e(0,G2)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 151000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be", + "Name": "bls_pairing_non-degeneracy", + "Expected": "0000000000000000000000000000000000000000000000000000000000000000", + "Gas": 108000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000a40300ce2dec9888b60690e9a41d3004fda4886854573974fab73b046d3147ba5b7a5bde85279ffede1b45b3918d82d0000000000000000000000000000000006d3d887e9f53b9ec4eb6cedf5607226754b07c01ace7834f57f3e7315faefb739e59018e22c492006190fba4a87002500000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "Name": "bls_pairing_bilinearity", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 194000, + "NoBenchmark": false + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "Name": "bls_pairing_e(G1,-G2)=e(-G1,G2)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 151000, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a0000000000000000000000000000000017cd7061575d3e8034fcea62adaa1a3bc38dca4b50e4c5c01d04dd78037c9cee914e17944ea99e7ad84278e5d49f36c4000000000000000000000000000000000bc2357c6782bbb6a078d9e171fc7a81f7bd8ca73eb485e76317359908bb09bd372fd362a637512a9d48019b383e54890000000000000000000000000000000004b8f49c3bac0247a09487049492b0ed99cf90c56263141daa35f011330d3ced3f3ad78d252c51a3bb42fc7d8f182594000000000000000000000000000000000982d17b17404ac198a0ff5f2dffa56a328d95ec4732d9cca9da420ec7cf716dc63d56d0f5179a8b1ec71fe0328fe88200000000000000000000000000000000147c92cb19e43943bb20c5360a6c4347411eb8ffb3d6f19cc428a8dc0cb3fd1eb3ad02b1c21e21c78f65a7691ee63de90000000000000000000000000000000016cae74dc6523e5273dbd2d9d25c53f1e2c453e6d9ba3f605021cfb514fa0bdf721b05f2200f32591d733e739fabf438000000000000000000000000000000001405df65fb71b738510b3a2fc31c33ef3d884ccc84efb1017341a368bf40727b7ad8cdc8e3fd6b0eb94102488c5cb77000000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "Name": "bls_pairing_e(aG1,bG2)=e(abG1,G2)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 151000, + "NoBenchmark": false + }, + { + "Input": "000000000000000000000000000000000491d1b0ecd9bb917989f0e74f0dea0422eac4a873e5e2644f368dffb9a6e20fd6e10c1b77654d067c0618f6e5a7f79a0000000000000000000000000000000017cd7061575d3e8034fcea62adaa1a3bc38dca4b50e4c5c01d04dd78037c9cee914e17944ea99e7ad84278e5d49f36c4000000000000000000000000000000000bc2357c6782bbb6a078d9e171fc7a81f7bd8ca73eb485e76317359908bb09bd372fd362a637512a9d48019b383e54890000000000000000000000000000000004b8f49c3bac0247a09487049492b0ed99cf90c56263141daa35f011330d3ced3f3ad78d252c51a3bb42fc7d8f182594000000000000000000000000000000000982d17b17404ac198a0ff5f2dffa56a328d95ec4732d9cca9da420ec7cf716dc63d56d0f5179a8b1ec71fe0328fe88200000000000000000000000000000000147c92cb19e43943bb20c5360a6c4347411eb8ffb3d6f19cc428a8dc0cb3fd1eb3ad02b1c21e21c78f65a7691ee63de90000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000000114d1d6855d545a8aa7d76c8cf2e21f267816aef1db507c96655b9d5caac42364e6f38ba0ecb751bad54dcd6b939c2ca00000000000000000000000000000000166335679f3b3e2617b70c22c48e820e2c6a35149c4f96293035c1494a1ce4591f7a44bce94e9d76def50a71c9e7fa41000000000000000000000000000000000ef11c636091748476331159c8259c064da712ffec033c89299384b4c11b801893026726d992aacdc8e0a28db1a3ab82000000000000000000000000000000000fd8d4944030f480f44ce0d2d4fb67ff6264d30a0f3193cc218b062e5114cf9e4ce847489f7be94b0d4a9fc0c550fdc60000000000000000000000000000000000edba2c166be3d673ea77016163ae5cdf7b3c9bd480e733eb5c08a5f1c798793d339cb503005f5a9e586ea5aabf9695", + "Name": "bls_pairing_e(aG1,bG2)=e(G1,abG2)", + "Expected": "0000000000000000000000000000000000000000000000000000000000000001", + "Gas": 151000, + "NoBenchmark": false + } +] From 30c6362bd4676911fa8f3306b4d8311cee340931 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 17 May 2024 16:51:40 +0300 Subject: [PATCH 21/88] fix(precompile): ignore infinity points in G1 MSM (#1432) --- crates/precompile/src/bls12_381/g1_msm.rs | 20 ++++++++++++++++---- crates/precompile/src/bls12_381/g2_msm.rs | 6 +++--- 2 files changed, 19 insertions(+), 7 deletions(-) diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index 503a7b74f9..c8d086abb6 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -41,13 +41,20 @@ pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { let mut g1_points: Vec = Vec::with_capacity(k); let mut scalars: Vec = Vec::with_capacity(k * SCALAR_LENGTH); for i in 0..k { + let slice = + &input[i * g1_mul::INPUT_LENGTH..i * g1_mul::INPUT_LENGTH + G1_INPUT_ITEM_LENGTH]; + + // BLST batch API for p1_affines blows up when you pass it a point at infinity and returns + // point at infinity so we just skip the element, and return 128 bytes in the response + if slice.iter().all(|i| *i == 0) { + continue; + } + // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. // // So we set the subgroup_check flag to `true` - let p0_aff = &extract_g1_input( - &input[i * g1_mul::INPUT_LENGTH..i * g1_mul::INPUT_LENGTH + G1_INPUT_ITEM_LENGTH], - true, - )?; + let p0_aff = &extract_g1_input(slice, true)?; + let mut p0 = blst_p1::default(); // SAFETY: p0 and p0_aff are blst values. unsafe { blst_p1_from_affine(&mut p0, p0_aff) }; @@ -62,6 +69,11 @@ pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { ); } + // return infinity point if all points are infinity + if g1_points.is_empty() { + return Ok((required_gas, [0; 128].into())); + } + let points = p1_affines::from(&g1_points); let multiexp = points.mult(&scalars, NBITS); diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index 0becd2b5db..85f8208fde 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -43,8 +43,8 @@ pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { for i in 0..k { let slice = &input[i * g2_mul::INPUT_LENGTH..i * g2_mul::INPUT_LENGTH + G2_INPUT_ITEM_LENGTH]; - // BLST batch API for p2_affines blows up when you pass it a point at infinity and returns point at infinity - // so we just skip the element, and return 256 bytes in the response + // BLST batch API for p2_affines blows up when you pass it a point at infinity and returns + // point at infinity so we just skip the element, and return 256 bytes in the response if slice.iter().all(|i| *i == 0) { continue; } @@ -71,7 +71,7 @@ pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { // return infinity point if all points are infinity if g2_points.is_empty() { - return Ok((required_gas, vec![0; 256].into())); + return Ok((required_gas, [0; 256].into())); } let points = p2_affines::from(&g2_points); From ff2dcf56c6c293cbeef5d822b0d27eff4450340e Mon Sep 17 00:00:00 2001 From: jpgonzalezra Date: Fri, 24 May 2024 05:31:54 -0300 Subject: [PATCH 22/88] chore(interpreter): optimisation for BYTE, SHL, SHR and SAR (#1418) * chore(interpreter): optimisation for BYTE, SHL, SHR and SAR * added previus comment in byte function * updated pr comments --- .../interpreter/src/instructions/bitwise.rs | 89 ++++++++++++++----- 1 file changed, 66 insertions(+), 23 deletions(-) diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 586af76ce3..62edf11c5a 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -1,11 +1,10 @@ -use super::i256::{i256_cmp, i256_sign_compl, two_compl, Sign}; +use super::i256::i256_cmp; use crate::{ gas, primitives::{Spec, U256}, Host, Interpreter, }; use core::cmp::Ordering; -use revm_primitives::uint; pub fn lt(interpreter: &mut Interpreter, _host: &mut H) { gas!(interpreter, gas::VERYLOW); @@ -85,7 +84,12 @@ pub fn shl(interpreter: &mut Interpreter, _host: & check!(interpreter, CONSTANTINOPLE); gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); - *op2 <<= as_usize_saturated!(op1); + let shift = as_usize_saturated!(op1); + *op2 = if shift < 256 { + *op2 << shift + } else { + U256::ZERO + } } /// EIP-145: Bitwise shifting instructions in EVM @@ -93,7 +97,12 @@ pub fn shr(interpreter: &mut Interpreter, _host: & check!(interpreter, CONSTANTINOPLE); gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); - *op2 >>= as_usize_saturated!(op1); + let shift = as_usize_saturated!(op1); + *op2 = if shift < 256 { + *op2 >> shift + } else { + U256::ZERO + } } /// EIP-145: Bitwise shifting instructions in EVM @@ -102,33 +111,32 @@ pub fn sar(interpreter: &mut Interpreter, _host: & gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, op1, op2); - let value_sign = i256_sign_compl(op2); - - // If the shift count is 255+, we can short-circuit. This is because shifting by 255 bits is the - // maximum shift that still leaves 1 bit in the original 256-bit number. Shifting by 256 bits or - // more would mean that no original bits remain. The result depends on what the highest bit of - // the value is. - *op2 = if value_sign == Sign::Zero || op1 >= U256::from(255) { - match value_sign { - // value is 0 or >=1, pushing 0 - Sign::Plus | Sign::Zero => U256::ZERO, - // value is <0, pushing -1 - Sign::Minus => U256::MAX, + let shift = as_usize_saturated!(op1); + *op2 = if shift >= 256 { + // If the shift is 256 or more, the result depends on the sign of the last bit. + if op2.bit(255) { + U256::MAX // Negative number, all bits set to one. + } else { + U256::ZERO // Non-negative number, all bits set to zero. } } else { - const ONE: U256 = uint!(1_U256); - // SAFETY: shift count is checked above; it's less than 255. - let shift = usize::try_from(op1).unwrap(); - match value_sign { - Sign::Plus | Sign::Zero => op2.wrapping_shr(shift), - Sign::Minus => two_compl(op2.wrapping_sub(ONE).wrapping_shr(shift).wrapping_add(ONE)), + // Normal shift + if op2.bit(255) { + // Check the most significant bit. + // Arithmetic right shift for negative numbers. + let shifted_value = *op2 >> shift; + let mask = U256::MAX << (256 - shift); // Mask for the sign bits. + shifted_value | mask // Apply the mask to simulate the filling of sign bits. + } else { + // Logical right shift for non-negative numbers. + *op2 >> shift } }; } #[cfg(test)] mod tests { - use crate::instructions::bitwise::{sar, shl, shr}; + use crate::instructions::bitwise::{byte, sar, shl, shr}; use crate::{Contract, DummyHost, Interpreter}; use revm_primitives::{uint, Env, LatestSpec, U256}; @@ -399,4 +407,39 @@ mod tests { assert_eq!(res, test.expected); } } + + #[test] + fn test_byte() { + struct TestCase { + input: U256, + index: usize, + expected: U256, + } + + let mut host = DummyHost::new(Env::default()); + let mut interpreter = Interpreter::new(Contract::default(), u64::MAX, false); + + let input_value = U256::from(0x1234567890abcdef1234567890abcdef_u128); + let test_cases = (0..32) + .map(|i| { + let byte_pos = 31 - i; + + let shift_amount = U256::from(byte_pos * 8); + let byte_value = (input_value >> shift_amount) & U256::from(0xFF); + TestCase { + input: input_value, + index: i, + expected: byte_value, + } + }) + .collect::>(); + + for test in test_cases.iter() { + push!(interpreter, test.input); + push!(interpreter, U256::from(test.index)); + byte(&mut interpreter, &mut host); + pop!(interpreter, res); + assert_eq!(res, test.expected, "Failed at index: {}", test.index); + } + } } From 45e3571beae5baf7324b0e9d4af7e95253384708 Mon Sep 17 00:00:00 2001 From: Pana Date: Fri, 24 May 2024 16:33:25 +0800 Subject: [PATCH 23/88] update doc about interpreter action (#1419) --- documentation/src/SUMMARY.md | 2 +- documentation/src/crates/interpreter.md | 2 +- .../src/crates/interpreter/inner_models.md | 29 -------------- .../crates/interpreter/interpreter_action.md | 39 +++++++++++++++++++ 4 files changed, 41 insertions(+), 31 deletions(-) delete mode 100644 documentation/src/crates/interpreter/inner_models.md create mode 100644 documentation/src/crates/interpreter/interpreter_action.md diff --git a/documentation/src/SUMMARY.md b/documentation/src/SUMMARY.md index d40b1b2b61..1d2900f332 100644 --- a/documentation/src/SUMMARY.md +++ b/documentation/src/SUMMARY.md @@ -12,7 +12,7 @@ - [gas](./crates/interpreter/gas.md) - [memory](./crates/interpreter/memory.md) - [host](./crates/interpreter/host.md) - - [inner_models](./crates/interpreter/inner_models.md) + - [interpreter_action](./crates/interpreter/interpreter_action.md) - [instruction_result](./crates/interpreter/instruction_result.md) - [instructions](./crates/interpreter/instructions.md) - [Primitives](./crates/primitives.md) diff --git a/documentation/src/crates/interpreter.md b/documentation/src/crates/interpreter.md index 629be56ab6..0ad39b0b6c 100644 --- a/documentation/src/crates/interpreter.md +++ b/documentation/src/crates/interpreter.md @@ -8,7 +8,7 @@ It is structured as follows: - [gas](./interpreter/gas.md): Handles gas mechanics in the EVM, such as calculating gas costs for operations. - [host](./interpreter/host.md): Defines the EVM context `Host` trait. -- [inner_models](./interpreter/inner_models.md): Contains inner data structures used in the EVM implementation. +- [interpreter_action](./interpreter/interpreter_action.md): Contains data structures used in the EVM implementation. - [instruction_result](./interpreter/instruction_result.md): Defines results of instruction execution. - [instructions](./interpreter/instructions.md): Defines the EVM opcodes (i.e. instructions). diff --git a/documentation/src/crates/interpreter/inner_models.md b/documentation/src/crates/interpreter/inner_models.md deleted file mode 100644 index 7524d94263..0000000000 --- a/documentation/src/crates/interpreter/inner_models.md +++ /dev/null @@ -1,29 +0,0 @@ -# The `inner_models.rs` Module in the Rust Ethereum Virtual Machine (EVM) - -The `inner_models.rs` module within this Rust EVM implementation encompasses a collection of datastructures used as internal models within the EVM. These models represent various aspects of EVM operations such as call and create inputs, call context, value transfers, and the result of self-destruction operations. - -## Data Structures - -- `CallInputs` Struct - - The `CallInputs` struct is used to encapsulate the inputs to a smart contract call in the EVM. This struct includes the target contract address, the value to be transferred (if any), the input data, the gas limit for the call, the call context, and a boolean indicating if the call is a static call (a read-only operation). - -- `CreateInputs` Struct - - The `CreateInputs` struct encapsulates the inputs for creating a new smart contract. This includes the address of the creator, the creation scheme, the value to be transferred, the initialization code for the new contract, and the gas limit for the creation operation. - -- `CallScheme` Enum - - The `CallScheme` enum represents the type of call being made to a smart contract. The different types of calls (`CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) represent different modes of interaction with a smart contract, each with its own semantics concerning the treatment of the message sender, value transfer, and the context in which the called code executes. - -- `CallContext` Struct - - The `CallContext` struct encapsulates the context of a smart contract call. This includes the executing contract's address, the caller's address, the address from which the contract code was loaded, the apparent value of the call (for `DELEGATECALL` and `CALLCODE`), and the call scheme. - -- `Transfer` Struct - -The `Transfer` struct represents a value transfer between two accounts. - -- `SelfDestructResult` Struct - -Finally, the `SelfDestructResult` struct captures the result of a self-destruction operation on a contract. In summary, the `inner_models.rs` module provides several crucial data structures that facilitate the representation and handling of various EVM operations and their associated data within this Rust EVM implementation. diff --git a/documentation/src/crates/interpreter/interpreter_action.md b/documentation/src/crates/interpreter/interpreter_action.md new file mode 100644 index 0000000000..9654b43e16 --- /dev/null +++ b/documentation/src/crates/interpreter/interpreter_action.md @@ -0,0 +1,39 @@ +# The `interpreter_action.rs` Module in the Rust Ethereum Virtual Machine (EVM) + +The `interpreter_action.rs` module within this Rust EVM implementation encompasses a collection of datastructures used as internal models within the EVM. These models represent various aspects of EVM operations such as call and create inputs, call context, value transfers, and the result of self-destruction operations. + +## Data Structures + +- `CallInputs` Struct + + The `CallInputs` struct is used to encapsulate the inputs to a smart contract call in the EVM. This struct includes the target contract address, the value to be transferred (if any), the input data, the gas limit for the call, the call context, and a boolean indicating if the call is a static call (a read-only operation). + +- `CallScheme` Enum + + The `CallScheme` enum represents the type of call being made to a smart contract. The different types of calls (`CALL`, `CALLCODE`, `DELEGATECALL`, `STATICCALL`) represent different modes of interaction with a smart contract, each with its own semantics concerning the treatment of the message sender, value transfer, and the context in which the called code executes. + +- `CallValue` Enum + + The `CallValue` Enum represents a value transfer between two accounts. + +- `CallOutcome` + + Represents the outcome of a call operation in a virtual machine. This struct encapsulates the result of executing an instruction by an interpreter, including the result itself, gas usage information, and the memory offset where output data is stored. + +- `CreateInputs` Struct + + The `CreateInputs` struct encapsulates the inputs for creating a new smart contract. This includes the address of the creator, the creation scheme, the value to be transferred, the initialization code for the new contract, and the gas limit for the creation operation. + +- `CreateOutcome` Struct + + Represents the outcome of a create operation in an interpreter. This struct holds the result of the operation along with an optional address. It provides methods to determine the next action based on the result of the operation. + +- `EOFCreateInput` Struct + + Inputs for EOF create call. + +- `EOFCreateOutcome` Struct + + Represents the outcome of a create operation in an interpreter. + +In summary, the `interpreter_action.rs` module provides several crucial data structures that facilitate the representation and handling of various EVM operations and their associated data within this Rust EVM implementation. From c75597723ceeb38ccf4d67bf0e7cc828ad435721 Mon Sep 17 00:00:00 2001 From: yjh Date: Fri, 24 May 2024 17:40:31 +0800 Subject: [PATCH 24/88] feat: load account should return db error (#1447) * feat: load account should return db error * simplify --- crates/revm/src/optimism/handler_register.rs | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index 0d3bcf4048..f517f94117 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -240,30 +240,20 @@ pub fn reward_beneficiary( let l1_cost = l1_block_info.calculate_tx_l1_cost(enveloped_tx, SPEC::SPEC_ID); // Send the L1 cost of the transaction to the L1 Fee Vault. - let Ok((l1_fee_vault_account, _)) = context + let (l1_fee_vault_account, _) = context .evm .inner .journaled_state - .load_account(optimism::L1_FEE_RECIPIENT, &mut context.evm.inner.db) - else { - return Err(EVMError::Custom( - "[OPTIMISM] Failed to load L1 Fee Vault account.".to_string(), - )); - }; + .load_account(optimism::L1_FEE_RECIPIENT, &mut context.evm.inner.db)?; l1_fee_vault_account.mark_touch(); l1_fee_vault_account.info.balance += l1_cost; // Send the base fee of the transaction to the Base Fee Vault. - let Ok((base_fee_vault_account, _)) = context + let (base_fee_vault_account, _) = context .evm .inner .journaled_state - .load_account(optimism::BASE_FEE_RECIPIENT, &mut context.evm.inner.db) - else { - return Err(EVMError::Custom( - "[OPTIMISM] Failed to load Base Fee Vault account.".to_string(), - )); - }; + .load_account(optimism::BASE_FEE_RECIPIENT, &mut context.evm.inner.db)?; base_fee_vault_account.mark_touch(); base_fee_vault_account.info.balance += context .evm From 44bafedd346af3f02ba342906989d3fceab19eae Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 24 May 2024 08:20:01 -0400 Subject: [PATCH 25/88] chore: add docs for BLS scalar input decoding (#1446) --- crates/precompile/src/bls12_381/utils.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/precompile/src/bls12_381/utils.rs b/crates/precompile/src/bls12_381/utils.rs index 3617a752c3..de370a07c3 100644 --- a/crates/precompile/src/bls12_381/utils.rs +++ b/crates/precompile/src/bls12_381/utils.rs @@ -42,7 +42,16 @@ pub(super) fn remove_padding(input: &[u8]) -> Result<&[u8; FP_LENGTH], Precompil Ok(unpadded.try_into().unwrap()) } -/// Extracts an Scalar from a 32 byte slice representation. +/// Extracts a scalar from a 32 byte slice representation, decoding the input as a big endian +/// unsigned integer. If the input is not exactly 32 bytes long, an error is returned. +/// +/// From [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537): +/// * A scalar for the multiplication operation is encoded as 32 bytes by performing BigEndian +/// encoding of the corresponding (unsigned) integer. +/// +/// We do not check that the scalar is a canonical Fr element, because the EIP specifies: +/// * The corresponding integer is not required to be less than or equal than main subgroup order +/// `q`. pub(super) fn extract_scalar_input(input: &[u8]) -> Result { if input.len() != SCALAR_LENGTH { return Err(PrecompileError::Other(format!( @@ -53,7 +62,13 @@ pub(super) fn extract_scalar_input(input: &[u8]) -> Result Date: Fri, 24 May 2024 15:02:23 +0200 Subject: [PATCH 26/88] chore: cargo update (#1451) --- Cargo.lock | 537 ++++++++++++++++++++---------------------- crates/revm/src/db.rs | 8 +- 2 files changed, 264 insertions(+), 281 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e6914d008c..fa834e7cb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -40,9 +40,9 @@ dependencies = [ [[package]] name = "allocator-api2" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "alloy-consensus" @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525448f6afc1b70dd0f9d0a8145631bf2f5e434678ab23ab18409ca264cae6b3" +checksum = "db8aa973e647ec336810a9356af8aea787249c9d00b1525359f3db29a68d231b" dependencies = [ "alloy-rlp", "arbitrary", @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "alloy-rlp" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d58d9f5da7b40e9bfff0b7e7816700be4019db97d4b6359fe7f94a9e22e42ac" +checksum = "b155716bab55763c95ba212806cf43d05bcc70e5f35b02bad20cf5ec7fe11fed" dependencies = [ "alloy-rlp-derive", "arrayvec", @@ -179,13 +179,13 @@ dependencies = [ [[package]] name = "alloy-rlp-derive" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a047897373be4bbb0224c1afdabca92648dc57a9c9ef6e7b0be3aff7a859c83" +checksum = "8037e03c7f462a063f28daec9fda285a9a89da003c552f8637a80b9c8fd96241" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -263,9 +263,23 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.2" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7dbd17d67f3e89478c8a634416358e539e577899666c927bc3d2b1328ee9b6ca" +dependencies = [ + "alloy-sol-macro-expander", + "alloy-sol-macro-input", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "alloy-sol-macro-expander" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89c80a2cb97e7aa48611cbb63950336f9824a174cdf670527cc6465078a26ea1" +checksum = "2c6da95adcf4760bb4b108fefa51d50096c5e5fdd29ee72fed3e86ee414f2e34" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -274,31 +288,31 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", "syn-solidity", "tiny-keccak", ] [[package]] name = "alloy-sol-macro-input" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58894b58ac50979eeac6249661991ac40b9d541830d9a725f7714cc9ef08c23" +checksum = "32c8da04c1343871fb6ce5a489218f9c85323c8340a36e9106b5fc98d4dd59d5" dependencies = [ "const-hex", "dunce", "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", "syn-solidity", ] [[package]] name = "alloy-sol-types" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399287f68d1081ed8b1f4903c49687658b95b142207d7cb4ae2f4813915343ef" +checksum = "40a64d2d2395c1ac636b62419a7b17ec39031d6b2367e66e9acbf566e6055e9c" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -312,7 +326,7 @@ version = "0.1.0" source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" dependencies = [ "alloy-json-rpc", - "base64 0.22.0", + "base64 0.22.1", "futures-util", "futures-utils-wasm", "serde", @@ -354,15 +368,15 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anyhow" -version = "1.0.83" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bdb32cbbdce2b519a9cd7df3a678443100e265d5e25ca763b7572a5104f5f3" +checksum = "b3d1d046238990b9cf5bcde22a3fb3584ee5cf65fb2765f454ed428c7a0063da" [[package]] name = "arbitrary" @@ -519,18 +533,18 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] name = "async-trait" -version = "0.1.79" +version = "0.1.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -544,6 +558,12 @@ dependencies = [ "rustc_version 0.4.0", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "atty" version = "0.2.14" @@ -573,14 +593,14 @@ checksum = "3c87f3f15e7794432337fc718554eaa4dc8f04c9677a950ffe366f20a162ae42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" @@ -617,9 +637,9 @@ checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" @@ -703,9 +723,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "byte-slice-cast" @@ -750,9 +770,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.90" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" [[package]] name = "cfg-if" @@ -762,9 +782,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" dependencies = [ "num-traits", ] @@ -813,9 +833,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", ] @@ -851,9 +871,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.3" +version = "1.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ba00838774b4ab0233e355d26710fbfc8327a05c017f6dc4873f876d1f79f78" +checksum = "70ff96486ccc291d36a958107caf2c0af8c78c0af7d31ae2f35ce055130de1a6" dependencies = [ "cfg-if", "cpufeatures", @@ -908,7 +928,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.3", + "clap 4.5.4", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -956,9 +976,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crunchy" @@ -1003,15 +1023,15 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" [[package]] name = "der" -version = "0.7.8" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c" +checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" dependencies = [ "const-oid", "zeroize", @@ -1045,7 +1065,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -1110,9 +1130,9 @@ dependencies = [ [[package]] name = "either" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" +checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" [[package]] name = "elliptic-curve" @@ -1141,9 +1161,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" dependencies = [ "cfg-if", ] @@ -1174,7 +1194,7 @@ checksum = "6fd000fd6988e73bbe993ea3db9b1aa64906ab88766d654973924340c8cddb42" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -1185,9 +1205,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys 0.52.0", @@ -1345,9 +1365,9 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.0.2" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fastrlp" @@ -1475,7 +1495,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -1546,9 +1566,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1592,9 +1612,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", @@ -1611,15 +1631,15 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" dependencies = [ + "atomic-waker", "bytes", "fnv", "futures-core", "futures-sink", - "futures-util", "http 1.1.0", "indexmap", "slab", @@ -1630,9 +1650,9 @@ dependencies = [ [[package]] name = "half" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5eceaaeec696539ddaf7b333340f1af35a5aa87ae3e4f3ead0532f72affab2e" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ "cfg-if", "crunchy", @@ -1802,7 +1822,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.25", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -1818,14 +1838,14 @@ dependencies = [ [[package]] name = "hyper" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.4", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -1858,7 +1878,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-util", "native-tls", "tokio", @@ -1877,7 +1897,7 @@ dependencies = [ "futures-util", "http 1.1.0", "http-body 1.0.0", - "hyper 1.2.0", + "hyper 1.3.1", "pin-project-lite", "socket2", "tokio", @@ -1965,9 +1985,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ "cfg-if", ] @@ -2009,9 +2029,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "js-sys" @@ -2061,9 +2081,9 @@ dependencies = [ [[package]] name = "keccak-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb8515fff80ed850aea4a1595f2e519c003e2a00a82fe168ebf5269196caf444" +checksum = "47a3633291834c4fbebf8673acbc1b04ec9d151418ff9b8e26dcd79129928758" dependencies = [ "digest 0.10.7", "sha3-asm", @@ -2080,9 +2100,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libm" @@ -2092,15 +2112,15 @@ checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -2123,9 +2143,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" [[package]] name = "microbench" @@ -2141,9 +2161,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" dependencies = [ "adler", ] @@ -2179,9 +2199,9 @@ dependencies = [ [[package]] name = "num" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05180d69e3da0e530ba2a1dae5110317e49e3b7f3d41be227dc5f92e49ee7af" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" dependencies = [ "num-bigint", "num-complex", @@ -2193,20 +2213,19 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "608e7659b5c3d7cba262d894801b9ec9d00de989e8a82bd4bef91d08da45cdc0" +checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" dependencies = [ - "autocfg", "num-integer", "num-traits", ] [[package]] name = "num-complex" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23c6602fda94a57c990fe0df199a035d83576b496aa29f4e634a8ac6004e68a6" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" dependencies = [ "num-traits", ] @@ -2228,9 +2247,9 @@ dependencies = [ [[package]] name = "num-iter" -version = "0.1.44" +version = "0.1.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" dependencies = [ "autocfg", "num-integer", @@ -2239,11 +2258,10 @@ dependencies = [ [[package]] name = "num-rational" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" dependencies = [ - "autocfg", "num-bigint", "num-integer", "num-traits", @@ -2251,9 +2269,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", @@ -2284,10 +2302,10 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate 3.1.0", + "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -2365,7 +2383,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -2388,9 +2406,9 @@ dependencies = [ [[package]] name = "parity-scale-codec" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "881331e34fa842a2fb61cc2db9643a8fedc615e47cfcc52597d1af0db9a7e8fe" +checksum = "306800abfa29c7f16596b5970a588435e3d5b3149683d00c12b699cc19f895ee" dependencies = [ "arrayvec", "bitvec", @@ -2402,11 +2420,11 @@ dependencies = [ [[package]] name = "parity-scale-codec-derive" -version = "3.6.9" +version = "3.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be30eaf4b0a9fba5336683b38de57bb86d179a35862ba6bfcf57625d006bde5b" +checksum = "d830939c76d294956402033aee57a6da7b438f2294eb94864c37b0569053a42c" dependencies = [ - "proc-macro-crate 2.0.0", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -2414,15 +2432,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -2448,9 +2466,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.8" +version = "2.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" +checksum = "560131c633294438da9f7c4b08189194b20946c8274c6b9e38881a7874dc8ee8" dependencies = [ "memchr", "thiserror", @@ -2497,7 +2515,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -2526,14 +2544,14 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "pin-utils" @@ -2568,9 +2586,9 @@ dependencies = [ [[package]] name = "plotters" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" +checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" dependencies = [ "num-traits", "plotters-backend", @@ -2581,15 +2599,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" +checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" [[package]] name = "plotters-svg" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" +checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" dependencies = [ "plotters-backend", ] @@ -2626,32 +2644,13 @@ dependencies = [ "uint", ] -[[package]] -name = "proc-macro-crate" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit 0.19.15", -] - -[[package]] -name = "proc-macro-crate" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" -dependencies = [ - "toml_edit 0.20.7", -] - [[package]] name = "proc-macro-crate" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] @@ -2680,9 +2679,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" dependencies = [ "unicode-ident", ] @@ -2726,9 +2725,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -2800,11 +2799,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -2832,9 +2831,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "relative-path" @@ -2853,7 +2852,7 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.25", + "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", @@ -2889,16 +2888,16 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "bytes", "encoding_rs", "futures-core", "futures-util", - "h2 0.4.4", + "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "http-body-util", - "hyper 1.2.0", + "hyper 1.3.1", "hyper-tls", "hyper-util", "ipnet", @@ -3135,7 +3134,7 @@ dependencies = [ "regex", "relative-path", "rustc_version 0.4.0", - "syn 2.0.55", + "syn 2.0.66", "unicode-ident", ] @@ -3172,9 +3171,9 @@ checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hex" @@ -3197,14 +3196,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.22", + "semver 1.0.23", ] [[package]] name = "rustix" -version = "0.38.32" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags 2.5.0", "errno", @@ -3215,9 +3214,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" dependencies = [ "log", "ring 0.17.8", @@ -3240,15 +3239,15 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" dependencies = [ - "base64 0.22.0", + "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.5.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" +checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" [[package]] name = "rustls-webpki" @@ -3262,9 +3261,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.14" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" [[package]] name = "rusty-fork" @@ -3280,9 +3279,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -3295,9 +3294,9 @@ dependencies = [ [[package]] name = "scale-info" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "788745a868b0e751750388f4e6546eb921ef714a4317fa6954f7cde114eb2eb7" +checksum = "eca070c12893629e2cc820a9761bedf6ce1dcddc9852984d1dc734b8bd9bd024" dependencies = [ "cfg-if", "derive_more", @@ -3307,11 +3306,11 @@ dependencies = [ [[package]] name = "scale-info-derive" -version = "2.11.1" +version = "2.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dc2f4e8bc344b9fc3d5f74f72c2e55bfc38d28dc2ebc69c194a3df424e4d9ac" +checksum = "2d35494501194174bda522a32605929eefc9ecf7e0a326c26db1fdd85881eb62" dependencies = [ - "proc-macro-crate 1.3.1", + "proc-macro-crate", "proc-macro2", "quote", "syn 1.0.109", @@ -3377,11 +3376,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "770452e37cad93e0a50d5abc3990d2bc351c36d0328f86cefec2f2fb206eaef6" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "core-foundation", "core-foundation-sys", "libc", @@ -3390,9 +3389,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.10.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f3cc463c0ef97e11c3461a9d3787412d30e8e7eb907c79180c4a57bf7c04ef" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" dependencies = [ "core-foundation-sys", "libc", @@ -3409,9 +3408,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "semver-parser" @@ -3436,22 +3435,22 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780f1cebed1629e4753a1a38a3c72d30b97ec044f0aef68cb26650a3c5cf363c" +checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.201" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5e405930b9796f1c00bee880d03fc7e0bb4b9a11afc776885ffe84320da2865" +checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -3512,9 +3511,9 @@ dependencies = [ [[package]] name = "sha3-asm" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac61da6b35ad76b195eb4771210f947734321a8d81d7738e1580d953bc7a15e" +checksum = "a9b57fd861253bff08bb1919e995f90ba8f4889de2726091c8876f3a4e823b40" dependencies = [ "cc", "cfg-if", @@ -3565,9 +3564,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.6" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" dependencies = [ "libc", "windows-sys 0.52.0", @@ -3650,7 +3649,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -3685,9 +3684,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.55" +version = "2.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" +checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" dependencies = [ "proc-macro2", "quote", @@ -3696,14 +3695,14 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa0cefd02f532035d83cfec82647c6eb53140b0485220760e669f4bad489e36" +checksum = "b8db114c44cf843a8bacd37a146e37987a0b823a0e8bc4fdc610c9c72ab397a5" dependencies = [ "paste", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -3762,22 +3761,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "579e9083ca58dd9dcf91a9923bb9054071b9ebbd800b342194c9feb0ee89fc18" +checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.60" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2470041c06ec3ac1ab38d0356a6119054dedaea53e12fbefc0de730a1c08524" +checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -3791,9 +3790,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.34" +version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" +checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" dependencies = [ "deranged", "itoa", @@ -3812,9 +3811,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" +checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" dependencies = [ "num-conv", "time-core", @@ -3879,7 +3878,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -3931,45 +3930,22 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml_datetime" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" - -[[package]] -name = "toml_edit" -version = "0.19.15" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" [[package]] name = "toml_edit" @@ -4030,7 +4006,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -4148,9 +4124,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" [[package]] name = "unicode-xid" @@ -4266,7 +4242,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", "wasm-bindgen-shared", ] @@ -4300,7 +4276,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4345,11 +4321,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -4373,7 +4349,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.4", + "windows-targets 0.52.5", ] [[package]] @@ -4393,17 +4369,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.4", - "windows_aarch64_msvc 0.52.4", - "windows_i686_gnu 0.52.4", - "windows_i686_msvc 0.52.4", - "windows_x86_64_gnu 0.52.4", - "windows_x86_64_gnullvm 0.52.4", - "windows_x86_64_msvc 0.52.4", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -4414,9 +4391,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -4426,9 +4403,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -4438,9 +4415,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.4" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -4450,9 +4433,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -4462,9 +4445,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -4474,9 +4457,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -4486,9 +4469,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.4" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" @@ -4549,22 +4532,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] [[package]] @@ -4584,5 +4567,5 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.55", + "syn 2.0.66", ] diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index bcb3aa463c..03dd5ac0a3 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -1,7 +1,7 @@ //! [Database] implementations. -#[cfg(feature = "alloydb")] -pub mod alloydb; +//#[cfg(feature = "alloydb")] +//pub mod alloydb; pub mod emptydb; #[cfg(feature = "ethersdb")] pub mod ethersdb; @@ -9,8 +9,8 @@ pub mod in_memory_db; pub mod states; pub use crate::primitives::db::*; -#[cfg(feature = "alloydb")] -pub use alloydb::AlloyDB; +//#[cfg(feature = "alloydb")] +//pub use alloydb::AlloyDB; pub use emptydb::{EmptyDB, EmptyDBTyped}; #[cfg(feature = "ethersdb")] pub use ethersdb::EthersDB; From 0e1cd99ae974a41082c7768ede19b6c7aefc5d07 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 24 May 2024 18:29:58 +0200 Subject: [PATCH 27/88] chore: skip tests with storage check and return status (#1452) * chore: cargo update * chore: skip tests with storage check and return error * return println and clippy * revert to previous println --- bins/revme/src/cmd/statetest/runner.rs | 12 ++++++++++++ bins/revme/src/main.rs | 8 +++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 16cf237938..85764f6aef 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -105,6 +105,18 @@ fn skip_test(path: &Path) -> bool { | "eip1559.json" | "mergeTest.json" + // Test with some storage check. + | "RevertInCreateInInit_Paris.json" + | "RevertInCreateInInit.json" + | "dynamicAccountOverwriteEmpty.json" + | "dynamicAccountOverwriteEmpty_Paris.json" + | "RevertInCreateInInitCreate2Paris.json" + | "create2collisionStorage.json" + | "RevertInCreateInInitCreate2.json" + | "create2collisionStorageParis.json" + | "InitCollision.json" + | "InitCollisionParis.json" + // These tests are passing, but they take a lot of time to execute so we are going to skip them. | "loopExp.json" | "Call50000_sha256.json" diff --git a/bins/revme/src/main.rs b/bins/revme/src/main.rs index 5e21714f2f..4662057476 100644 --- a/bins/revme/src/main.rs +++ b/bins/revme/src/main.rs @@ -1,9 +1,11 @@ -use revme::cmd::MainCmd; +use revme::cmd::{Error, MainCmd}; use structopt::StructOpt; -pub fn main() { +pub fn main() -> Result<(), Error> { let cmd = MainCmd::from_args(); if let Err(e) = cmd.run() { - println!("{}", e) + println!("{:?}", e); + return Err(e); } + Ok(()) } From 8b6ab3118a47df8574ed463f37d38ea5c94c6ad7 Mon Sep 17 00:00:00 2001 From: Alexey Shekhirin Date: Fri, 24 May 2024 17:30:17 +0100 Subject: [PATCH 28/88] feat(revm): revert EIP-2935 BLOCKHASH opcode changes (#1450) * feat(revm): revert EIP-2935 BLOCKHASH opcode changes * fix lint * bump time * return previous impl mod prague branch * remove unused imports --- crates/revm/src/context.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index aa2ae4be9c..6cdbdfe6fa 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -13,10 +13,7 @@ use revm_interpreter::as_usize_saturated; use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, - primitives::{ - Address, Bytecode, EVMError, Env, HandlerCfg, Log, B256, BLOCKHASH_SERVE_WINDOW, - BLOCKHASH_STORAGE_ADDRESS, BLOCK_HASH_HISTORY, PRAGUE, U256, - }, + primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256}, }; use std::boxed::Box; @@ -130,17 +127,6 @@ impl Host for Context { .ok(); } - if self.evm.journaled_state.spec.is_enabled_in(PRAGUE) && diff <= BLOCKHASH_SERVE_WINDOW { - let index = number.wrapping_rem(U256::from(BLOCKHASH_SERVE_WINDOW)); - return self - .evm - .db - .storage(BLOCKHASH_STORAGE_ADDRESS, index) - .map_err(|e| self.evm.error = Err(EVMError::Database(e))) - .ok() - .map(|v| v.into()); - } - Some(B256::ZERO) } From 2ce53cde4a2991d1c3f0b2f5ac3299e571b60f13 Mon Sep 17 00:00:00 2001 From: Brian Bland Date: Sat, 25 May 2024 09:59:51 -0700 Subject: [PATCH 29/88] chore: Update fork_ref_transact to use alloy instead of ethers (#1454) --- examples/fork_ref_transact.rs | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/examples/fork_ref_transact.rs b/examples/fork_ref_transact.rs index 9086467720..6953fda2a0 100644 --- a/examples/fork_ref_transact.rs +++ b/examples/fork_ref_transact.rs @@ -1,5 +1,5 @@ -use ethers_contract::BaseContract; -use ethers_core::abi::parse_abi; +use alloy_sol_types::sol; +use alloy_sol_types::SolCall; use ethers_providers::{Http, Provider}; use revm::{ db::{CacheDB, EmptyDB, EthersDB}, @@ -35,14 +35,12 @@ async fn main() -> anyhow::Result<()> { let pool_address = address!("0d4a11d5EEaaC28EC3F61d100daF4d40471f1852"); // generate abi for the calldata from the human readable interface - let abi = BaseContract::from( - parse_abi(&[ - "function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast)", - ])? - ); + sol! { + function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); + } // encode abi into Bytes - let encoded = abi.encode("getReserves", ())?; + let encoded = getReservesCall::new(()).abi_encode(); // initialize new EthersDB let mut ethersdb = EthersDB::new(Arc::clone(&client), None).unwrap(); @@ -74,7 +72,7 @@ async fn main() -> anyhow::Result<()> { // account you want to transact with tx.transact_to = TransactTo::Call(pool_address); // calldata formed via abigen - tx.data = encoded.0.into(); + tx.data = encoded.into(); // transaction value in wei tx.value = U256::from(0); }) @@ -94,13 +92,13 @@ async fn main() -> anyhow::Result<()> { result => panic!("Execution failed: {result:?}"), }; - // decode bytes to reserves + ts via ethers-rs's abi decode - let (reserve0, reserve1, ts): (u128, u128, u32) = abi.decode_output("getReserves", value)?; + // decode bytes to reserves + ts via alloy's abi decode + let return_vals = getReservesCall::abi_decode_returns(&value, true)?; // Print emulated getReserves() call output - println!("Reserve0: {:#?}", reserve0); - println!("Reserve1: {:#?}", reserve1); - println!("Timestamp: {:#?}", ts); + println!("Reserve0: {:#?}", return_vals.reserve0); + println!("Reserve1: {:#?}", return_vals.reserve1); + println!("Timestamp: {:#?}", return_vals.blockTimestampLast); Ok(()) } From 928883c26c21feaed45fefc78a4d1a810bbbd3b5 Mon Sep 17 00:00:00 2001 From: Brian Bland Date: Sun, 26 May 2024 09:02:34 -0700 Subject: [PATCH 30/88] feat(optimism): Add secp256r1 precompile for Fjord (#1436) * feat(optimism): Add secp256r1 precompile for Fjord * Fix docs * Fix nostd build * Load fjord precompiles via optimism handler register * Remove outdated fjord() precompile spec constructor * Document the secp256r1 feature * Address feedback * Handle invalid signatures * Update crates/precompile/src/secp256r1.rs * Update crates/precompile/src/secp256r1.rs * Blank return on failed signature verification * Add test case for invalid (zero) pubkey --------- Co-authored-by: rakita --- Cargo.lock | 22 ++++ crates/precompile/Cargo.toml | 8 +- crates/precompile/src/lib.rs | 4 +- crates/precompile/src/secp256r1.rs | 128 +++++++++++++++++++ crates/primitives/src/specification.rs | 43 ++++++- crates/revm/src/db/in_memory_db.rs | 2 +- crates/revm/src/optimism.rs | 4 +- crates/revm/src/optimism/handler_register.rs | 20 ++- 8 files changed, 224 insertions(+), 7 deletions(-) create mode 100644 crates/precompile/src/secp256r1.rs diff --git a/Cargo.lock b/Cargo.lock index fa834e7cb6..46150b3b02 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2404,6 +2404,18 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "p256" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" +dependencies = [ + "ecdsa", + "elliptic-curve", + "primeorder", + "sha2", +] + [[package]] name = "parity-scale-codec" version = "3.6.12" @@ -2630,6 +2642,15 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "primeorder" +version = "0.13.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" +dependencies = [ + "elliptic-curve", +] + [[package]] name = "primitive-types" version = "0.12.2" @@ -2972,6 +2993,7 @@ dependencies = [ "eyre", "k256", "once_cell", + "p256", "rand", "revm-primitives", "ripemd", diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index f761e726e1..08abf55bb6 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -44,6 +44,9 @@ secp256k1 = { version = "0.29.0", default-features = false, features = [ # BLS12-381 precompiles blst = { version = "0.3.11", optional = true } +# p256verify precompile +p256 = { version = "0.13.2", optional = true, default-features = false, features = ["ecdsa"] } + [dev-dependencies] criterion = { version = "0.5" } rand = { version = "0.8", features = ["std"] } @@ -67,7 +70,7 @@ std = [ hashbrown = ["revm-primitives/hashbrown"] asm-keccak = ["revm-primitives/asm-keccak"] -optimism = ["revm-primitives/optimism"] +optimism = ["revm-primitives/optimism", "secp256r1"] # Optimism default handler enabled Optimism handler register by default in EvmBuilder. optimism-default-handler = [ "optimism", @@ -77,6 +80,9 @@ negate-optimism-default-handler = [ "revm-primitives/negate-optimism-default-handler", ] +# Enables the p256verify precompile. +secp256r1 = ["dep:p256"] + # These libraries may not work on all no_std platforms as they depend on C. # Enables the KZG point evaluation precompile. diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index fe2486d3d1..ca797c8118 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -18,6 +18,8 @@ pub mod identity; pub mod kzg_point_evaluation; pub mod modexp; pub mod secp256k1; +#[cfg(feature = "secp256r1")] +pub mod secp256r1; pub mod utilities; use core::hash::Hash; @@ -271,7 +273,7 @@ impl PrecompileSpecId { #[cfg(feature = "optimism")] BEDROCK | REGOLITH | CANYON => Self::BERLIN, #[cfg(feature = "optimism")] - ECOTONE => Self::CANCUN, + ECOTONE | FJORD => Self::CANCUN, } } } diff --git a/crates/precompile/src/secp256r1.rs b/crates/precompile/src/secp256r1.rs new file mode 100644 index 0000000000..e2c9951a21 --- /dev/null +++ b/crates/precompile/src/secp256r1.rs @@ -0,0 +1,128 @@ +//! # EIP-7212 secp256r1 Precompile +//! +//! This module implements the [EIP-7212](https://eips.ethereum.org/EIPS/eip-7212) precompile for +//! secp256r1 curve support. +//! +//! The main purpose of this precompile is to verify ECDSA signatures that use the secp256r1, or +//! 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, Precompile, PrecompileWithAddress}; +use p256::ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey}; +use revm_primitives::{Bytes, PrecompileError, PrecompileResult, B256}; + +/// Base gas fee for secp256r1 p256verify operation. +const P256VERIFY_BASE: u64 = 3450; + +/// Returns the secp256r1 precompile with its address. +pub fn precompiles() -> impl Iterator { + [P256VERIFY].into_iter() +} + +/// [EIP-7212](https://eips.ethereum.org/EIPS/eip-7212#specification) secp256r1 precompile. +pub const P256VERIFY: PrecompileWithAddress = + PrecompileWithAddress(u64_to_address(0x100), Precompile::Standard(p256_verify)); + +/// secp256r1 precompile logic. It takes the input bytes sent to the precompile +/// and the gas limit. The output represents the result of verifying the +/// secp256r1 signature of the input. +/// +/// The input is encoded as follows: +/// +/// | signed message hash | r | s | public key x | public key y | +/// | :-----------------: | :-: | :-: | :----------: | :----------: | +/// | 32 | 32 | 32 | 32 | 32 | +pub fn p256_verify(input: &Bytes, gas_limit: u64) -> PrecompileResult { + if P256VERIFY_BASE > gas_limit { + return Err(PrecompileError::OutOfGas); + } + let result = if verify_impl(input).is_some() { + B256::with_last_byte(1).into() + } else { + Bytes::new() + }; + Ok((P256VERIFY_BASE, result)) +} + +/// Returns `Some(())` if the signature included in the input byte slice is +/// valid, `None` otherwise. +pub fn verify_impl(input: &[u8]) -> Option<()> { + if input.len() != 160 { + return None; + } + + // msg signed (msg is already the hash of the original message) + let msg = &input[..32]; + // r, s: signature + let sig = &input[32..96]; + // x, y: public key + let pk = &input[96..160]; + + // prepend 0x04 to the public key: uncompressed form + let mut uncompressed_pk = [0u8; 65]; + uncompressed_pk[0] = 0x04; + uncompressed_pk[1..].copy_from_slice(pk); + + // Can fail only if the input is not exact length. + let signature = Signature::from_slice(sig).ok()?; + // Can fail if the input is not valid, so we have to propagate the error. + let public_key = VerifyingKey::from_sec1_bytes(&uncompressed_pk).ok()?; + + public_key.verify_prehash(msg, &signature).ok() +} + +#[cfg(test)] +mod test { + use super::*; + use revm_primitives::hex::FromHex; + use rstest::rstest; + + #[rstest] + // test vectors from https://github.com/daimo-eth/p256-verifier/tree/master/test-vectors + #[case::ok_1("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", true)] + #[case::ok_2("3fec5769b5cf4e310a7d150508e82fb8e3eda1c2c94c61492d3bd8aea99e06c9e22466e928fdccef0de49e3503d2657d00494a00e764fd437bdafa05f5922b1fbbb77c6817ccf50748419477e843d5bac67e6a70e97dde5a57e0c983b777e1ad31a80482dadf89de6302b1988c82c29544c9c07bb910596158f6062517eb089a2f54c9a0f348752950094d3228d3b940258c75fe2a413cb70baa21dc2e352fc5", true)] + #[case::ok_3("e775723953ead4a90411a02908fd1a629db584bc600664c609061f221ef6bf7c440066c8626b49daaa7bf2bcc0b74be4f7a1e3dcf0e869f1542fe821498cbf2de73ad398194129f635de4424a07ca715838aefe8fe69d1a391cfa70470795a80dd056866e6e1125aff94413921880c437c9e2570a28ced7267c8beef7e9b2d8d1547d76dfcf4bee592f5fefe10ddfb6aeb0991c5b9dbbee6ec80d11b17c0eb1a", true)] + #[case::ok_4("b5a77e7a90aa14e0bf5f337f06f597148676424fae26e175c6e5621c34351955289f319789da424845c9eac935245fcddd805950e2f02506d09be7e411199556d262144475b1fa46ad85250728c600c53dfd10f8b3f4adf140e27241aec3c2da3a81046703fccf468b48b145f939efdbb96c3786db712b3113bb2488ef286cdcef8afe82d200a5bb36b5462166e8ce77f2d831a52ef2135b2af188110beaefb1", true)] + #[case::ok_5("858b991cfd78f16537fe6d1f4afd10273384db08bdfc843562a22b0626766686f6aec8247599f40bfe01bec0e0ecf17b4319559022d4d9bf007fe929943004eb4866760dedf31b7c691f5ce665f8aae0bda895c23595c834fecc2390a5bcc203b04afcacbb4280713287a2d0c37e23f7513fab898f2c1fefa00ec09a924c335d9b629f1d4fb71901c3e59611afbfea354d101324e894c788d1c01f00b3c251b2", true)] + #[case::fail_wrong_msg_1("3cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", false)] + #[case::fail_wrong_msg_2("afec5769b5cf4e310a7d150508e82fb8e3eda1c2c94c61492d3bd8aea99e06c9e22466e928fdccef0de49e3503d2657d00494a00e764fd437bdafa05f5922b1fbbb77c6817ccf50748419477e843d5bac67e6a70e97dde5a57e0c983b777e1ad31a80482dadf89de6302b1988c82c29544c9c07bb910596158f6062517eb089a2f54c9a0f348752950094d3228d3b940258c75fe2a413cb70baa21dc2e352fc5", false)] + #[case::fail_wrong_msg_3("f775723953ead4a90411a02908fd1a629db584bc600664c609061f221ef6bf7c440066c8626b49daaa7bf2bcc0b74be4f7a1e3dcf0e869f1542fe821498cbf2de73ad398194129f635de4424a07ca715838aefe8fe69d1a391cfa70470795a80dd056866e6e1125aff94413921880c437c9e2570a28ced7267c8beef7e9b2d8d1547d76dfcf4bee592f5fefe10ddfb6aeb0991c5b9dbbee6ec80d11b17c0eb1a", false)] + #[case::fail_wrong_msg_4("c5a77e7a90aa14e0bf5f337f06f597148676424fae26e175c6e5621c34351955289f319789da424845c9eac935245fcddd805950e2f02506d09be7e411199556d262144475b1fa46ad85250728c600c53dfd10f8b3f4adf140e27241aec3c2da3a81046703fccf468b48b145f939efdbb96c3786db712b3113bb2488ef286cdcef8afe82d200a5bb36b5462166e8ce77f2d831a52ef2135b2af188110beaefb1", false)] + #[case::fail_wrong_msg_5("958b991cfd78f16537fe6d1f4afd10273384db08bdfc843562a22b0626766686f6aec8247599f40bfe01bec0e0ecf17b4319559022d4d9bf007fe929943004eb4866760dedf31b7c691f5ce665f8aae0bda895c23595c834fecc2390a5bcc203b04afcacbb4280713287a2d0c37e23f7513fab898f2c1fefa00ec09a924c335d9b629f1d4fb71901c3e59611afbfea354d101324e894c788d1c01f00b3c251b2", false)] + #[case::fail_short_input_1("4cee90eb86eaa050036147a12d49004b6a", false)] + #[case::fail_short_input_2("4cee90eb86eaa050036147a12d49004b6a958b991cfd78f16537fe6d1f4afd10273384db08bdfc843562a22b0626766686f6aec8247599f40bfe01bec0e0ecf17b4319559022d4d9bf007fe929943004eb4866760dedf319", false)] + #[case::fail_long_input("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d604aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e00", false)] + #[case::fail_invalid_sig("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4dffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff4aebd3099c618202fcfe16ae7770b0c49ab5eadf74b754204a3bb6060e44eff37618b065f9832de4ca6ca971a7a1adc826d0f7c00181a5fb2ddf79ae00b4e10e", false)] + #[case::fail_invalid_pubkey("4cee90eb86eaa050036147a12d49004b6b9c72bd725d39d4785011fe190f0b4da73bd4903f0ce3b639bbbf6e8e80d16931ff4bcf5993d58468e8fb19086e8cac36dbcd03009df8c59286b162af3bd7fcc0450c9aa81be5d10d312af6c66b1d6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", false)] + fn test_sig_verify(#[case] input: &str, #[case] expect_success: bool) { + let input = Bytes::from_hex(input).unwrap(); + let target_gas = 3_500u64; + let (gas_used, res) = p256_verify(&input, target_gas).unwrap(); + assert_eq!(gas_used, 3_450u64); + let expected_result = if expect_success { + B256::with_last_byte(1).into() + } else { + Bytes::new() + }; + assert_eq!(res, expected_result); + } + + #[rstest] + 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); + + assert!(result.is_err()); + assert_eq!(result.err(), Some(PrecompileError::OutOfGas)); + } + + #[rstest] + #[case::ok_1("b5a77e7a90aa14e0bf5f337f06f597148676424fae26e175c6e5621c34351955289f319789da424845c9eac935245fcddd805950e2f02506d09be7e411199556d262144475b1fa46ad85250728c600c53dfd10f8b3f4adf140e27241aec3c2da3a81046703fccf468b48b145f939efdbb96c3786db712b3113bb2488ef286cdcef8afe82d200a5bb36b5462166e8ce77f2d831a52ef2135b2af188110beaefb1", true)] + #[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); + + assert_eq!(result.is_some(), expect_success); + } +} diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index 52abf9ecba..d7c1d3e6cf 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -63,7 +63,8 @@ pub enum SpecId { CANYON = 19, CANCUN = 20, ECOTONE = 21, - PRAGUE = 22, + FJORD = 22, + PRAGUE = 23, #[default] LATEST = u8::MAX, } @@ -114,6 +115,8 @@ impl From<&str> for SpecId { "Canyon" => SpecId::CANYON, #[cfg(feature = "optimism")] "Ecotone" => SpecId::ECOTONE, + #[cfg(feature = "optimism")] + "Fjord" => SpecId::FJORD, _ => Self::LATEST, } } @@ -149,6 +152,8 @@ impl From for &'static str { SpecId::CANYON => "Canyon", #[cfg(feature = "optimism")] SpecId::ECOTONE => "Ecotone", + #[cfg(feature = "optimism")] + SpecId::FJORD => "Fjord", SpecId::LATEST => "Latest", } } @@ -207,6 +212,8 @@ spec!(REGOLITH, RegolithSpec); spec!(CANYON, CanyonSpec); #[cfg(feature = "optimism")] spec!(ECOTONE, EcotoneSpec); +#[cfg(feature = "optimism")] +spec!(FJORD, FjordSpec); #[cfg(not(feature = "optimism"))] #[macro_export] @@ -354,6 +361,10 @@ macro_rules! spec_to_generic { use $crate::EcotoneSpec as SPEC; $e } + $crate::SpecId::FJORD => { + use $crate::FjordSpec as SPEC; + $e + } } }}; } @@ -390,6 +401,10 @@ mod tests { #[cfg(feature = "optimism")] spec_to_generic!(CANYON, assert_eq!(SPEC::SPEC_ID, CANYON)); spec_to_generic!(CANCUN, assert_eq!(SPEC::SPEC_ID, CANCUN)); + #[cfg(feature = "optimism")] + spec_to_generic!(ECOTONE, assert_eq!(SPEC::SPEC_ID, ECOTONE)); + #[cfg(feature = "optimism")] + spec_to_generic!(FJORD, assert_eq!(SPEC::SPEC_ID, FJORD)); spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE)); spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); } @@ -485,4 +500,30 @@ mod optimism_tests { assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::CANYON)); assert!(SpecId::enabled(SpecId::ECOTONE, SpecId::ECOTONE)); } + + #[test] + fn test_fjord_post_merge_hardforks() { + assert!(FjordSpec::enabled(SpecId::MERGE)); + assert!(FjordSpec::enabled(SpecId::SHANGHAI)); + assert!(FjordSpec::enabled(SpecId::CANCUN)); + assert!(!FjordSpec::enabled(SpecId::LATEST)); + assert!(FjordSpec::enabled(SpecId::BEDROCK)); + assert!(FjordSpec::enabled(SpecId::REGOLITH)); + assert!(FjordSpec::enabled(SpecId::CANYON)); + assert!(FjordSpec::enabled(SpecId::ECOTONE)); + assert!(FjordSpec::enabled(SpecId::FJORD)); + } + + #[test] + fn test_fjord_post_merge_hardforks_spec_id() { + assert!(SpecId::enabled(SpecId::FJORD, SpecId::MERGE)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::SHANGHAI)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::CANCUN)); + assert!(!SpecId::enabled(SpecId::FJORD, SpecId::LATEST)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::BEDROCK)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::REGOLITH)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::CANYON)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::ECOTONE)); + assert!(SpecId::enabled(SpecId::FJORD, SpecId::FJORD)); + } } diff --git a/crates/revm/src/db/in_memory_db.rs b/crates/revm/src/db/in_memory_db.rs index 00602d78b5..a46e6be9cf 100644 --- a/crates/revm/src/db/in_memory_db.rs +++ b/crates/revm/src/db/in_memory_db.rs @@ -482,7 +482,7 @@ mod tests { let serialized = serde_json::to_string(&init_state).unwrap(); let deserialized: CacheDB = serde_json::from_str(&serialized).unwrap(); - assert!(deserialized.accounts.get(&account).is_some()); + assert!(deserialized.accounts.contains_key(&account)); assert_eq!( deserialized.accounts.get(&account).unwrap().info.nonce, nonce diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index 3923b0c622..c72272b84d 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -4,7 +4,7 @@ mod handler_register; mod l1block; pub use handler_register::{ - deduct_caller, end, last_frame_return, load_accounts, optimism_handle_register, output, - reward_beneficiary, validate_env, validate_tx_against_state, + deduct_caller, end, last_frame_return, load_accounts, load_precompiles, + optimism_handle_register, output, reward_beneficiary, validate_env, validate_tx_against_state, }; pub use l1block::{L1BlockInfo, BASE_FEE_RECIPIENT, L1_BLOCK_CONTRACT, L1_FEE_RECIPIENT}; diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index f517f94117..d4996cca21 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -11,9 +11,10 @@ use crate::{ db::Database, spec_to_generic, Account, EVMError, Env, ExecutionResult, HaltReason, HashMap, InvalidTransaction, ResultAndState, Spec, SpecId, SpecId::REGOLITH, U256, }, - Context, FrameResult, + Context, ContextPrecompiles, FrameResult, }; use core::ops::Mul; +use revm_precompile::{secp256r1, PrecompileSpecId, Precompiles}; use std::string::ToString; use std::sync::Arc; @@ -23,6 +24,8 @@ pub fn optimism_handle_register(handler: &mut EvmHandler<'_, handler.validation.env = Arc::new(validate_env::); // Validate transaction against state. handler.validation.tx_against_state = Arc::new(validate_tx_against_state::); + // Load additional precompiles for the given chain spec. + handler.pre_execution.load_precompiles = Arc::new(load_precompiles::); // load l1 data handler.pre_execution.load_accounts = Arc::new(load_accounts::); // An estimated batch cost is charged from the caller and added to L1 Fee Vault. @@ -137,6 +140,21 @@ pub fn last_frame_return( Ok(()) } +/// Load precompiles for Optimism chain. +#[inline] +pub fn load_precompiles() -> ContextPrecompiles { + let mut precompiles = Precompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)).clone(); + + if SPEC::enabled(SpecId::FJORD) { + precompiles.extend([ + // EIP-7212: secp256r1 P256verify + secp256r1::P256VERIFY, + ]) + } + + precompiles.into() +} + /// Load account (make them warm) and l1 data from database. #[inline] pub fn load_accounts( From 3a8b5d0430c57bd07b3e85828bd573dcad3d7d17 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Sun, 26 May 2024 12:53:08 -0400 Subject: [PATCH 31/88] fix: check canonical Fp elements (#1434) * fix: check canonical field elements * chore: more cleanups * remove hex, update comments * fix more docs * small refactor and check if fp is canonical * doc fix --- crates/precompile/src/bls12_381.rs | 32 +++++++++---- crates/precompile/src/bls12_381/g1.rs | 35 +++++++++----- crates/precompile/src/bls12_381/g1_msm.rs | 1 + crates/precompile/src/bls12_381/g1_mul.rs | 5 +- crates/precompile/src/bls12_381/g2.rs | 45 +++++++++++++----- crates/precompile/src/bls12_381/g2_msm.rs | 1 + .../precompile/src/bls12_381/map_fp2_to_g2.rs | 19 ++------ .../precompile/src/bls12_381/map_fp_to_g1.rs | 14 ++---- crates/precompile/src/bls12_381/utils.rs | 43 ++++++++++++++++- .../test-vectors/fail-add_G1_bls.json | 32 +++++++++++++ .../test-vectors/fail-add_G2_bls.json | 32 +++++++++++++ .../test-vectors/fail-map_fp2_to_G2_bls.json | 27 +++++++++++ .../test-vectors/fail-map_fp_to_G1_bls.json | 27 +++++++++++ .../test-vectors/fail-mul_G1_bls.json | 37 +++++++++++++++ .../test-vectors/fail-mul_G2_bls.json | 37 +++++++++++++++ .../test-vectors/fail-multiexp_G1_bls.json | 37 +++++++++++++++ .../test-vectors/fail-multiexp_G2_bls.json | 37 +++++++++++++++ .../test-vectors/fail-pairing_check_bls.json | 47 +++++++++++++++++++ 18 files changed, 451 insertions(+), 57 deletions(-) create mode 100644 crates/precompile/test-vectors/fail-add_G1_bls.json create mode 100644 crates/precompile/test-vectors/fail-add_G2_bls.json create mode 100644 crates/precompile/test-vectors/fail-map_fp2_to_G2_bls.json create mode 100644 crates/precompile/test-vectors/fail-map_fp_to_G1_bls.json create mode 100644 crates/precompile/test-vectors/fail-mul_G1_bls.json create mode 100644 crates/precompile/test-vectors/fail-mul_G2_bls.json create mode 100644 crates/precompile/test-vectors/fail-multiexp_G1_bls.json create mode 100644 crates/precompile/test-vectors/fail-multiexp_G2_bls.json create mode 100644 crates/precompile/test-vectors/fail-pairing_check_bls.json diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs index fd5daae00a..a020e8b13a 100644 --- a/crates/precompile/src/bls12_381.rs +++ b/crates/precompile/src/bls12_381.rs @@ -48,14 +48,15 @@ mod test { use serde_derive::{Deserialize, Serialize}; use std::{fs, path::Path}; + /// Test vector structure for BLS12-381 precompile tests. #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "PascalCase")] struct TestVector { input: String, - expected: String, + expected: Option, name: String, - gas: u64, - error: Option, + gas: Option, + expected_error: Option, } #[derive(Serialize, Deserialize, Debug)] @@ -67,6 +68,15 @@ mod test { } #[rstest] + #[case::fail_g1_add(g1_add::g1_add, "fail-add_G1_bls.json")] + #[case::fail_g1_mul(g1_mul::g1_mul, "fail-mul_G1_bls.json")] + #[case::fail_g1_msm(g1_msm::g1_msm, "fail-multiexp_G1_bls.json")] + #[case::fail_g2_add(g2_add::g2_add, "fail-add_G2_bls.json")] + #[case::fail_g2_mul(g2_mul::g2_mul, "fail-mul_G2_bls.json")] + #[case::fail_g2_msm(g2_msm::g2_msm, "fail-multiexp_G2_bls.json")] + #[case::fail_pairing(pairing::pairing, "fail-pairing_check_bls.json")] + #[case::fail_map_fp_to_g1(map_fp_to_g1::map_fp_to_g1, "fail-map_fp_to_G1_bls.json")] + #[case::fail_map_fp2_to_g2(map_fp2_to_g2::map_fp2_to_g2, "fail-map_fp2_to_G2_bls.json")] #[case::g1_add(g1_add::g1_add, "add_G1_bls.json")] #[case::g1_mul(g1_mul::g1_mul, "mul_G1_bls.json")] #[case::g1_msm(g1_msm::g1_msm, "multiexp_G1_bls.json")] @@ -93,17 +103,23 @@ mod test { }); let target_gas: u64 = 30_000_000; let res = precompile(&input, target_gas); - if vector.error.unwrap_or_default() { - assert!(res.is_err(), "expected error didn't happen in {test_name}"); + if let Some(expected_error) = vector.expected_error { + assert!(res.is_err(), "expected error {expected_error} didn't happen in {test_name}, got result {res:?}"); } else { + let Some(gas) = vector.gas else { + panic!("gas is missing in {test_name}"); + }; let (actual_gas, actual_output) = res.unwrap_or_else(|e| panic!("precompile call failed for {test_name}: {e}")); assert_eq!( - vector.gas, actual_gas, + gas, actual_gas, "expected gas: {}, actual gas: {} in {test_name}", - vector.gas, actual_gas + gas, actual_gas ); - let expected_output = Bytes::from_hex(vector.expected).unwrap(); + let Some(expected) = vector.expected else { + panic!("expected output is missing in {test_name}"); + }; + let expected_output = Bytes::from_hex(expected).unwrap(); assert_eq!( expected_output, actual_output, "expected output: {expected_output}, actual output: {actual_output} in {test_name}"); diff --git a/crates/precompile/src/bls12_381/g1.rs b/crates/precompile/src/bls12_381/g1.rs index 9d4f630dbf..6e4b73faab 100644 --- a/crates/precompile/src/bls12_381/g1.rs +++ b/crates/precompile/src/bls12_381/g1.rs @@ -1,13 +1,14 @@ -use super::utils::{fp_to_bytes, remove_padding, PADDED_FP_LENGTH}; -use blst::{blst_fp_from_bendian, blst_p1_affine, blst_p1_affine_in_g1, blst_p1_affine_on_curve}; -use revm_primitives::{Bytes, PrecompileError}; +use super::utils::{fp_from_bendian, fp_to_bytes, remove_padding, PADDED_FP_LENGTH}; +use crate::primitives::{Bytes, PrecompileError}; +use blst::{blst_p1_affine, blst_p1_affine_in_g1, blst_p1_affine_on_curve}; /// Length of each of the elements in a g1 operation input. pub(super) const G1_INPUT_ITEM_LENGTH: usize = 128; + /// Output length of a g1 operation. const G1_OUTPUT_LENGTH: usize = 128; -/// Encodes a G1 point in affine format into a byte slice with padded elements. +/// Encodes a G1 point in affine format into byte slice with padded elements. pub(super) fn encode_g1_point(input: *const blst_p1_affine) -> Bytes { let mut out = vec![0u8; G1_OUTPUT_LENGTH]; // SAFETY: out comes from fixed length array, input is a blst value. @@ -18,6 +19,24 @@ pub(super) fn encode_g1_point(input: *const blst_p1_affine) -> Bytes { out.into() } +/// Returns a `blst_p1_affine` from the provided byte slices, which represent the x and y +/// affine coordinates of the point. +/// +/// If the x or y coordinate do not represent a canonical field element, an error is returned. +/// +/// See [fp_from_bendian] for more information. +pub(super) fn decode_and_check_g1( + p0_x: &[u8; 48], + p0_y: &[u8; 48], +) -> Result { + let out = blst_p1_affine { + x: fp_from_bendian(p0_x)?, + y: fp_from_bendian(p0_y)?, + }; + + Ok(out) +} + /// Extracts a G1 point in Affine format from a 128 byte slice representation. /// /// NOTE: This function will perform a G1 subgroup check if `subgroup_check` is set to `true`. @@ -34,13 +53,7 @@ pub(super) fn extract_g1_input( let input_p0_x = remove_padding(&input[..PADDED_FP_LENGTH])?; let input_p0_y = remove_padding(&input[PADDED_FP_LENGTH..G1_INPUT_ITEM_LENGTH])?; - - let mut out = blst_p1_affine::default(); - // SAFETY: input_p0_x and input_p0_y have fixed length, out is a blst value. - unsafe { - blst_fp_from_bendian(&mut out.x, input_p0_x.as_ptr()); - blst_fp_from_bendian(&mut out.y, input_p0_y.as_ptr()); - } + let out = decode_and_check_g1(input_p0_x, input_p0_y)?; if subgroup_check { // NB: Subgroup checks diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index c8d086abb6..f0003a3295 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -11,6 +11,7 @@ use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1MSM precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g1_msm)); + /// BLS12_G1MSM precompile address. pub const ADDRESS: u64 = 0x0d; diff --git a/crates/precompile/src/bls12_381/g1_mul.rs b/crates/precompile/src/bls12_381/g1_mul.rs index 305458e236..2b62a39c1d 100644 --- a/crates/precompile/src/bls12_381/g1_mul.rs +++ b/crates/precompile/src/bls12_381/g1_mul.rs @@ -37,8 +37,11 @@ pub(super) fn g1_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. // // So we set the subgroup_check flag to `true` - let p0_aff = &extract_g1_input(&input[..G1_INPUT_ITEM_LENGTH], true)?; + let slice = &input[..G1_INPUT_ITEM_LENGTH]; + let p0_aff = &extract_g1_input(slice, true)?; + let mut p0 = blst_p1::default(); + // SAFETY: p0 and p0_aff are blst values. unsafe { blst_p1_from_affine(&mut p0, p0_aff) }; diff --git a/crates/precompile/src/bls12_381/g2.rs b/crates/precompile/src/bls12_381/g2.rs index 321fc5f69a..585368959e 100644 --- a/crates/precompile/src/bls12_381/g2.rs +++ b/crates/precompile/src/bls12_381/g2.rs @@ -1,13 +1,14 @@ -use super::utils::{fp_to_bytes, remove_padding, FP_LENGTH, PADDED_FP_LENGTH}; -use blst::{blst_fp_from_bendian, blst_p2_affine, blst_p2_affine_in_g2, blst_p2_affine_on_curve}; -use revm_primitives::{Bytes, PrecompileError}; +use super::utils::{fp_from_bendian, fp_to_bytes, remove_padding, FP_LENGTH, PADDED_FP_LENGTH}; +use crate::primitives::{Bytes, PrecompileError}; +use blst::{blst_fp2, blst_p2_affine, blst_p2_affine_in_g2, blst_p2_affine_on_curve}; /// Length of each of the elements in a g2 operation input. pub(super) const G2_INPUT_ITEM_LENGTH: usize = 256; + /// Output length of a g2 operation. const G2_OUTPUT_LENGTH: usize = 256; -/// Encodes a G2 point in affine format into a byte slice with padded elements. +/// Encodes a G2 point in affine format into byte slice with padded elements. pub(super) fn encode_g2_point(input: &blst_p2_affine) -> Bytes { let mut out = vec![0u8; G2_OUTPUT_LENGTH]; fp_to_bytes(&mut out[..PADDED_FP_LENGTH], &input.x.fp[0]); @@ -26,6 +27,33 @@ pub(super) fn encode_g2_point(input: &blst_p2_affine) -> Bytes { out.into() } +/// Convert the following field elements from byte slices into a `blst_p2_affine` point. +pub(super) fn decode_and_check_g2( + x1: &[u8; 48], + x2: &[u8; 48], + y1: &[u8; 48], + y2: &[u8; 48], +) -> Result { + Ok(blst_p2_affine { + x: check_canonical_fp2(x1, x2)?, + y: check_canonical_fp2(y1, y2)?, + }) +} + +/// Checks whether or not the input represents a canonical fp2 field element, returning the field +/// element if successful. +pub(super) fn check_canonical_fp2( + input_1: &[u8; 48], + input_2: &[u8; 48], +) -> Result { + let fp_1 = fp_from_bendian(input_1)?; + let fp_2 = fp_from_bendian(input_2)?; + + let fp2 = blst_fp2 { fp: [fp_1, fp_2] }; + + Ok(fp2) +} + /// Extracts a G2 point in Affine format from a 256 byte slice representation. /// /// NOTE: This function will perform a G2 subgroup check if `subgroup_check` is set to `true`. @@ -45,14 +73,7 @@ pub(super) fn extract_g2_input( input_fps[i] = remove_padding(&input[i * PADDED_FP_LENGTH..(i + 1) * PADDED_FP_LENGTH])?; } - let mut out = blst_p2_affine::default(); - // SAFETY: items in fps have fixed length, out is a blst value. - unsafe { - blst_fp_from_bendian(&mut out.x.fp[0], input_fps[0].as_ptr()); - blst_fp_from_bendian(&mut out.x.fp[1], input_fps[1].as_ptr()); - blst_fp_from_bendian(&mut out.y.fp[0], input_fps[2].as_ptr()); - blst_fp_from_bendian(&mut out.y.fp[1], input_fps[3].as_ptr()); - } + let out = decode_and_check_g2(input_fps[0], input_fps[1], input_fps[2], input_fps[3])?; if subgroup_check { // NB: Subgroup checks diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index 85f8208fde..cedc73a147 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -11,6 +11,7 @@ use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2MSM precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(g2_msm)); + /// BLS12_G2MSM precompile address. pub const ADDRESS: u64 = 0x10; 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 51a90ac313..30c3ab5b63 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -1,19 +1,19 @@ use super::{ + g2::check_canonical_fp2, g2::encode_g2_point, utils::{remove_padding, PADDED_FP2_LENGTH, PADDED_FP_LENGTH}, }; use crate::{u64_to_address, PrecompileWithAddress}; -use blst::{ - blst_fp, blst_fp2, blst_fp_from_bendian, blst_map_to_g2, blst_p2, blst_p2_affine, - blst_p2_to_affine, -}; +use blst::{blst_map_to_g2, blst_p2, blst_p2_affine, blst_p2_to_affine}; use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP2_TO_G2 precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(map_fp2_to_g2)); + /// BLS12_MAP_FP2_TO_G2 precompile address. pub const ADDRESS: u64 = 0x13; + /// Base gas fee for BLS12-381 map_fp2_to_g2 operation. const BASE_GAS_FEE: u64 = 75000; @@ -35,16 +35,7 @@ pub(super) fn map_fp2_to_g2(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input_p0_x = remove_padding(&input[..PADDED_FP_LENGTH])?; let input_p0_y = remove_padding(&input[PADDED_FP_LENGTH..PADDED_FP2_LENGTH])?; - - let mut fp2 = blst_fp2::default(); - let mut fp_x = blst_fp::default(); - let mut fp_y = blst_fp::default(); - // SAFETY: input_p0_x has fixed length, fp_x is a blst value. - unsafe { blst_fp_from_bendian(&mut fp_x, input_p0_x.as_ptr()) }; - // SAFETY: input_p0_y has fixed length, fp_y is a blst value. - unsafe { blst_fp_from_bendian(&mut fp_y, input_p0_y.as_ptr()) }; - fp2.fp[0] = fp_x; - fp2.fp[1] = fp_y; + let fp2 = check_canonical_fp2(input_p0_x, input_p0_y)?; let mut p = blst_p2::default(); // SAFETY: p and fp2 are blst values. 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 a6d9f48ecb..ddbebb379b 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -1,18 +1,18 @@ use super::{ g1::encode_g1_point, - utils::{remove_padding, PADDED_FP_LENGTH}, + utils::{fp_from_bendian, remove_padding, PADDED_FP_LENGTH}, }; use crate::{u64_to_address, PrecompileWithAddress}; -use blst::{ - blst_fp, blst_fp_from_bendian, blst_map_to_g1, blst_p1, blst_p1_affine, blst_p1_to_affine, -}; +use blst::{blst_map_to_g1, blst_p1, blst_p1_affine, blst_p1_to_affine}; use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP_TO_G1 precompile. pub const PRECOMPILE: PrecompileWithAddress = PrecompileWithAddress(u64_to_address(ADDRESS), Precompile::Standard(map_fp_to_g1)); + /// BLS12_MAP_FP_TO_G1 precompile address. pub const ADDRESS: u64 = 0x12; + /// Base gas fee for BLS12-381 map_fp_to_g1 operation. const MAP_FP_TO_G1_BASE: u64 = 5500; @@ -32,11 +32,7 @@ pub(super) fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { } let input_p0 = remove_padding(input)?; - - let mut fp = blst_fp::default(); - - // SAFETY: input_p0 has fixed length, fp is a blst value. - unsafe { blst_fp_from_bendian(&mut fp, input_p0.as_ptr()) }; + let fp = fp_from_bendian(input_p0)?; let mut p = blst_p1::default(); // SAFETY: p and fp are blst values. diff --git a/crates/precompile/src/bls12_381/utils.rs b/crates/precompile/src/bls12_381/utils.rs index de370a07c3..ba18475c67 100644 --- a/crates/precompile/src/bls12_381/utils.rs +++ b/crates/precompile/src/bls12_381/utils.rs @@ -1,4 +1,8 @@ -use blst::{blst_bendian_from_fp, blst_fp, blst_scalar, blst_scalar_from_bendian}; +use core::cmp::Ordering; + +use blst::{ + blst_bendian_from_fp, blst_fp, blst_fp_from_bendian, blst_scalar, blst_scalar_from_bendian, +}; use revm_primitives::PrecompileError; /// Number of bits used in the BLS12-381 curve finite field elements. @@ -13,8 +17,14 @@ pub(super) const PADDED_FP2_LENGTH: usize = 128; pub(super) const PADDING_LENGTH: usize = 16; /// Scalar length. pub(super) const SCALAR_LENGTH: usize = 32; +// Big-endian non-Montgomery form. +pub(super) const MODULUS_REPR: [u8; 48] = [ + 0x1a, 0x01, 0x11, 0xea, 0x39, 0x7f, 0xe6, 0x9a, 0x4b, 0x1b, 0xa7, 0xb6, 0x43, 0x4b, 0xac, 0xd7, + 0x64, 0x77, 0x4b, 0x84, 0xf3, 0x85, 0x12, 0xbf, 0x67, 0x30, 0xd2, 0xa0, 0xf6, 0xb0, 0xf6, 0x24, + 0x1e, 0xab, 0xff, 0xfe, 0xb1, 0x53, 0xff, 0xff, 0xb9, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xaa, 0xab, +]; -/// Encodes a single finite field element into a byte slice with padding. +/// Encodes a single finite field element into byte slice with padding. pub(super) fn fp_to_bytes(out: &mut [u8], input: *const blst_fp) { if out.len() != PADDED_FP_LENGTH { return; @@ -72,3 +82,32 @@ pub(super) fn extract_scalar_input(input: &[u8]) -> Result bool { + for (i, modul) in input.iter().zip(MODULUS_REPR.iter()) { + match i.cmp(modul) { + Ordering::Greater => return false, + Ordering::Less => return true, + Ordering::Equal => continue, + } + } + // false if matching the modulus + false +} + +/// Checks whether or not the input represents a canonical field element, returning the field +/// element if successful. +pub(super) fn fp_from_bendian(input: &[u8; 48]) -> Result { + if !is_valid_be(input) { + return Err(PrecompileError::Other("non-canonical fp value".to_string())); + } + let mut fp = blst_fp::default(); + // SAFETY: input has fixed length, and fp is a blst value. + unsafe { + // This performs the check for canonical field elements + blst_fp_from_bendian(&mut fp, input.as_ptr()); + } + + Ok(fp) +} diff --git a/crates/precompile/test-vectors/fail-add_G1_bls.json b/crates/precompile/test-vectors/fail-add_G1_bls.json new file mode 100644 index 0000000000..e61e269d21 --- /dev/null +++ b/crates/precompile/test-vectors/fail-add_G1_bls.json @@ -0,0 +1,32 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_g1add_empty_input" + }, + { + "Input": "00000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "ExpectedError": "invalid input length", + "Name": "bls_g1add_short_input" + }, + { + "Input": "000000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "ExpectedError": "invalid input length", + "Name": "bls_g1add_large_input" + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_g1add_point_not_on_curve" + }, + { + "Input": "0000000000000000000000000000000031f2e5916b17be2e71b10b4292f558e727dfd7d48af9cbc5087f0ce00dcca27c8b01e83eaace1aefb539f00adb2271660000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_g2add_invalid_field_element" + }, + { + "Input": "1000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_g1add_violate_top_bytes" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-add_G2_bls.json b/crates/precompile/test-vectors/fail-add_G2_bls.json new file mode 100644 index 0000000000..9d3ab9c18a --- /dev/null +++ b/crates/precompile/test-vectors/fail-add_G2_bls.json @@ -0,0 +1,32 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_g2add_empty_input" + }, + { + "Input": "000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "ExpectedError": "invalid input length", + "Name": "bls_g2add_short_input" + }, + { + "Input": "0000000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "ExpectedError": "invalid input length", + "Name": "bls_g2add_long_input" + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_g2add_point_not_on_curve" + }, + { + "Input": "000000000000000000000000000000001c4bb49d2a0ef12b7123acdd7110bd292b5bc659edc54dc21b81de057194c79b2a5803255959bbef8e7f56c8c12168630000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_g2add_invalid_field_element" + }, + { + "Input": "10000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be00000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d878451", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_g2add_violate_top_bytes" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-map_fp2_to_G2_bls.json b/crates/precompile/test-vectors/fail-map_fp2_to_G2_bls.json new file mode 100644 index 0000000000..4411fdcc0f --- /dev/null +++ b/crates/precompile/test-vectors/fail-map_fp2_to_G2_bls.json @@ -0,0 +1,27 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_mapg2_empty_input" + }, + { + "Input": "0000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b7", + "ExpectedError": "invalid input length", + "Name": "bls_mapg2_short_input" + }, + { + "Input": "000000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c", + "ExpectedError": "invalid input length", + "Name": "bls_mapg2_long_input" + }, + { + "Input": "000000000000000000000000000000000007355d25caf6e7f2f0cb2812ca0e513bd026ed09dda65b177500fa31714e09ea0ded3a078b526bed3307f804d4b93b040000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b7", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_mapg2_top_bytes" + }, + { + "Input": "0000000000000000000000000000000021366f100476ce8d3be6cfc90d59fe13349e388ed12b6dd6dc31ccd267ff000e2c993a063ca66beced06f804d4b8e5af0000000000000000000000000000000002829ce3c021339ccb5caf3e187f6370e1e2a311dec9b75363117063ab2015603ff52c3d3b98f19c2f65575e99e8b78c", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_mapg2_invalid_fq_element" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-map_fp_to_G1_bls.json b/crates/precompile/test-vectors/fail-map_fp_to_G1_bls.json new file mode 100644 index 0000000000..2f66856931 --- /dev/null +++ b/crates/precompile/test-vectors/fail-map_fp_to_G1_bls.json @@ -0,0 +1,27 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_mapg1_empty_input" + }, + { + "Input": "00000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f", + "ExpectedError": "invalid input length", + "Name": "bls_mapg1_short_input" + }, + { + "Input": "0000000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f03", + "ExpectedError": "invalid input length", + "Name": "bls_mapg1_large_input" + }, + { + "Input": "1000000000000000000000000000000000156c8a6a2c184569d69a76be144b5cdc5141d2d2ca4fe341f011e25e3969c55ad9e9b9ce2eb833c81a908e5fa4ac5f", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_mapg1_top_bytes" + }, + { + "Input": "000000000000000000000000000000002f6d9c5465982c0421b61e74579709b3b5b91e57bdd4f6015742b4ff301abb7ef895b9cce00c33c7d48f8e5fa4ac09ae", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_invalid_fq_element" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-mul_G1_bls.json b/crates/precompile/test-vectors/fail-mul_G1_bls.json new file mode 100644 index 0000000000..5ae8e3b536 --- /dev/null +++ b/crates/precompile/test-vectors/fail-mul_G1_bls.json @@ -0,0 +1,37 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_g1mul_empty_input" + }, + { + "Input": "00000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g1mul_short_input" + }, + { + "Input": "000000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g1mul_large_input" + }, + { + "Input": "0000000000000000000000000000000031f2e5916b17be2e71b10b4292f558e727dfd7d48af9cbc5087f0ce00dcca27c8b01e83eaace1aefb539f00adb2271660000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_g1mul_invalid_field_element" + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_g1mul_point_not_on_curve" + }, + { + "Input": "1000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e10000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_g1mul_violate_top_bytes" + }, + { + "Input": "000000000000000000000000000000000123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000000000000000000000000000000193fb7cedb32b2c3adc06ec11a96bc0d661869316f5e4a577a9f7c179593987beb4fb2ee424dbb2f5dd891e228b46c4a0000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "g1 point is not on correct subgroup", + "Name": "bls_g1mul_g1_not_in_correct_subgroup" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-mul_G2_bls.json b/crates/precompile/test-vectors/fail-mul_G2_bls.json new file mode 100644 index 0000000000..5b4fa8a1f6 --- /dev/null +++ b/crates/precompile/test-vectors/fail-mul_G2_bls.json @@ -0,0 +1,37 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_g2mul_empty_input" + }, + { + "Input": "000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g2mul_short_input" + }, + { + "Input": "0000000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g2mul_large_input" + }, + { + "Input": "000000000000000000000000000000001c4bb49d2a0ef12b7123acdd7110bd292b5bc659edc54dc21b81de057194c79b2a5803255959bbef8e7f56c8c12168630000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_g2mul_invalid_field_element" + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_g2mul_point_not_on_curve" + }, + { + "Input": "10000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_g2mul_violate_top_bytes" + }, + { + "Input": "00000000000000000000000000000000197bfd0342bbc8bee2beced2f173e1a87be576379b343e93232d6cef98d84b1d696e5612ff283ce2cfdccb2cfb65fa0c00000000000000000000000000000000184e811f55e6f9d84d77d2f79102fd7ea7422f4759df5bf7f6331d550245e3f1bcf6a30e3b29110d85e0ca16f9f6ae7a000000000000000000000000000000000f10e1eb3c1e53d2ad9cf2d398b2dc22c5842fab0a74b174f691a7e914975da3564d835cd7d2982815b8ac57f507348f000000000000000000000000000000000767d1c453890f1b9110fda82f5815c27281aba3f026ee868e4176a0654feea41a96575e0c4d58a14dbfbcc05b5010b10000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "g2 point is not on correct subgroup", + "Name": "bls_g2mul_g2_not_in_correct_subgroup" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-multiexp_G1_bls.json b/crates/precompile/test-vectors/fail-multiexp_G1_bls.json new file mode 100644 index 0000000000..976f28c480 --- /dev/null +++ b/crates/precompile/test-vectors/fail-multiexp_G1_bls.json @@ -0,0 +1,37 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_g1multiexp_empty_input" + }, + { + "Input": "00000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g1multiexp_short_input" + }, + { + "Input": "000000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g1multiexp_long_input" + }, + { + "Input": "0000000000000000000000000000000031f2e5916b17be2e71b10b4292f558e727dfd7d48af9cbc5087f0ce00dcca27c8b01e83eaace1aefb539f00adb2271660000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_g1multiexp_invalid_field_element" + }, + { + "Input": "1000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e1000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_g1multiexp_violate_top_bytes" + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a21000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_g1multiexp_point_not_on_curve" + }, + { + "Input": "000000000000000000000000000000000123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000000000000000000000000000000193fb7cedb32b2c3adc06ec11a96bc0d661869316f5e4a577a9f7c179593987beb4fb2ee424dbb2f5dd891e228b46c4a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000112b98340eee2777cc3c14163dea3ec97977ac3dc5c70da32e6e87578f44912e902ccef9efe28d4a78b8999dfbca942600000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a210000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "g1 point is not on correct subgroup", + "Name": "bls_g1multiexp_g1_not_in_correct_subgroup" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-multiexp_G2_bls.json b/crates/precompile/test-vectors/fail-multiexp_G2_bls.json new file mode 100644 index 0000000000..486138985b --- /dev/null +++ b/crates/precompile/test-vectors/fail-multiexp_G2_bls.json @@ -0,0 +1,37 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_g2multiexp_empty_input" + }, + { + "Input": "000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g2multiexp_short_input" + }, + { + "Input": "0000000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid input length", + "Name": "bls_g2multiexp_long_input" + }, + { + "Input": "10000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_g2multiexp_violate_top_bytes" + }, + { + "Input": "000000000000000000000000000000001c4bb49d2a0ef12b7123acdd7110bd292b5bc659edc54dc21b81de057194c79b2a5803255959bbef8e7f56c8c12168630000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_g2multiexp_invalid_field_element" + }, + { + "Input": "00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_g2multiexp_point_not_on_curve" + }, + { + "Input": "00000000000000000000000000000000197bfd0342bbc8bee2beced2f173e1a87be576379b343e93232d6cef98d84b1d696e5612ff283ce2cfdccb2cfb65fa0c00000000000000000000000000000000184e811f55e6f9d84d77d2f79102fd7ea7422f4759df5bf7f6331d550245e3f1bcf6a30e3b29110d85e0ca16f9f6ae7a000000000000000000000000000000000f10e1eb3c1e53d2ad9cf2d398b2dc22c5842fab0a74b174f691a7e914975da3564d835cd7d2982815b8ac57f507348f000000000000000000000000000000000767d1c453890f1b9110fda82f5815c27281aba3f026ee868e4176a0654feea41a96575e0c4d58a14dbfbcc05b5010b1000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000103121a2ceaae586d240843a398967325f8eb5a93e8fea99b62b9f88d8556c80dd726a4b30e84a36eeabaf3592937f2700000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000f9e7ba9a86a8f7624aa2b42dcc8772e1af4ae115685e60abc2c9b90242167acef3d0be4050bf935eed7c3b6fc7ba77e000000000000000000000000000000000d22c3652d0dc6f0fc9316e14268477c2049ef772e852108d269d9c38dba1d4802e8dae479818184c08f9a569d8784510000000000000000000000000000000000000000000000000000000000000002", + "ExpectedError": "g2 point is not on correct subgroup", + "Name": "bls_pairing_g2_not_in_correct_subgroup" + } +] \ No newline at end of file diff --git a/crates/precompile/test-vectors/fail-pairing_check_bls.json b/crates/precompile/test-vectors/fail-pairing_check_bls.json new file mode 100644 index 0000000000..e14cb8e648 --- /dev/null +++ b/crates/precompile/test-vectors/fail-pairing_check_bls.json @@ -0,0 +1,47 @@ +[ + { + "Input": "", + "ExpectedError": "invalid input length", + "Name": "bls_pairing_empty_input" + }, + { + "Input": "00000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "invalid input length", + "Name": "bls_pairing_missing_data" + }, + { + "Input": "000000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "invalid input length", + "Name": "bls_pairing_extra_data" + }, + { + "Input": "1000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "invalid field element top bytes", + "Name": "bls_pairing_top_bytes" + }, + { + "Input": "0000000000000000000000000000000031f2e5916b17be2e71b10b4292f558e727dfd7d48af9cbc5087f0ce00dcca27c8b01e83eaace1aefb539f00adb2271660000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "invalid fp.Element encoding", + "Name": "bls_pairing_invalid_field_element" + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb00000000000000000000000000000000186b28d92356c4dfec4b5201ad099dbdede3781f8998ddf929b4cd7756192185ca7b8f4ef7088f813270ac3d48868a2100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_pairing_g1_not_on_curve" + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb800000000000000000000000000000000086b990f3da2aeac0a36143b7d7c824428215140db1bb859338764cb58458f081d92664f9053b50b3fbd2e4723121b68000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "invalid point: not on curve", + "Name": "bls_pairing_g2_not_on_curve" + }, + { + "Input": "000000000000000000000000000000000123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef00000000000000000000000000000000193fb7cedb32b2c3adc06ec11a96bc0d661869316f5e4a577a9f7c179593987beb4fb2ee424dbb2f5dd891e228b46c4a00000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000ce5d527727d6e118cc9cdc6da2e351aadfd9baa8cbdd3a76d429a695160d12c923ac9cc3baca289e193548608b82801000000000000000000000000000000000606c4a02ea734cc32acd2b02bc28b99cb3e287e85a763af267492ab572e99ab3f370d275cec1da1aaa9075ff05f79be0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "g1 point is not on correct subgroup", + "Name": "bls_pairing_g1_not_in_correct_subgroup" + }, + { + "Input": "0000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000197bfd0342bbc8bee2beced2f173e1a87be576379b343e93232d6cef98d84b1d696e5612ff283ce2cfdccb2cfb65fa0c00000000000000000000000000000000184e811f55e6f9d84d77d2f79102fd7ea7422f4759df5bf7f6331d550245e3f1bcf6a30e3b29110d85e0ca16f9f6ae7a000000000000000000000000000000000f10e1eb3c1e53d2ad9cf2d398b2dc22c5842fab0a74b174f691a7e914975da3564d835cd7d2982815b8ac57f507348f000000000000000000000000000000000767d1c453890f1b9110fda82f5815c27281aba3f026ee868e4176a0654feea41a96575e0c4d58a14dbfbcc05b5010b10000000000000000000000000000000017f1d3a73197d7942695638c4fa9ac0fc3688c4f9774b905a14e3a3f171bac586c55e83ff97a1aeffb3af00adb22c6bb0000000000000000000000000000000008b3f481e3aaa0f1a09e30ed741d8ae4fcf5e095d5d00af600db18cb2c04b3edd03cc744a2888ae40caa232946c5e7e100000000000000000000000000000000024aa2b2f08f0a91260805272dc51051c6e47ad4fa403b02b4510b647ae3d1770bac0326a805bbefd48056c8c121bdb80000000000000000000000000000000013e02b6052719f607dacd3a088274f65596bd0d09920b61ab5da61bbdc7f5049334cf11213945d57e5ac7d055d042b7e000000000000000000000000000000000d1b3cc2c7027888be51d9ef691d77bcb679afda66c73f17f9ee3837a55024f78c71363275a75d75d86bab79f74782aa0000000000000000000000000000000013fa4d4a0ad8b1ce186ed5061789213d993923066dddaf1040bc3ff59f825c78df74f2d75467e25e0f55f8a00fa030ed", + "ExpectedError": "g2 point is not on correct subgroup", + "Name": "bls_pairing_g2_not_in_correct_subgroup" + } +] \ No newline at end of file From 1b471bd138a1e263e677f566848591071b33d42a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 May 2024 09:06:41 +0200 Subject: [PATCH 32/88] chore(deps): bump serde from 1.0.202 to 1.0.203 (#1457) Bumps [serde](https://github.com/serde-rs/serde) from 1.0.202 to 1.0.203. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.202...v1.0.203) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 46150b3b02..35c433fba3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3457,18 +3457,18 @@ checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" [[package]] name = "serde" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "226b61a0d411b2ba5ff6d7f73a476ac4f8bb900373459cd00fab8512828ba395" +checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.202" +version = "1.0.203" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6048858004bcff69094cd972ed40a32500f153bd3be9f716b2eed2e8217c4838" +checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" dependencies = [ "proc-macro2", "quote", From af88ee9968167a6eb286fc9f7ac9b022c5a6e13c Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 27 May 2024 11:38:08 +0200 Subject: [PATCH 33/88] fix(Interpreter): wrong block number used (#1458) --- crates/interpreter/src/instructions/host.rs | 3 +-- crates/revm/src/db/states/state.rs | 3 ++- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 20a2bcfe6c..0bc777c341 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -106,8 +106,7 @@ pub fn blockhash(interpreter: &mut Interpreter, ho gas!(interpreter, gas::BLOCKHASH); pop_top!(interpreter, number); - let block_number = host.env().block.number; - let Some(hash) = host.block_hash(block_number) else { + let Some(hash) = host.block_hash(*number) else { interpreter.instruction_result = InstructionResult::FatalExternalError; return; }; diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index 22a937c5b8..4ca380d838 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -277,8 +277,9 @@ impl Database for State { let ret = *entry.insert(self.database.block_hash(number)?); // prune all hashes that are older then BLOCK_HASH_HISTORY + let last_block = u64num.saturating_sub(BLOCK_HASH_HISTORY as u64); while let Some(entry) = self.block_hashes.first_entry() { - if *entry.key() < u64num.saturating_sub(BLOCK_HASH_HISTORY as u64) { + if *entry.key() < last_block { entry.remove(); } else { break; From ba0220273c145a925bc2339af46abb917ec49406 Mon Sep 17 00:00:00 2001 From: vandenbogart <73037091+vandenbogart@users.noreply.github.com> Date: Tue, 28 May 2024 03:11:31 -0700 Subject: [PATCH 34/88] remove 'checked' bytecode bench causing benchmarks to crash due to name (#1461) conflict Co-authored-by: Eric Bogard --- crates/revm/benches/bench.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index d98d35199b..b45beefd6f 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -35,13 +35,6 @@ fn analysis(c: &mut Criterion) { .build(); bench_transact(&mut g, &mut evm); - let checked = Bytecode::new_raw(contract_data.clone()); - let mut evm = evm - .modify() - .reset_handler_with_db(BenchmarkDB::new_bytecode(checked)) - .build(); - bench_transact(&mut g, &mut evm); - let analysed = to_analysed(Bytecode::new_raw(contract_data)); let mut evm = evm .modify() From d9033998b5af9cbb42ef64bba2c7d3457a925e72 Mon Sep 17 00:00:00 2001 From: Brian Bland Date: Tue, 28 May 2024 04:06:20 -0700 Subject: [PATCH 35/88] feat(optimism): Implement new L1 cost function for Fjord (#1420) * Implement new L1 cost function for Fjord * Add fastlz test * Adds a second, more faithful adaptation of solady fastlz for fuzzing * Fix bounds check * Remove some unnecessary constants * Fix some linting issues * Add tests for parity with evm bytecode implementation of fastlz * Replace ethers abi encode/decode with alloy * Use rstest for parameterized testcases * Revert change to examples * Remove duplicate solady flz implementation * Remove direct alloy-sol-macro dependency * Remove unnecessary flag check * Undo dependency reordering --- Cargo.lock | 1 + crates/revm/Cargo.toml | 1 + crates/revm/src/optimism.rs | 1 + crates/revm/src/optimism/fast_lz.rs | 183 ++++++++++++++++++++++++++++ crates/revm/src/optimism/l1block.rs | 116 ++++++++++++++++-- 5 files changed, 294 insertions(+), 8 deletions(-) create mode 100644 crates/revm/src/optimism/fast_lz.rs diff --git a/Cargo.lock b/Cargo.lock index 35c433fba3..8250353bfa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2964,6 +2964,7 @@ dependencies = [ "reqwest 0.12.4", "revm-interpreter", "revm-precompile", + "rstest", "serde", "serde_json", "tokio", diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 9c1830e438..1a93a83d19 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -62,6 +62,7 @@ anyhow = "1.0.83" criterion = "0.5" indicatif = "0.17" reqwest = { version = "0.12" } +rstest = "0.19.0" alloy-provider = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d", default-features = false, features = [ "reqwest", diff --git a/crates/revm/src/optimism.rs b/crates/revm/src/optimism.rs index c72272b84d..12f3db9969 100644 --- a/crates/revm/src/optimism.rs +++ b/crates/revm/src/optimism.rs @@ -1,5 +1,6 @@ //! Optimism-specific constants, types, and helpers. +mod fast_lz; mod handler_register; mod l1block; diff --git a/crates/revm/src/optimism/fast_lz.rs b/crates/revm/src/optimism/fast_lz.rs new file mode 100644 index 0000000000..51ea82d493 --- /dev/null +++ b/crates/revm/src/optimism/fast_lz.rs @@ -0,0 +1,183 @@ +/// Returns the length of the data after compression through FastLZ, based on +// https://github.com/Vectorized/solady/blob/5315d937d79b335c668896d7533ac603adac5315/js/solady.js +pub(crate) fn flz_compress_len(input: &[u8]) -> u32 { + let mut idx: u32 = 2; + + let idx_limit: u32 = if input.len() < 13 { + 0 + } else { + input.len() as u32 - 13 + }; + + let mut anchor = 0; + + let mut size = 0; + + let mut htab = [0; 8192]; + + while idx < idx_limit { + let mut r: u32; + let mut distance: u32; + + loop { + let seq = u24(input, idx); + let hash = hash(seq); + r = htab[hash as usize]; + htab[hash as usize] = idx; + distance = idx - r; + if idx >= idx_limit { + break; + } + idx += 1; + if distance < 8192 && seq == u24(input, r) { + break; + } + } + + if idx >= idx_limit { + break; + } + + idx -= 1; + + if idx > anchor { + size = literals(idx - anchor, size); + } + + let len = cmp(input, r + 3, idx + 3, idx_limit + 9); + size = flz_match(len, size); + + idx = set_next_hash(&mut htab, input, idx + len); + idx = set_next_hash(&mut htab, input, idx); + anchor = idx; + } + + literals(input.len() as u32 - anchor, size) +} + +fn literals(r: u32, size: u32) -> u32 { + let size = size + 0x21 * (r / 0x20); + let r = r % 0x20; + if r != 0 { + size + r + 1 + } else { + size + } +} + +fn cmp(input: &[u8], p: u32, q: u32, r: u32) -> u32 { + let mut l = 0; + let mut r = r - q; + while l < r { + if input[(p + l) as usize] != input[(q + l) as usize] { + r = 0; + } + l += 1; + } + l +} + +fn flz_match(l: u32, size: u32) -> u32 { + let l = l - 1; + let size = size + (3 * (l / 262)); + if l % 262 >= 6 { + size + 3 + } else { + size + 2 + } +} + +fn set_next_hash(htab: &mut [u32; 8192], input: &[u8], idx: u32) -> u32 { + htab[hash(u24(input, idx)) as usize] = idx; + idx + 1 +} + +fn hash(v: u32) -> u16 { + let hash = (v as u64 * 2654435769) >> 19; + hash as u16 & 0x1fff +} + +fn u24(input: &[u8], idx: u32) -> u32 { + u32::from(input[idx as usize]) + + (u32::from(input[(idx + 1) as usize]) << 8) + + (u32::from(input[(idx + 2) as usize]) << 16) +} + +#[cfg(test)] +mod tests { + use alloy_sol_types::sol; + use alloy_sol_types::SolCall; + + use super::*; + use crate::db::BenchmarkDB; + use crate::{ + primitives::address, primitives::bytes, primitives::Bytecode, primitives::Bytes, + primitives::TransactTo, primitives::U256, Evm, + }; + + use rstest::rstest; + + #[rstest] + #[case::empty(&[], 0)] + #[case::thousand_zeros(&[0; 1000], 21)] + #[case::thousand_fourty_twos(&[42; 1000], 21)] + #[case::short_hex(&bytes!("FACADE"), 4)] + #[case::sample_contract_call(&bytes!("02f901550a758302df1483be21b88304743f94f80e51afb613d764fa61751affd3313c190a86bb870151bd62fd12adb8e41ef24f3f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000003c1e5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000148c89ed219d02f1a5be012c689b4f5b731827bebe000000000000000000000000c001a033fd89cb37c31b2cba46b6466e040c61fc9b2a3675a7f5f493ebd5ad77c497f8a07cdf65680e238392693019b4092f610222e71b7cec06449cb922b93b6a12744e"), 202)] + #[case::base_0x5dadeb52979f29fc7a7494c43fdabc5be1d8ff404f3aafe93d729fa8e5d00769(&bytes!("b9047c02f904788221050883036ee48409c6c87383037f6f941195cf65f83b3a5768f3c496d3a05ad6412c64b78644364c5bb000b90404d123b4d80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000f6476f90447748c19248ccaa31e6b8bfda4eb9d830f5f47df7f0998f7c2123d9e6137761b75d3184efb0f788e3b14516000000000000000000000000000000000000000000000000000044364c5bb000000000000000000000000000f38e53bd45c8225a7c94b513beadaa7afe5d222d0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084d6574614d61736b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d656852577a743347745961776343347564745657557233454c587261436746434259416b66507331696f48610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cd0d83d9e840f8e27d5c2e365fd365ff1c05b2480000000000000000000000000000000000000000000000000000000000000ce40000000000000000000000000000000000000000000000000000000000000041e4480d358dbae20880960a0a464d63b06565a0c9f9b1b37aa94b522247b23ce149c81359bf4239d1a879eeb41047ec710c15f5c0f67453da59a383e6abd742971c00000000000000000000000000000000000000000000000000000000000000c001a0b57f0ff8516ea29cb26a44ac5055a5420847d1e16a8e7b03b70f0c02291ff2d5a00ad3771e5f39ccacfff0faa8c5d25ef7a1c179f79e66e828ffddcb994c8b512e"), 471)] + fn test_flz_compress_len(#[case] input: &[u8], #[case] expected: u32) { + assert_eq!(flz_compress_len(input), expected); + } + + #[test] + fn test_flz_compress_len_no_repeats() { + let mut input = Vec::new(); + let mut len = 0; + + for i in 0..256 { + input.push(i as u8); + let prev_len = len; + len = flz_compress_len(&input); + assert!(len > prev_len); + } + } + + #[rstest] + #[case::short_hex(bytes!("FACADE"))] + #[case::sample_contract_call(bytes!("02f901550a758302df1483be21b88304743f94f80e51afb613d764fa61751affd3313c190a86bb870151bd62fd12adb8e41ef24f3f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000003c1e5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000148c89ed219d02f1a5be012c689b4f5b731827bebe000000000000000000000000c001a033fd89cb37c31b2cba46b6466e040c61fc9b2a3675a7f5f493ebd5ad77c497f8a07cdf65680e238392693019b4092f610222e71b7cec06449cb922b93b6a12744e"))] + #[case::base_0x5dadeb52979f29fc7a7494c43fdabc5be1d8ff404f3aafe93d729fa8e5d00769(bytes!("b9047c02f904788221050883036ee48409c6c87383037f6f941195cf65f83b3a5768f3c496d3a05ad6412c64b78644364c5bb000b90404d123b4d80000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000038000000000000000000000000000000000f6476f90447748c19248ccaa31e6b8bfda4eb9d830f5f47df7f0998f7c2123d9e6137761b75d3184efb0f788e3b14516000000000000000000000000000000000000000000000000000044364c5bb000000000000000000000000000f38e53bd45c8225a7c94b513beadaa7afe5d222d0000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000002a000000000000000000000000000000000000000000000000000000000000002c000000000000000000000000000000000000000000000000000000000000002e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084d6574614d61736b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000035697066733a2f2f516d656852577a743347745961776343347564745657557233454c587261436746434259416b66507331696f48610000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000cd0d83d9e840f8e27d5c2e365fd365ff1c05b2480000000000000000000000000000000000000000000000000000000000000ce40000000000000000000000000000000000000000000000000000000000000041e4480d358dbae20880960a0a464d63b06565a0c9f9b1b37aa94b522247b23ce149c81359bf4239d1a879eeb41047ec710c15f5c0f67453da59a383e6abd742971c00000000000000000000000000000000000000000000000000000000000000c001a0b57f0ff8516ea29cb26a44ac5055a5420847d1e16a8e7b03b70f0c02291ff2d5a00ad3771e5f39ccacfff0faa8c5d25ef7a1c179f79e66e828ffddcb994c8b512e"))] + #[case::base_0xfaada76a2dac09fc17f5a28d066aaabefc6d82ef6589b211ed8c9f766b070721(bytes!("b87602f873822105528304320f8409cfe5c98252089480c67432656d59144ceff962e8faf8926599bcf888011dfe52d06b633f80c001a08632f069f837aea7a28bab0affee14dda116956bd5a850a355c045d25afedd17a0084b8f273efffe17ece527116053e5781a4915ff89ab9c379f1e62c25b697687"))] + #[case::base_0x112864e9b971af6a1dac840018833c5a5a659acc187cfdaba919ad1da013678d(bytes!("b8b302f8b0822105308304320f8409cfe5c9827496944ed4e862860bed51a9570b96d89af5e1b0efefed80b844095ea7b3000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba300000000000000000000000000000000000000000000015e10fb0973595fffffc001a02020e39f07917c1a852feb131c857e12478c7e88a20772b91a8bf5cee38c5aeea06055981727f9aaa3471c1af800555b35a77916c154be3f9d02ad1a63029455ab"))] + #[case::base_0x6905051352691641888d0c427fb137c5b95afb5870d5169ff014eff1d0952195(bytes!("b87202f86f8221058303dc6c8310db1f84068fa8d7838954409436af2ff952a7355c8045fcd5e88bc9f6c8257f7b8080c001a0b89e7ff3d7694109e73e7f4244e032581670313c36e48e485c9c94b853bd81d2a038ffaf8f10859ce21d1f7f7046c3d08027fb8aa15b69038f6102be97aaa1179a"))] + #[case::base_0x6a38e9a26d7202a2268de69d2d47531c1a9829867579a483fb48d78e9e0b080d(bytes!("b9049b02f904978221058201618506fc23ac008506fc23ac008306ddd0943fc91a3afd70395cd496c647d5a6cc9d4b2b7fad80b904243593564c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000006641d67b00000000000000000000000000000000000000000000000000000000000000030a000c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000001e000000000000000000000000000000000000000000000000000000000000003000000000000000000000000000000000000000000000000000000000000000160000000000000000000000000088487bd8c3222d64d1d0b3fa7098dcf9d94d79e000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000006669635d00000000000000000000000000000000000000000000000000000000000000000000000000000000000000003fc91a3afd70395cd496c647d5a6cc9d4b2b7fad000000000000000000000000000000000000000000000000000000006641d78900000000000000000000000000000000000000000000000000000000000000e000000000000000000000000000000000000000000000000000000000000000418661369ca026f92ff88347bd0e3625a7b5ed65071b366368c68ad7c55aed136c18659b34f9246e30a784227a53dd374fbd3d2124696808c678cd987c4e954a681b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000549e5c020c764dbfffff00000000000000000000000000000000000000000000000002e5a629c093a2b600000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000002b088487bd8c3222d64d1d0b3fa7098dcf9d94d79e0027104200000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000c001a014a3acef764ff6d3bb9bd81e420bfa94171a5734ab997dfbc9b41b653ce018a4a01ff5fccb01ef5c60ba3aef67d4e74f3f47312dd78bfbbff9e5090fbf2d3d62bb"))] + fn test_flz_native_evm_parity(#[case] input: Bytes) { + // This bytecode and ABI is for a contract, which wraps the LibZip library for easier fuzz testing. + // The source of this contract is here: https://github.com/danyalprout/fastlz/blob/main/src/FastLz.sol#L6-L10 + sol! { + interface FastLz { + function fastLz(bytes input) external view returns (uint256); + } + } + + let contract_bytecode = Bytecode::new_raw(bytes!("608060405234801561001057600080fd5b506004361061002b5760003560e01c8063920a769114610030575b600080fd5b61004361003e366004610374565b610055565b60405190815260200160405180910390f35b600061006082610067565b5192915050565b60606101e0565b818153600101919050565b600082840393505b838110156100a25782810151828201511860001a1590930292600101610081565b9392505050565b825b602082106100d75782516100c0601f8361006e565b5260209290920191601f19909101906021016100ab565b81156100a25782516100ec600184038361006e565b520160010192915050565b60006001830392505b61010782106101385761012a8360ff1661012560fd6101258760081c60e0018961006e565b61006e565b935061010682039150610100565b600782106101655761015e8360ff16610125600785036101258760081c60e0018961006e565b90506100a2565b61017e8360ff166101258560081c8560051b018761006e565b949350505050565b80516101d890838303906101bc90600081901a600182901a60081b1760029190911a60101b17639e3779b90260131c611fff1690565b8060021b6040510182815160e01c1860e01b8151188152505050565b600101919050565b5060405161800038823961800081016020830180600d8551820103826002015b81811015610313576000805b50508051604051600082901a600183901a60081b1760029290921a60101b91909117639e3779b9810260111c617ffc16909101805160e081811c878603811890911b9091189091528401908183039084841061026857506102a3565b600184019350611fff821161029d578251600081901a600182901a60081b1760029190911a60101b17810361029d57506102a3565b5061020c565b8383106102b1575050610313565b600183039250858311156102cf576102cc87878886036100a9565b96505b6102e3600985016003850160038501610079565b91506102f08782846100f7565b9650506103088461030386848601610186565b610186565b915050809350610200565b5050617fe061032884848589518601036100a9565b03925050506020820180820383525b81811161034e57617fe08101518152602001610337565b5060008152602001604052919050565b634e487b7160e01b600052604160045260246000fd5b60006020828403121561038657600080fd5b813567ffffffffffffffff8082111561039e57600080fd5b818401915084601f8301126103b257600080fd5b8135818111156103c4576103c461035e565b604051601f8201601f19908116603f011681019083821181831017156103ec576103ec61035e565b8160405282815287602084870101111561040557600080fd5b82602086016020830137600092810160200192909252509594505050505056fea264697066735822122000646b2953fc4a6f501bd0456ac52203089443937719e16b3190b7979c39511264736f6c63430008190033")); + + let native_val = flz_compress_len(&input); + + let mut evm = Evm::builder() + .with_db(BenchmarkDB::new_bytecode(contract_bytecode.clone())) + .modify_tx_env(|tx| { + tx.caller = address!("1000000000000000000000000000000000000000"); + tx.transact_to = + TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); + }) + .build(); + + let result_and_state = evm.transact().unwrap(); + let output = result_and_state.result.output().unwrap(); + let evm_val = FastLz::fastLzCall::abi_decode_returns(output, true) + .unwrap() + ._0; + + assert_eq!(U256::from(native_val), evm_val); + } +} diff --git a/crates/revm/src/optimism/l1block.rs b/crates/revm/src/optimism/l1block.rs index b598bd827e..2dab41a4e4 100644 --- a/crates/revm/src/optimism/l1block.rs +++ b/crates/revm/src/optimism/l1block.rs @@ -1,3 +1,4 @@ +use crate::optimism::fast_lz::flz_compress_len; use crate::primitives::{address, db::Database, Address, SpecId, U256}; use core::ops::Mul; @@ -116,12 +117,22 @@ impl L1BlockInfo { } } - /// Calculate the data gas for posting the transaction on L1. Calldata costs 16 gas per non-zero - /// byte and 4 gas per zero byte. + /// Calculate the data gas for posting the transaction on L1. Calldata costs 16 gas per byte + /// after compression. + /// + /// Prior to fjord, calldata costs 16 gas per non-zero byte and 4 gas per zero byte. /// /// Prior to regolith, an extra 68 non-zero bytes were included in the rollup data costs to /// account for the empty signature. pub fn data_gas(&self, input: &[u8], spec_id: SpecId) -> U256 { + if spec_id.is_enabled_in(SpecId::FJORD) { + let estimated_size = self.tx_estimated_size_fjord(input); + + return estimated_size + .saturating_mul(U256::from(NON_ZERO_BYTE_COST)) + .wrapping_div(U256::from(1_000_000)); + }; + let mut rollup_data_gas_cost = U256::from(input.iter().fold(0, |acc, byte| { acc + if *byte == 0x00 { ZERO_BYTE_COST @@ -138,6 +149,18 @@ impl L1BlockInfo { rollup_data_gas_cost } + // Calculate the estimated compressed transaction size in bytes, scaled by 1e6. + // This value is computed based on the following formula: + // max(minTransactionSize, intercept + fastlzCoef*fastlzSize) + fn tx_estimated_size_fjord(&self, input: &[u8]) -> U256 { + let fastlz_size = U256::from(flz_compress_len(input)); + + fastlz_size + .saturating_mul(U256::from(836_500)) + .saturating_sub(U256::from(42_585_600)) + .max(U256::from(100_000_000)) + } + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, depending on the [SpecId] passed. pub fn calculate_tx_l1_cost(&self, input: &[u8], spec_id: SpecId) -> U256 { // If the input is a deposit transaction or empty, the default value is zero. @@ -145,7 +168,9 @@ impl L1BlockInfo { return U256::ZERO; } - if spec_id.is_enabled_in(SpecId::ECOTONE) { + if spec_id.is_enabled_in(SpecId::FJORD) { + self.calculate_tx_l1_cost_fjord(input) + } else if spec_id.is_enabled_in(SpecId::ECOTONE) { self.calculate_tx_l1_cost_ecotone(input, spec_id) } else { self.calculate_tx_l1_cost_bedrock(input, spec_id) @@ -181,19 +206,38 @@ impl L1BlockInfo { } let rollup_data_gas_cost = self.data_gas(input, spec_id); + let l1_fee_scaled = self.calculate_l1_fee_scaled_ecotone(); + + l1_fee_scaled + .saturating_mul(rollup_data_gas_cost) + .wrapping_div(U256::from(1_000_000 * NON_ZERO_BYTE_COST)) + } + + /// Calculate the gas cost of a transaction based on L1 block data posted on L2, post-Fjord. + /// + /// [SpecId::FJORD] L1 cost function: + /// `estimatedSize*(baseFeeScalar*l1BaseFee*16 + blobFeeScalar*l1BlobBaseFee)/1e12` + fn calculate_tx_l1_cost_fjord(&self, input: &[u8]) -> U256 { + let l1_fee_scaled = self.calculate_l1_fee_scaled_ecotone(); + let estimated_size = self.tx_estimated_size_fjord(input); + + estimated_size + .saturating_mul(l1_fee_scaled) + .wrapping_div(U256::from(1e12)) + } + + // l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar + fn calculate_l1_fee_scaled_ecotone(&self) -> U256 { let calldata_cost_per_byte = self .l1_base_fee - .saturating_mul(U256::from(16)) + .saturating_mul(U256::from(NON_ZERO_BYTE_COST)) .saturating_mul(self.l1_base_fee_scalar); let blob_cost_per_byte = self .l1_blob_base_fee .unwrap_or_default() .saturating_mul(self.l1_blob_base_fee_scalar.unwrap_or_default()); - calldata_cost_per_byte - .saturating_add(blob_cost_per_byte) - .saturating_mul(rollup_data_gas_cost) - .wrapping_div(U256::from(1_000_000 * 16)) + calldata_cost_per_byte.saturating_add(blob_cost_per_byte) } } @@ -225,6 +269,11 @@ mod tests { // gas cost = 3 * 16 = 48 let regolith_data_gas = l1_block_info.data_gas(&input, SpecId::REGOLITH); assert_eq!(regolith_data_gas, U256::from(48)); + + // Fjord has a minimum compressed size of 100 bytes + // gas cost = 100 * 16 = 1600 + let fjord_data_gas = l1_block_info.data_gas(&input, SpecId::FJORD); + assert_eq!(fjord_data_gas, U256::from(1600)); } #[test] @@ -250,6 +299,11 @@ mod tests { // gas cost = 3 * 16 + 2 * 4 = 56 let regolith_data_gas = l1_block_info.data_gas(&input, SpecId::REGOLITH); assert_eq!(regolith_data_gas, U256::from(56)); + + // Fjord has a minimum compressed size of 100 bytes + // gas cost = 100 * 16 = 1600 + let fjord_data_gas = l1_block_info.data_gas(&input, SpecId::FJORD); + assert_eq!(fjord_data_gas, U256::from(1600)); } #[test] @@ -310,4 +364,50 @@ mod tests { let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::ECOTONE); assert_eq!(gas_cost, U256::from(1048)); } + + #[test] + fn test_calculate_tx_l1_cost_fjord() { + // l1FeeScaled = baseFeeScalar*l1BaseFee*16 + blobFeeScalar*l1BlobBaseFee + // = 1000 * 1000 * 16 + 1000 * 1000 + // = 17e6 + let l1_block_info = L1BlockInfo { + l1_base_fee: U256::from(1_000), + l1_base_fee_scalar: U256::from(1_000), + l1_blob_base_fee: Some(U256::from(1_000)), + l1_blob_base_fee_scalar: Some(U256::from(1_000)), + ..Default::default() + }; + + // fastLzSize = 4 + // estimatedSize = max(minTransactionSize, intercept + fastlzCoef*fastlzSize) + // = max(100e6, 836500*4 - 42585600) + // = 100e6 + let input = bytes!("FACADE"); + // l1Cost = estimatedSize * l1FeeScaled / 1e12 + // = 100e6 * 17 / 1e6 + // = 1700 + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + assert_eq!(gas_cost, U256::from(1700)); + + // fastLzSize = 202 + // estimatedSize = max(minTransactionSize, intercept + fastlzCoef*fastlzSize) + // = max(100e6, 836500*202 - 42585600) + // = 126387400 + let input = bytes!("02f901550a758302df1483be21b88304743f94f80e51afb613d764fa61751affd3313c190a86bb870151bd62fd12adb8e41ef24f3f000000000000000000000000000000000000000000000000000000000000006e000000000000000000000000af88d065e77c8cc2239327c5edb3a432268e5831000000000000000000000000000000000000000000000000000000000003c1e5000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000148c89ed219d02f1a5be012c689b4f5b731827bebe000000000000000000000000c001a033fd89cb37c31b2cba46b6466e040c61fc9b2a3675a7f5f493ebd5ad77c497f8a07cdf65680e238392693019b4092f610222e71b7cec06449cb922b93b6a12744e"); + // l1Cost = estimatedSize * l1FeeScaled / 1e12 + // = 126387400 * 17 / 1e6 + // = 2148 + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + assert_eq!(gas_cost, U256::from(2148)); + + // Zero rollup data gas cost should result in zero + let input = bytes!(""); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + assert_eq!(gas_cost, U256::ZERO); + + // Deposit transactions with the EIP-2718 type of 0x7F should result in zero + let input = bytes!("7FFACADE"); + let gas_cost = l1_block_info.calculate_tx_l1_cost(&input, SpecId::FJORD); + assert_eq!(gas_cost, U256::ZERO); + } } From a28a5439b9cfb7494cbd670da10cbedcfe6c5854 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 28 May 2024 13:08:12 +0200 Subject: [PATCH 36/88] chore(primitives): rename State/Storage to EvmState/EvmStorage (#1459) * fix(Interpreter): wrong block number used * chore(primitives): rename State to PlainState * Restructure StorageSlot and rename PlainState to EvmState * doc --- crates/primitives/src/result.rs | 4 +- crates/primitives/src/state.rs | 41 +++++++-------- crates/revm/src/db/states.rs | 2 +- crates/revm/src/db/states/bundle_account.rs | 4 +- crates/revm/src/db/states/bundle_state.rs | 5 +- crates/revm/src/db/states/cache.rs | 25 ++++++--- crates/revm/src/db/states/plain_account.rs | 57 ++++++++++++++++++++- crates/revm/src/db/states/state.rs | 6 +-- crates/revm/src/journaled_state.rs | 22 ++++---- 9 files changed, 113 insertions(+), 53 deletions(-) diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index d5a0f90fa9..438451e2a9 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -1,4 +1,4 @@ -use crate::{Address, Bytes, Log, State, U256}; +use crate::{Address, Bytes, EvmState, Log, U256}; use core::fmt; use std::{boxed::Box, string::String, vec::Vec}; @@ -14,7 +14,7 @@ pub struct ResultAndState { /// Status of execution pub result: ExecutionResult, /// State that got updated - pub state: State, + pub state: EvmState, } /// Result of a transaction execution. diff --git a/crates/primitives/src/state.rs b/crates/primitives/src/state.rs index d0038f8d73..37315d3b68 100644 --- a/crates/primitives/src/state.rs +++ b/crates/primitives/src/state.rs @@ -3,13 +3,13 @@ use bitflags::bitflags; use core::hash::{Hash, Hasher}; /// EVM State is a mapping from addresses to accounts. -pub type State = HashMap; +pub type EvmState = HashMap; /// Structure used for EIP-1153 transient storage. pub type TransientStorage = HashMap<(Address, U256), U256>; -/// An account's Storage is a mapping from 256-bit integer keys to [StorageSlot]s. -pub type Storage = HashMap; +/// An account's Storage is a mapping from 256-bit integer keys to [EvmStorageSlot]s. +pub type EvmStorage = HashMap; #[derive(Debug, Clone, PartialEq, Eq, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] @@ -17,7 +17,7 @@ pub struct Account { /// Balance, nonce, and code. pub info: AccountInfo, /// Storage cache - pub storage: Storage, + pub storage: EvmStorage, /// Account status flags. pub status: AccountStatus, } @@ -119,8 +119,8 @@ impl Account { /// Returns an iterator over the storage slots that have been changed. /// - /// See also [StorageSlot::is_changed] - pub fn changed_storage_slots(&self) -> impl Iterator { + /// See also [EvmStorageSlot::is_changed] + pub fn changed_storage_slots(&self) -> impl Iterator { self.storage.iter().filter(|(_, slot)| slot.is_changed()) } } @@ -138,42 +138,37 @@ impl From for Account { /// This type keeps track of the current value of a storage slot. #[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct StorageSlot { - /// The value of the storage slot before it was changed. - /// - /// When the slot is first loaded, this is the original value. - /// - /// If the slot was not changed, this is equal to the present value. - pub previous_or_original_value: U256, - /// When loaded with sload present value is set to original value +pub struct EvmStorageSlot { + /// Original value of the storage slot. + pub original_value: U256, + /// Present value of the storage slot. pub present_value: U256, } -impl StorageSlot { - /// Creates a new _unchanged_ `StorageSlot` for the given value. +impl EvmStorageSlot { + /// Creates a new _unchanged_ `EvmStorageSlot` for the given value. pub fn new(original: U256) -> Self { Self { - previous_or_original_value: original, + original_value: original, present_value: original, } } - /// Creates a new _changed_ `StorageSlot`. - pub fn new_changed(previous_or_original_value: U256, present_value: U256) -> Self { + /// Creates a new _changed_ `EvmStorageSlot`. + pub fn new_changed(original_value: U256, present_value: U256) -> Self { Self { - previous_or_original_value, + original_value, present_value, } } - /// Returns true if the present value differs from the original value pub fn is_changed(&self) -> bool { - self.previous_or_original_value != self.present_value + self.original_value != self.present_value } /// Returns the original value of the storage slot. pub fn original_value(&self) -> U256 { - self.previous_or_original_value + self.original_value } /// Returns the current value of the storage slot. diff --git a/crates/revm/src/db/states.rs b/crates/revm/src/db/states.rs index 2c58f2d632..2fa08b2a52 100644 --- a/crates/revm/src/db/states.rs +++ b/crates/revm/src/db/states.rs @@ -18,7 +18,7 @@ pub use bundle_state::{BundleBuilder, BundleState, OriginalValuesKnown}; pub use cache::CacheState; pub use cache_account::CacheAccount; pub use changes::{PlainStateReverts, PlainStorageChangeset, PlainStorageRevert, StateChangeset}; -pub use plain_account::{PlainAccount, StorageWithOriginalValues}; +pub use plain_account::{PlainAccount, StorageSlot, StorageWithOriginalValues}; pub use reverts::{AccountRevert, RevertToSlot}; pub use state::{DBBox, State, StateDBBox}; pub use state_builder::StateBuilder; diff --git a/crates/revm/src/db/states/bundle_account.rs b/crates/revm/src/db/states/bundle_account.rs index c582dfdd42..9916139d12 100644 --- a/crates/revm/src/db/states/bundle_account.rs +++ b/crates/revm/src/db/states/bundle_account.rs @@ -1,8 +1,8 @@ use super::{ - reverts::AccountInfoRevert, AccountRevert, AccountStatus, RevertToSlot, + reverts::AccountInfoRevert, AccountRevert, AccountStatus, RevertToSlot, StorageSlot, StorageWithOriginalValues, TransitionAccount, }; -use revm_interpreter::primitives::{AccountInfo, StorageSlot, U256}; +use revm_interpreter::primitives::{AccountInfo, U256}; use revm_precompile::HashMap; /// Account information focused on creating of database changesets diff --git a/crates/revm/src/db/states/bundle_state.rs b/crates/revm/src/db/states/bundle_state.rs index 5f189041d9..8dd4edfe26 100644 --- a/crates/revm/src/db/states/bundle_state.rs +++ b/crates/revm/src/db/states/bundle_state.rs @@ -1,12 +1,13 @@ use super::{ changes::{PlainStorageChangeset, StateChangeset}, reverts::{AccountInfoRevert, Reverts}, - AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, TransitionState, + AccountRevert, AccountStatus, BundleAccount, PlainStateReverts, RevertToSlot, StorageSlot, + TransitionState, }; use core::{mem, ops::RangeInclusive}; use revm_interpreter::primitives::{ hash_map::{self, Entry}, - AccountInfo, Address, Bytecode, HashMap, HashSet, StorageSlot, B256, KECCAK_EMPTY, U256, + AccountInfo, Address, Bytecode, HashMap, HashSet, B256, KECCAK_EMPTY, U256, }; use std::{ collections::{BTreeMap, BTreeSet}, diff --git a/crates/revm/src/db/states/cache.rs b/crates/revm/src/db/states/cache.rs index eb1c4577ae..63c0160bab 100644 --- a/crates/revm/src/db/states/cache.rs +++ b/crates/revm/src/db/states/cache.rs @@ -2,7 +2,7 @@ use super::{ plain_account::PlainStorage, transition_account::TransitionAccount, CacheAccount, PlainAccount, }; use revm_interpreter::primitives::{ - Account, AccountInfo, Address, Bytecode, HashMap, State as EVMState, B256, + Account, AccountInfo, Address, Bytecode, EvmState, HashMap, B256, }; use std::vec::Vec; @@ -88,7 +88,7 @@ impl CacheState { } /// Apply output of revm execution and create account transitions that are used to build BundleState. - pub fn apply_evm_state(&mut self, evm_state: EVMState) -> Vec<(Address, TransitionAccount)> { + pub fn apply_evm_state(&mut self, evm_state: EvmState) -> Vec<(Address, TransitionAccount)> { let mut transitions = Vec::with_capacity(evm_state.len()); for (address, account) in evm_state { if let Some(transition) = self.apply_account_state(address, account) { @@ -121,6 +121,17 @@ impl CacheState { return this_account.selfdestruct(); } + let is_created = account.is_created(); + let is_empty = account.is_empty(); + + // transform evm storage to storage with previous value. + let changed_storage = account + .storage + .into_iter() + .filter(|(_, slot)| slot.is_changed()) + .map(|(key, slot)| (key, slot.into())) + .collect(); + // Note: it can happen that created contract get selfdestructed in same block // that is why is_created is checked after selfdestructed // @@ -129,25 +140,25 @@ impl CacheState { // Note: It is possibility to create KECCAK_EMPTY contract with some storage // by just setting storage inside CRATE constructor. Overlap of those contracts // is not possible because CREATE2 is introduced later. - if account.is_created() { - return Some(this_account.newly_created(account.info, account.storage)); + if is_created { + return Some(this_account.newly_created(account.info, changed_storage)); } // Account is touched, but not selfdestructed or newly created. // Account can be touched and not changed. // And when empty account is touched it needs to be removed from database. // EIP-161 state clear - if account.is_empty() { + if is_empty { if self.has_state_clear { // touch empty account. this_account.touch_empty_eip161() } else { // if account is empty and state clear is not enabled we should save // empty account. - this_account.touch_create_pre_eip161(account.storage) + this_account.touch_create_pre_eip161(changed_storage) } } else { - Some(this_account.change(account.info, account.storage)) + Some(this_account.change(account.info, changed_storage)) } } } diff --git a/crates/revm/src/db/states/plain_account.rs b/crates/revm/src/db/states/plain_account.rs index f6cb76618c..5aadfcc073 100644 --- a/crates/revm/src/db/states/plain_account.rs +++ b/crates/revm/src/db/states/plain_account.rs @@ -1,4 +1,4 @@ -use revm_interpreter::primitives::{AccountInfo, HashMap, StorageSlot, U256}; +use crate::primitives::{AccountInfo, EvmStorageSlot, HashMap, U256}; // TODO rename this to BundleAccount. As for the block level we have original state. #[derive(Clone, Debug, Default, PartialEq, Eq)] @@ -20,9 +20,62 @@ impl PlainAccount { } } +/// This type keeps track of the current value of a storage slot. +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct StorageSlot { + /// The value of the storage slot before it was changed. + /// + /// When the slot is first loaded, this is the original value. + /// + /// If the slot was not changed, this is equal to the present value. + pub previous_or_original_value: U256, + /// When loaded with sload present value is set to original value + pub present_value: U256, +} + +impl From for StorageSlot { + fn from(value: EvmStorageSlot) -> Self { + Self::new_changed(value.original_value, value.present_value) + } +} + +impl StorageSlot { + /// Creates a new _unchanged_ `StorageSlot` for the given value. + pub fn new(original: U256) -> Self { + Self { + previous_or_original_value: original, + present_value: original, + } + } + + /// Creates a new _changed_ `StorageSlot`. + pub fn new_changed(previous_or_original_value: U256, present_value: U256) -> Self { + Self { + previous_or_original_value, + present_value, + } + } + + /// Returns true if the present value differs from the original value + pub fn is_changed(&self) -> bool { + self.previous_or_original_value != self.present_value + } + + /// Returns the original value of the storage slot. + pub fn original_value(&self) -> U256 { + self.previous_or_original_value + } + + /// Returns the current value of the storage slot. + pub fn present_value(&self) -> U256 { + self.present_value + } +} + /// This storage represent values that are before block changed. /// -/// Note: Storage that we get EVM contains original values before t +/// Note: Storage that we get EVM contains original values before block changed. pub type StorageWithOriginalValues = HashMap; /// Simple plain storage that does not have previous value. diff --git a/crates/revm/src/db/states/state.rs b/crates/revm/src/db/states/state.rs index 4ca380d838..2b63b7abd4 100644 --- a/crates/revm/src/db/states/state.rs +++ b/crates/revm/src/db/states/state.rs @@ -303,10 +303,10 @@ impl DatabaseCommit for State { mod tests { use super::*; use crate::db::{ - states::reverts::AccountInfoRevert, AccountRevert, AccountStatus, BundleAccount, - RevertToSlot, + states::{reverts::AccountInfoRevert, StorageSlot}, + AccountRevert, AccountStatus, BundleAccount, RevertToSlot, }; - use revm_interpreter::primitives::{keccak256, StorageSlot}; + use revm_interpreter::primitives::keccak256; #[test] fn block_hash_cache() { diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index a233a78ca0..51b27b32b9 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -1,7 +1,7 @@ use crate::interpreter::{InstructionResult, SelfDestructResult}; use crate::primitives::{ - db::Database, hash_map::Entry, Account, Address, Bytecode, EVMError, HashMap, HashSet, Log, - SpecId::*, State, StorageSlot, TransientStorage, KECCAK_EMPTY, PRECOMPILE3, U256, + db::Database, hash_map::Entry, Account, Address, Bytecode, EVMError, EvmState, EvmStorageSlot, + HashMap, HashSet, Log, SpecId::*, TransientStorage, KECCAK_EMPTY, PRECOMPILE3, U256, }; use core::mem; use revm_interpreter::primitives::SpecId; @@ -14,7 +14,7 @@ use std::vec::Vec; #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct JournaledState { /// Current state. - pub state: State, + pub state: EvmState, /// [EIP-1153](https://eips.ethereum.org/EIPS/eip-1153) transient storage that is discarded after every transactions pub transient_storage: TransientStorage, /// logs @@ -62,7 +62,7 @@ impl JournaledState { /// Return reference to state. #[inline] - pub fn state(&mut self) -> &mut State { + pub fn state(&mut self) -> &mut EvmState { &mut self.state } @@ -101,7 +101,7 @@ impl JournaledState { /// /// This resets the [JournaledState] to its initial state in [Self::new] #[inline] - pub fn finalize(&mut self) -> (State, Vec) { + pub fn finalize(&mut self) -> (EvmState, Vec) { let Self { state, transient_storage, @@ -273,7 +273,7 @@ impl JournaledState { // Set all storages to default value. They need to be present to act as accessed slots in access list. // it shouldn't be possible for them to have different values then zero as code is not existing for this account, // but because tests can change that assumption we are doing it. - let empty = StorageSlot::default(); + let empty = EvmStorageSlot::default(); account .storage .iter_mut() @@ -314,7 +314,7 @@ impl JournaledState { /// Revert all changes that happened in given journal entries. #[inline] fn journal_revert( - state: &mut State, + state: &mut EvmState, transient_storage: &mut TransientStorage, journal_entries: Vec, is_spurious_dragon_enabled: bool, @@ -542,7 +542,7 @@ impl JournaledState { for slot in slots { if let Entry::Vacant(entry) = account.storage.entry(*slot) { let storage = db.storage(address, *slot).map_err(EVMError::Database)?; - entry.insert(StorageSlot::new(storage)); + entry.insert(EvmStorageSlot::new(storage)); } } Ok(account) @@ -660,7 +660,7 @@ impl JournaledState { had_value: None, }); - vac.insert(StorageSlot::new(value)); + vac.insert(EvmStorageSlot::new(value)); (value, true) } @@ -692,7 +692,7 @@ impl JournaledState { // new value is same as present, we don't need to do anything if present == new { return Ok(SStoreResult { - original_value: slot.previous_or_original_value, + original_value: slot.original_value(), present_value: present, new_value: new, is_cold, @@ -710,7 +710,7 @@ impl JournaledState { // insert value into present state. slot.present_value = new; Ok(SStoreResult { - original_value: slot.previous_or_original_value, + original_value: slot.original_value(), present_value: present, new_value: new, is_cold, From 6d5256eaa9212e17da5a9fd8e9131fc85a0e7ad9 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 29 May 2024 15:51:52 +0200 Subject: [PATCH 37/88] chore: add test for map_fp_to_g1 precompile (#1465) --- crates/precompile/src/bls12_381/map_fp_to_g1.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) 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 ddbebb379b..26b5987322 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -46,3 +46,19 @@ pub(super) fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { let out = encode_g1_point(&p_aff); Ok((MAP_FP_TO_G1_BASE, out)) } + +#[cfg(test)] +mod test { + use super::*; + use crate::primitives::hex; + + #[test] + fn sanity_test() { + let input = Bytes::from(hex!("000000000000000000000000000000006900000000000000636f6e7472616374595a603f343061cd305a03f40239f5ffff31818185c136bc2595f2aa18e08f17")); + let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE); + assert_eq!( + fail, + Err(PrecompileError::Other("non-canonical fp value".to_string())) + ); + } +} From c844f15641bad0bf5246ccdb4c79a327042ac65e Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 31 May 2024 15:05:38 +0200 Subject: [PATCH 38/88] fix(EOF): returncontract immediate is one byte (#1468) * bug(EOF): returncontract immediate is one byte * rm dependency --- crates/interpreter/src/instructions/contract.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 9e2cd81d2c..1ed0dd11d6 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -7,7 +7,6 @@ use revm_primitives::{keccak256, BerlinSpec}; use crate::{ gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD}, - instructions::utility::read_u16, interpreter::Interpreter, primitives::{Address, Bytes, Eof, Spec, SpecId::*, U256}, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInput, Host, @@ -92,7 +91,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) pub fn return_contract(interpreter: &mut Interpreter, _host: &mut H) { require_init_eof!(interpreter); - let deploy_container_index = unsafe { read_u16(interpreter.instruction_pointer) }; + let deploy_container_index = unsafe { *interpreter.instruction_pointer }; pop!(interpreter, aux_data_offset, aux_data_size); let aux_data_size = as_usize_or_fail!(interpreter, aux_data_size); // important: offset must be ignored if len is zeros From 72c7c40524486090f09411989dded6f1f23ffc71 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 31 May 2024 15:09:32 +0200 Subject: [PATCH 39/88] feat(EOF): Add EOF to inspector handle register (#1469) * feat(EOF): Add EOF to inspector handle register * add comments, remove TODO --- crates/revm/src/inspector.rs | 4 ++ crates/revm/src/inspector/handler_register.rs | 44 +++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 170a42cd26..6fb8eca427 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -135,6 +135,9 @@ pub trait Inspector { outcome } + /// Called when EOF creating is called. + /// + /// This can happen from create TX or from EOFCREATE opcode. fn eofcreate( &mut self, context: &mut EvmContext, @@ -145,6 +148,7 @@ pub trait Inspector { None } + /// Called when eof creating has ended. fn eofcreate_end( &mut self, context: &mut EvmContext, diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 01bc11c577..a0ab7befa1 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -161,7 +161,47 @@ pub fn inspector_handle_register>( }, ); - // TODO(EOF) EOF create call. + // Calls inspector `eofcreate` and `initialize_interp` functions. Queues the inputs for the `eofcreate_end`` function. + // Calls the old handler, and in case of inspector returning outcome, + // returns the outcome without executing eofcreate. + let eofcreate_input_stack_inner = eofcreate_input_stack.clone(); + let old_handle = handler.execution.eofcreate.clone(); + handler.execution.eofcreate = Arc::new( + move |ctx, mut inputs| -> Result> { + // Call inspector to change input or return outcome. + let outcome = ctx + .external + .get_inspector() + .eofcreate(&mut ctx.evm, &mut inputs); + eofcreate_input_stack_inner + .borrow_mut() + .push(inputs.clone()); + if let Some(outcome) = outcome { + return Ok(FrameOrResult::Result(FrameResult::EOFCreate(outcome))); + } + + let mut frame_or_result = old_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }, + ); + + // Pops eofcreate input from the stack and calls inspector `eofcreate_end` function. + // preserve the old handler and calls it with the outcome. + let eofcreate_input_stack_inner = eofcreate_input_stack.clone(); + let old_handle = handler.execution.insert_eofcreate_outcome.clone(); + handler.execution.insert_eofcreate_outcome = Arc::new(move |ctx, frame, mut outcome| { + let create_inputs = eofcreate_input_stack_inner.borrow_mut().pop().unwrap(); + outcome = ctx + .external + .get_inspector() + .eofcreate_end(&mut ctx.evm, &create_inputs, outcome); + old_handle(ctx, frame, outcome) + }); // call outcome let call_input_stack_inner = call_input_stack.clone(); @@ -188,8 +228,6 @@ pub fn inspector_handle_register>( old_handle(ctx, frame, outcome) }); - // TODO(EOF) EOF create handle. - // last frame outcome let old_handle = handler.execution.last_frame_return.clone(); handler.execution.last_frame_return = Arc::new(move |ctx, frame_result| { From 9d49e6a2426900cce5307749cc737697e5598741 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 31 May 2024 15:09:53 +0200 Subject: [PATCH 40/88] fix(stack): pop with five items was not correct (#1472) --- crates/interpreter/src/instructions/macros.rs | 4 ++-- crates/interpreter/src/instructions/system.rs | 7 +++++++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/crates/interpreter/src/instructions/macros.rs b/crates/interpreter/src/instructions/macros.rs index 2592956ec7..6938eeada4 100644 --- a/crates/interpreter/src/instructions/macros.rs +++ b/crates/interpreter/src/instructions/macros.rs @@ -165,7 +165,7 @@ macro_rules! pop { $crate::pop_ret!($interp, $x1, $x2, $x3, $x4, ()) }; ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident, $x5:ident) => { - pop_ret!($interp, $x1, $x2, $x3, $x4, $x5, ()) + $crate::pop_ret!($interp, $x1, $x2, $x3, $x4, $x5, ()) }; } @@ -206,7 +206,7 @@ macro_rules! pop_ret { let ($x1, $x2, $x3, $x4) = unsafe { $interp.stack.pop4_unsafe() }; }; ($interp:expr, $x1:ident, $x2:ident, $x3:ident, $x4:ident, $x5:ident, $ret:expr) => { - if $interp.stack.len() < 4 { + if $interp.stack.len() < 5 { $interp.instruction_result = $crate::InstructionResult::StackUnderflow; return $ret; } diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index 0887a874f4..b00a82f617 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -149,11 +149,18 @@ pub fn returndataload(interpreter: &mut Interpreter, _host: &m gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, offset); let offset_usize = as_usize_or_fail!(interpreter, offset); + // TODO EOF needs to be padded with zeros, it is not correct to fail. + /* + if offset + 32 > len(returndata buffer) the result is zero-padded + (same behavior as CALLDATALOAD).see matching behavior of RETURNDATACOPY + in Modified Behavior section. + */ if offset_usize.saturating_add(32) > interpreter.return_data_buffer.len() { // TODO(EOF) proper error. interpreter.instruction_result = InstructionResult::OutOfOffset; return; } + *offset = B256::from_slice(&interpreter.return_data_buffer[offset_usize..offset_usize + 32]).into(); } From fadf6fbe43a3022c1406c0d8ee062a83e951d4d3 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 31 May 2024 15:23:11 +0200 Subject: [PATCH 41/88] fix(eof): EOFCREATE spend gas and apply 63/64 rule (#1471) --- crates/interpreter/src/instructions/contract.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 1ed0dd11d6..555b5e2876 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -74,6 +74,10 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) .caller .create2(salt.to_be_bytes(), keccak256(sub_container)); + let gas_reduce = max(interpreter.gas.remaining() / 64, 5000); + let gas_limit = interpreter.gas().remaining().saturating_sub(gas_reduce); + gas!(interpreter, gas_limit); + // Send container for execution container is preverified. interpreter.next_action = InterpreterAction::EOFCreate { inputs: Box::new(EOFCreateInput::new( @@ -81,7 +85,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) created_address, value, eof, - interpreter.gas().remaining(), + gas_limit, return_range, )), }; From 6df5d208a04a784fe511186cc0523d98d6e283cf Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 1 Jun 2024 23:25:35 +0300 Subject: [PATCH 42/88] chore(interpreter): use max gas limit in `impl Default for Interpreter` (#1478) --- crates/interpreter/src/interpreter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index a27752b2e8..66d12ff9e1 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -64,7 +64,7 @@ pub struct Interpreter { impl Default for Interpreter { fn default() -> Self { - Self::new(Contract::default(), 0, false) + Self::new(Contract::default(), u64::MAX, false) } } From c083b05b659aef198f891aa035dc3b0304b9f735 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 23:50:38 +0200 Subject: [PATCH 43/88] chore(deps): bump tokio from 1.37.0 to 1.38.0 (#1480) Bumps [tokio](https://github.com/tokio-rs/tokio) from 1.37.0 to 1.38.0. - [Release notes](https://github.com/tokio-rs/tokio/releases) - [Commits](https://github.com/tokio-rs/tokio/compare/tokio-1.37.0...tokio-1.38.0) --- updated-dependencies: - dependency-name: tokio dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- crates/revm/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8250353bfa..43543b6f0b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3878,9 +3878,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.37.0" +version = "1.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" dependencies = [ "backtrace", "bytes", @@ -3895,9 +3895,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 1a93a83d19..2691d02f0d 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -41,7 +41,7 @@ serde_json = { version = "1.0", default-features = false, features = [ ], optional = true } # ethersdb -tokio = { version = "1.37", features = [ +tokio = { version = "1.38", features = [ "rt-multi-thread", "macros", ], optional = true } From b8123b5a721106932f0f2e661387e41e26bdc84e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 23:51:02 +0200 Subject: [PATCH 44/88] chore(deps): bump blst from 0.3.11 to 0.3.12 (#1481) Bumps [blst](https://github.com/supranational/blst) from 0.3.11 to 0.3.12. - [Release notes](https://github.com/supranational/blst/releases) - [Commits](https://github.com/supranational/blst/compare/v0.3.11...v0.3.12) --- updated-dependencies: - dependency-name: blst dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- crates/precompile/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43543b6f0b..d578d16fb2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -711,9 +711,9 @@ dependencies = [ [[package]] name = "blst" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c94087b935a822949d3291a9989ad2b2051ea141eda0fd4e478a75f6aa3e604b" +checksum = "62dc83a094a71d43eeadd254b1ec2d24cb6a0bb6cadce00df51f0db594711a32" dependencies = [ "cc", "glob", diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 08abf55bb6..b9e0bd141f 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -42,7 +42,7 @@ secp256k1 = { version = "0.29.0", default-features = false, features = [ ], optional = true } # BLS12-381 precompiles -blst = { version = "0.3.11", optional = true } +blst = { version = "0.3.12", optional = true } # p256verify precompile p256 = { version = "0.13.2", optional = true, default-features = false, features = ["ecdsa"] } From 916458c362a6cb837d8962e685924d554bac9828 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Jun 2024 23:51:27 +0200 Subject: [PATCH 45/88] chore(deps): bump rstest from 0.19.0 to 0.21.0 (#1482) Bumps [rstest](https://github.com/la10736/rstest) from 0.19.0 to 0.21.0. - [Release notes](https://github.com/la10736/rstest/releases) - [Changelog](https://github.com/la10736/rstest/blob/master/CHANGELOG.md) - [Commits](https://github.com/la10736/rstest/compare/v0.19.0...v0.21.0) --- updated-dependencies: - dependency-name: rstest dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 9 +++++---- crates/precompile/Cargo.toml | 2 +- crates/revm/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d578d16fb2..b1717751ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3134,9 +3134,9 @@ dependencies = [ [[package]] name = "rstest" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5316d2a1479eeef1ea21e7f9ddc67c191d497abc8fc3ba2467857abbb68330" +checksum = "9afd55a67069d6e434a95161415f5beeada95a01c7b815508a82dcb0e1593682" dependencies = [ "futures", "futures-timer", @@ -3146,12 +3146,13 @@ dependencies = [ [[package]] name = "rstest_macros" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04a9df72cc1f67020b0d63ad9bfe4a323e459ea7eb68e03bd9824db49f9a4c25" +checksum = "4165dfae59a39dd41d8dec720d3cbfbc71f69744efb480a3920f5d4e0cc6798d" dependencies = [ "cfg-if", "glob", + "proc-macro-crate", "proc-macro2", "quote", "regex", diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index b9e0bd141f..7a5c81e6a8 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -51,7 +51,7 @@ p256 = { version = "0.13.2", optional = true, default-features = false, feature criterion = { version = "0.5" } rand = { version = "0.8", features = ["std"] } eyre = "0.6.12" -rstest = "0.19.0" +rstest = "0.21.0" serde = "1.0" serde_json = "1.0" serde_derive = "1.0" diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 2691d02f0d..4655f27a33 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -62,7 +62,7 @@ anyhow = "1.0.83" criterion = "0.5" indicatif = "0.17" reqwest = { version = "0.12" } -rstest = "0.19.0" +rstest = "0.21.0" alloy-provider = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d", default-features = false, features = [ "reqwest", From b7b92aee232558ea48e9580bfac74d442a17babd Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 3 Jun 2024 23:52:54 +0200 Subject: [PATCH 46/88] feat(EOF): EIP-7698 eof creation transaction (#1467) * feat(EOF): eof tx create * cleanup * add box import * fix(eof): add FrameResult if eof is in create tx * Make returncontract a success, enabled by eof tx create * fix build, add case --- crates/interpreter/src/instruction_result.rs | 5 +- .../interpreter/src/instructions/contract.rs | 43 ++++-------- .../src/instructions/contract/call_helpers.rs | 6 +- crates/interpreter/src/interpreter.rs | 33 +++++---- .../interpreter_action/eof_create_inputs.rs | 34 ++++++++-- .../interpreter_action/eof_create_outcome.rs | 21 +----- crates/primitives/src/bytecode/eof.rs | 56 +++++++++++++++ crates/primitives/src/bytecode/eof/header.rs | 5 +- crates/primitives/src/result.rs | 1 + crates/revm/src/context.rs | 2 + crates/revm/src/context/inner_evm_context.rs | 4 +- crates/revm/src/evm.rs | 68 +++++++++++++++++-- crates/revm/src/frame.rs | 14 +--- crates/revm/src/handler/mainnet/execution.rs | 1 - 14 files changed, 198 insertions(+), 95 deletions(-) diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index 9e0f6e1264..121e12ead7 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -61,6 +61,7 @@ impl From for InstructionResult { SuccessReason::Return => InstructionResult::Return, SuccessReason::Stop => InstructionResult::Stop, SuccessReason::SelfDestruct => InstructionResult::SelfDestruct, + SuccessReason::EofReturnContract => InstructionResult::ReturnContract, } } } @@ -269,9 +270,7 @@ impl From for SuccessOrHalt { InstructionResult::FatalExternalError => Self::FatalExternalError, InstructionResult::EOFOpcodeDisabledInLegacy => Self::Halt(HaltReason::OpcodeNotFound), InstructionResult::EOFFunctionStackOverflow => Self::FatalExternalError, - InstructionResult::ReturnContract => { - panic!("Unexpected EOF internal Return Contract") - } + InstructionResult::ReturnContract => Self::Success(SuccessReason::EofReturnContract), } } } diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 555b5e2876..206891e962 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -1,8 +1,6 @@ mod call_helpers; -pub use call_helpers::{ - calc_call_gas, get_memory_input_and_out_ranges, resize_memory_and_return_range, -}; +pub use call_helpers::{calc_call_gas, get_memory_input_and_out_ranges, resize_memory}; use revm_primitives::{keccak256, BerlinSpec}; use crate::{ @@ -12,29 +10,9 @@ use crate::{ CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInput, Host, InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE, }; -use core::{cmp::max, ops::Range}; +use core::cmp::max; use std::boxed::Box; -/// Resize memory and return memory range if successful. -/// Return `None` if there is not enough gas. And if `len` -/// is zero return `Some(usize::MAX..usize::MAX)`. -pub fn resize_memory( - interpreter: &mut Interpreter, - offset: U256, - len: U256, -) -> Option> { - let len = as_usize_or_fail_ret!(interpreter, len, None); - if len != 0 { - let offset = as_usize_or_fail_ret!(interpreter, offset, None); - resize_memory!(interpreter, offset, len, None); - // range is checked in resize_memory! macro and it is bounded by usize. - Some(offset..offset + len) - } else { - //unrealistic value so we are sure it is not used - Some(usize::MAX..usize::MAX) - } -} - /// EOF Create instruction pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) { require_eof!(interpreter); @@ -52,10 +30,20 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) .expect("EOF is checked"); // resize memory and get return range. - let Some(return_range) = resize_memory(interpreter, data_offset, data_size) else { + let Some(input_range) = resize_memory(interpreter, data_offset, data_size) else { return; }; + let input = if !input_range.is_empty() { + interpreter + .shared_memory + .slice_range(input_range) + .to_vec() + .into() + } else { + Bytes::new() + }; + let eof = Eof::decode(sub_container.clone()).expect("Subcontainer is verified"); if !eof.body.is_data_filled { @@ -86,7 +74,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) value, eof, gas_limit, - return_range, + input, )), }; @@ -150,8 +138,7 @@ pub fn return_contract(interpreter: &mut Interpreter, _host: & pub fn extcall_input(interpreter: &mut Interpreter) -> Option { pop_ret!(interpreter, input_offset, input_size, None); - let return_memory_offset = - resize_memory_and_return_range(interpreter, input_offset, input_size)?; + let return_memory_offset = resize_memory(interpreter, input_offset, input_size)?; Some(Bytes::copy_from_slice( interpreter diff --git a/crates/interpreter/src/instructions/contract/call_helpers.rs b/crates/interpreter/src/instructions/contract/call_helpers.rs index 5570efe3ac..f9acc74901 100644 --- a/crates/interpreter/src/instructions/contract/call_helpers.rs +++ b/crates/interpreter/src/instructions/contract/call_helpers.rs @@ -11,21 +11,21 @@ pub fn get_memory_input_and_out_ranges( ) -> Option<(Bytes, Range)> { pop_ret!(interpreter, in_offset, in_len, out_offset, out_len, None); - let in_range = resize_memory_and_return_range(interpreter, in_offset, in_len)?; + let in_range = resize_memory(interpreter, in_offset, in_len)?; let mut input = Bytes::new(); if !in_range.is_empty() { input = Bytes::copy_from_slice(interpreter.shared_memory.slice_range(in_range)); } - let ret_range = resize_memory_and_return_range(interpreter, out_offset, out_len)?; + let ret_range = resize_memory(interpreter, out_offset, out_len)?; Some((input, ret_range)) } /// Resize memory and return range of memory. /// If `len` is 0 dont touch memory and return `usize::MAX` as offset and 0 as length. #[inline] -pub fn resize_memory_and_return_range( +pub fn resize_memory( interpreter: &mut Interpreter, offset: U256, len: U256, diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 66d12ff9e1..219b2e8f9c 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -68,18 +68,6 @@ impl Default for Interpreter { } } -/// The result of an interpreter operation. -#[derive(Clone, Debug, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] -pub struct InterpreterResult { - /// The result of the instruction execution. - pub result: InstructionResult, - /// The output of the instruction execution. - pub output: Bytes, - /// The gas usage information. - pub gas: Gas, -} - impl Interpreter { /// Create new interpreter pub fn new(contract: Contract, gas_limit: u64, is_static: bool) -> Self { @@ -388,7 +376,28 @@ impl Interpreter { } } +/// The result of an interpreter operation. +#[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(::serde::Serialize, ::serde::Deserialize))] +pub struct InterpreterResult { + /// The result of the instruction execution. + pub result: InstructionResult, + /// The output of the instruction execution. + pub output: Bytes, + /// The gas usage information. + pub gas: Gas, +} + impl InterpreterResult { + /// Returns a new `InterpreterResult` with the given values. + pub fn new(result: InstructionResult, output: Bytes, gas: Gas) -> Self { + Self { + result, + output, + gas, + } + } + /// Returns whether the instruction result is a success. #[inline] pub const fn is_ok(&self) -> bool { diff --git a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs index 25dac1e046..28a1a471b9 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs @@ -1,5 +1,5 @@ -use crate::primitives::{Address, Eof, U256}; -use core::ops::Range; +use crate::primitives::{eof::EofDecodeError, Address, Bytes, Eof, TxEnv, U256}; +use std::boxed::Box; /// Inputs for EOF create call. #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -13,14 +13,34 @@ pub struct EOFCreateInput { pub value: U256, /// Init eof code that is going to be executed. pub eof_init_code: Eof, + /// Call data the input of the EOFCREATE call. + pub input: Bytes, /// Gas limit for the create call. pub gas_limit: u64, - /// Return memory range. If EOF creation Reverts it can return the - /// the memory range. - pub return_memory_range: Range, } impl EOFCreateInput { + /// Returns boxed EOFCreateInput or error. + /// Internally calls [`Self::new_tx`]. + pub fn new_tx_boxed(tx: &TxEnv, nonce: u64) -> Result, EofDecodeError> { + Ok(Box::new(Self::new_tx(tx, nonce)?)) + } + + /// Create new EOF crate input from transaction that has concatenated eof init code and calldata. + /// + /// Legacy transaction still have optional nonce so we need to obtain it. + pub fn new_tx(tx: &TxEnv, nonce: u64) -> Result { + let (eof_init_code, input) = Eof::decode_dangling(tx.data.clone())?; + Ok(EOFCreateInput { + caller: tx.caller, + created_address: tx.caller.create(nonce), + value: tx.value, + eof_init_code, + gas_limit: tx.gas_limit, + input, + }) + } + /// Returns a new instance of EOFCreateInput. pub fn new( caller: Address, @@ -28,7 +48,7 @@ impl EOFCreateInput { value: U256, eof_init_code: Eof, gas_limit: u64, - return_memory_range: Range, + input: Bytes, ) -> EOFCreateInput { EOFCreateInput { caller, @@ -36,7 +56,7 @@ impl EOFCreateInput { value, eof_init_code, gas_limit, - return_memory_range, + input, } } } diff --git a/crates/interpreter/src/interpreter_action/eof_create_outcome.rs b/crates/interpreter/src/interpreter_action/eof_create_outcome.rs index 9ec669a070..beeda24e50 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_outcome.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_outcome.rs @@ -1,5 +1,3 @@ -use core::ops::Range; - use crate::{Gas, InstructionResult, InterpreterResult}; use revm_primitives::{Address, Bytes}; @@ -14,8 +12,6 @@ pub struct EOFCreateOutcome { pub result: InterpreterResult, /// An optional address associated with the create operation. pub address: Address, - /// Return memory range. If EOF creation Reverts it can return bytes from the memory. - pub return_memory_range: Range, } impl EOFCreateOutcome { @@ -30,16 +26,8 @@ impl EOFCreateOutcome { /// # Returns /// /// A new [`EOFCreateOutcome`] instance. - pub fn new( - result: InterpreterResult, - address: Address, - return_memory_range: Range, - ) -> Self { - Self { - result, - address, - return_memory_range, - } + pub fn new(result: InterpreterResult, address: Address) -> Self { + Self { result, address } } /// Retrieves a reference to the [`InstructionResult`] from the [`InterpreterResult`]. @@ -80,9 +68,4 @@ impl EOFCreateOutcome { pub fn gas(&self) -> &Gas { &self.result.gas } - - /// Returns the memory range that Revert bytes are going to be written. - pub fn return_range(&self) -> Range { - self.return_memory_range.clone() - } } diff --git a/crates/primitives/src/bytecode/eof.rs b/crates/primitives/src/bytecode/eof.rs index 67580c1577..3f78bc26da 100644 --- a/crates/primitives/src/bytecode/eof.rs +++ b/crates/primitives/src/bytecode/eof.rs @@ -76,6 +76,26 @@ impl Eof { buffer.into() } + /// Decode EOF that have additional dangling bytes. + /// Assume that data section is fully filled. + pub fn decode_dangling(mut eof: Bytes) -> Result<(Self, Bytes), EofDecodeError> { + let (header, _) = EofHeader::decode(&eof)?; + let eof_size = header.body_size() + header.size(); + if eof_size > eof.len() { + return Err(EofDecodeError::MissingInput); + } + let dangling_data = eof.split_off(eof_size); + let body = EofBody::decode(&eof, &header)?; + Ok(( + Self { + header, + body, + raw: eof, + }, + dangling_data, + )) + } + /// Decode EOF from raw bytes. pub fn decode(raw: Bytes) -> Result { let (header, _) = EofHeader::decode(&raw)?; @@ -140,6 +160,42 @@ mod test { assert_eq!(bytes, eof.encode_slow()); } + #[test] + fn decode_eof_dangling() { + let test_cases = [ + ( + bytes!("ef000101000402000100010400000000800000fe"), + bytes!("010203"), + false, + ), + ( + bytes!("ef000101000402000100010400000000800000fe"), + bytes!(""), + false, + ), + ( + bytes!("ef000101000402000100010400000000800000"), + bytes!(""), + true, + ), + ]; + + for (eof_bytes, dangling_data, is_err) in test_cases { + let mut raw = eof_bytes.to_vec(); + raw.extend(&dangling_data); + let raw = Bytes::from(raw); + + let result = Eof::decode_dangling(raw.clone()); + assert_eq!(result.is_err(), is_err); + if is_err { + continue; + } + let (decoded_eof, decoded_dangling) = result.unwrap(); + assert_eq!(eof_bytes, decoded_eof.encode_slow()); + assert_eq!(decoded_dangling, dangling_data); + } + } + #[test] fn data_slice() { let bytes = bytes!("ef000101000402000100010400000000800000fe"); diff --git a/crates/primitives/src/bytecode/eof/header.rs b/crates/primitives/src/bytecode/eof/header.rs index bd7a33d7b7..1074f066a4 100644 --- a/crates/primitives/src/bytecode/eof/header.rs +++ b/crates/primitives/src/bytecode/eof/header.rs @@ -90,7 +90,10 @@ impl EofHeader { /// Returns body size. It is sum of code sizes, container sizes and data size. pub fn body_size(&self) -> usize { - self.sum_code_sizes + self.sum_container_sizes + self.data_size as usize + self.types_size as usize + + self.sum_code_sizes + + self.sum_container_sizes + + self.data_size as usize } /// Returns raw size of the EOF. diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 438451e2a9..36cd0db90d 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -388,6 +388,7 @@ pub enum SuccessReason { Stop, Return, SelfDestruct, + EofReturnContract, } /// Indicates that the EVM has experienced an exceptional halt. This causes execution to diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 6cdbdfe6fa..40107651cb 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -98,6 +98,8 @@ where } impl Host for Context { + /// Returns reference to Environment. + #[inline] fn env(&self) -> &Env { &self.evm.env } diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 109b16a7a6..d12e90c148 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -239,7 +239,6 @@ impl InnerEvmContext { output: Bytes::new(), }, inputs.created_address, - inputs.return_memory_range.clone(), )) }; @@ -280,7 +279,7 @@ impl InnerEvmContext { }; let contract = Contract::new( - Bytes::new(), + inputs.input.clone(), // fine to clone as it is Bytes. Bytecode::Eof(inputs.eof_init_code.clone()), None, @@ -295,7 +294,6 @@ impl InnerEvmContext { Ok(FrameOrResult::new_eofcreate_frame( inputs.created_address, - inputs.return_memory_range.clone(), checkpoint, interpreter, )) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 2fcf932452..bebd7bc57b 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -2,15 +2,17 @@ use crate::{ builder::{EvmBuilder, HandlerStage, SetGenericStage}, db::{Database, DatabaseCommit, EmptyDB}, handler::Handler, - interpreter::{Host, InterpreterAction, SharedMemory}, + interpreter::{ + analysis::validate_eof, CallInputs, CreateInputs, EOFCreateInput, EOFCreateOutcome, Gas, + Host, InstructionResult, InterpreterAction, InterpreterResult, SharedMemory, + }, primitives::{ - specification::SpecId, BlockEnv, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, + specification::SpecId, BlockEnv, Bytes, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, ExecutionResult, HandlerCfg, ResultAndState, TransactTo, TxEnv, }, Context, ContextWithHandlerCfg, Frame, FrameOrResult, FrameResult, }; use core::fmt; -use revm_interpreter::{CallInputs, CreateInputs}; use std::vec::Vec; /// EVM call stack limit. @@ -324,6 +326,7 @@ impl Evm<'_, EXT, DB> { /// Transact pre-verified transaction. fn transact_preverified_inner(&mut self, initial_gas_spend: u64) -> EVMResult { + let spec_id = self.spec_id(); let ctx = &mut self.context; let pre_exec = self.handler.pre_execution(); @@ -346,10 +349,61 @@ impl Evm<'_, EXT, DB> { ctx, CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), )?, - TransactTo::Create => exec.create( - ctx, - CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), - )?, + TransactTo::Create => { + // if first byte of data is magic 0xEF00, then it is EOFCreate. + if spec_id.is_enabled_in(SpecId::PRAGUE) + && ctx + .env() + .tx + .data + .get(0..=1) + .filter(|&t| t == [0xEF, 00]) + .is_some() + { + // TODO Should we just check 0xEF it seems excessive to switch to legacy only + // if it 0xEF00? + + // get nonce from tx (if set) or from account (if not). + // Nonce for call is bumped in deduct_caller while + // for CREATE it is not (it is done inside exec handlers). + let nonce = ctx.evm.env.tx.nonce.unwrap_or_else(|| { + let caller = ctx.evm.env.tx.caller; + ctx.evm + .load_account(caller) + .map(|(a, _)| a.info.nonce) + .unwrap_or_default() + }); + + // Create EOFCreateInput from transaction initdata. + let eofcreate = EOFCreateInput::new_tx_boxed(&ctx.evm.env.tx, nonce) + .ok() + .and_then(|eofcreate| { + // validate EOF initcode + validate_eof(&eofcreate.eof_init_code).ok()?; + Some(eofcreate) + }); + + if let Some(eofcreate) = eofcreate { + exec.eofcreate(ctx, eofcreate)? + } else { + // Return result, as code is invalid. + FrameOrResult::Result(FrameResult::EOFCreate(EOFCreateOutcome::new( + InterpreterResult::new( + InstructionResult::Stop, + Bytes::new(), + Gas::new(gas_limit), + ), + ctx.env().tx.caller.create(nonce), + ))) + } + } else { + // Safe to unwrap because we are sure that it is create tx. + exec.create( + ctx, + CreateInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), + )? + } + } }; // Starts the main running loop. diff --git a/crates/revm/src/frame.rs b/crates/revm/src/frame.rs index 7257650581..1988705ab1 100644 --- a/crates/revm/src/frame.rs +++ b/crates/revm/src/frame.rs @@ -33,7 +33,6 @@ pub struct CreateFrame { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct EOFCreateFrame { pub created_address: Address, - pub return_memory_range: Range, pub frame_data: FrameData, } @@ -81,8 +80,8 @@ impl FrameResult { FrameResult::Create(outcome) => { Output::Create(outcome.result.output.clone(), outcome.address) } - FrameResult::EOFCreate(_) => { - panic!("EOFCreate can't be called from external world."); + FrameResult::EOFCreate(outcome) => { + Output::Create(outcome.result.output.clone(), Some(outcome.address)) } } } @@ -240,13 +239,11 @@ impl FrameOrResult { pub fn new_eofcreate_frame( created_address: Address, - return_memory_range: Range, checkpoint: JournalCheckpoint, interpreter: Interpreter, ) -> Self { Self::Frame(Frame::EOFCreate(Box::new(EOFCreateFrame { created_address, - return_memory_range, frame_data: FrameData { checkpoint, interpreter, @@ -278,15 +275,10 @@ impl FrameOrResult { })) } - pub fn new_eofcreate_result( - interpreter_result: InterpreterResult, - address: Address, - return_memory_range: Range, - ) -> Self { + pub fn new_eofcreate_result(interpreter_result: InterpreterResult, address: Address) -> Self { FrameOrResult::Result(FrameResult::EOFCreate(EOFCreateOutcome { result: interpreter_result, address, - return_memory_range, })) } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 9e1ff3ef54..e55d6c4474 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -183,7 +183,6 @@ pub fn eofcreate_return( Ok(EOFCreateOutcome::new( interpreter_result, frame.created_address, - frame.return_memory_range, )) } From 3ae8ff2b0a11da14edc4085fe738db36a760a436 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:56:45 +0200 Subject: [PATCH 47/88] chore(deps): allow multiple versions of secp256k1 (#1490) --- crates/precompile/Cargo.toml | 31 +++++++++++++++++++------------ crates/precompile/src/lib.rs | 4 ++-- 2 files changed, 21 insertions(+), 14 deletions(-) diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 7a5c81e6a8..097985edca 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -22,33 +22,40 @@ all = "warn" [dependencies] revm-primitives = { path = "../primitives", version = "4.0.0", default-features = false } -bn = { package = "substrate-bn", version = "0.6", default-features = false } once_cell = { version = "1.19", default-features = false, features = ["alloc"] } -ripemd = { version = "0.1", default-features = false } -sha2 = { version = "0.10", default-features = false } -# modexp precompile -aurora-engine-modexp = { version = "1.1", default-features = false } -# Optional KZG point evaluation precompile -c-kzg = { version = "1.0.2", default-features = false, optional = true } - -# ecRecover precompile +# ecRecover k256 = { version = "0.13.3", default-features = false, features = ["ecdsa"] } -secp256k1 = { version = "0.29.0", default-features = false, features = [ +secp256k1 = { version = ">=0.28, <=0.29", default-features = false, features = [ "alloc", "recovery", "rand", "global-context", ], optional = true } +# SHA2-256 and RIPEMD-160 +sha2 = { version = "0.10", default-features = false } +ripemd = { version = "0.1", default-features = false } + +# modexp +aurora-engine-modexp = { version = "1.1", default-features = false } + +# ecAdd, ecMul, ecPairing +bn = { package = "substrate-bn", version = "0.6", default-features = false } + +# KZG point evaluation precompile +c-kzg = { version = "1.0.2", default-features = false, optional = true } + # BLS12-381 precompiles blst = { version = "0.3.12", optional = true } # p256verify precompile -p256 = { version = "0.13.2", optional = true, default-features = false, features = ["ecdsa"] } +p256 = { version = "0.13.2", optional = true, default-features = false, features = [ + "ecdsa", +] } [dev-dependencies] -criterion = { version = "0.5" } +criterion = "0.5" rand = { version = "0.8", features = ["std"] } eyre = "0.6.12" rstest = "0.21.0" diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index ca797c8118..a6c57a44a0 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -111,12 +111,12 @@ impl Precompiles { INSTANCE.get_or_init(|| { let mut precompiles = Self::byzantium().clone(); precompiles.extend([ - // EIP-152: Add BLAKE2 compression function `F` precompile. - blake2::FUN, // EIP-1108: Reduce alt_bn128 precompile gas costs. bn128::add::ISTANBUL, bn128::mul::ISTANBUL, bn128::pair::ISTANBUL, + // EIP-152: Add BLAKE2 compression function `F` precompile. + blake2::FUN, ]); Box::new(precompiles) }) From 22e15d396cffbaee7cca3e324c480b02913bf1c3 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Thu, 6 Jun 2024 15:57:16 +0200 Subject: [PATCH 48/88] chore: remove old deprecated items (#1489) --- crates/interpreter/src/gas.rs | 7 ------ crates/primitives/src/db.rs | 40 ----------------------------------- crates/revm/src/db/emptydb.rs | 6 ------ 3 files changed, 53 deletions(-) diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index ac0af3079d..01a3ebeafe 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -66,13 +66,6 @@ impl Gas { self.limit - self.remaining } - #[doc(hidden)] - #[inline] - #[deprecated(note = "use `spent` instead")] - pub const fn spend(&self) -> u64 { - self.spent() - } - /// Returns the amount of gas remaining. #[inline] pub const fn remaining(&self) -> u64 { diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index 3b1c6dc803..ca4ced987b 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -103,43 +103,3 @@ impl DatabaseCommit for WrapDatabaseRef { self.0.commit(changes) } } - -/// Wraps a `dyn DatabaseRef` to provide a [`Database`] implementation. -#[doc(hidden)] -#[deprecated = "use `WrapDatabaseRef` instead"] -pub struct RefDBWrapper<'a, E> { - pub db: &'a dyn DatabaseRef, -} - -#[allow(deprecated)] -impl<'a, E> RefDBWrapper<'a, E> { - #[inline] - pub fn new(db: &'a dyn DatabaseRef) -> Self { - Self { db } - } -} - -#[allow(deprecated)] -impl<'a, E> Database for RefDBWrapper<'a, E> { - type Error = E; - - #[inline] - fn basic(&mut self, address: Address) -> Result, Self::Error> { - self.db.basic_ref(address) - } - - #[inline] - fn code_by_hash(&mut self, code_hash: B256) -> Result { - self.db.code_by_hash_ref(code_hash) - } - - #[inline] - fn storage(&mut self, address: Address, index: U256) -> Result { - self.db.storage_ref(address, index) - } - - #[inline] - fn block_hash(&mut self, number: U256) -> Result { - self.db.block_hash_ref(number) - } -} diff --git a/crates/revm/src/db/emptydb.rs b/crates/revm/src/db/emptydb.rs index 9911612837..23598e8ca7 100644 --- a/crates/revm/src/db/emptydb.rs +++ b/crates/revm/src/db/emptydb.rs @@ -51,12 +51,6 @@ impl EmptyDBTyped { _phantom: PhantomData, } } - - #[doc(hidden)] - #[deprecated = "use `new` instead"] - pub fn new_keccak_block_hash() -> Self { - Self::new() - } } impl Database for EmptyDBTyped { From bdd1b8e666226ec658c45f36768e9399c4971b97 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 7 Jun 2024 16:43:18 +0200 Subject: [PATCH 49/88] fix(EOF): panic on empty input range, and continue exec after eofcreate (#1477) * reset instruction result * switch extcall value order * fix empty input * revert value pop --- crates/interpreter/src/instructions/contract.rs | 4 ++++ crates/interpreter/src/interpreter.rs | 1 + crates/revm/src/evm.rs | 1 - crates/revm/src/frame.rs | 2 ++ 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 206891e962..4c0b13ed1a 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -140,6 +140,10 @@ pub fn extcall_input(interpreter: &mut Interpreter) -> Option { let return_memory_offset = resize_memory(interpreter, input_offset, input_size)?; + if return_memory_offset.is_empty() { + return Some(Bytes::new()); + } + Some(Bytes::copy_from_slice( interpreter .shared_memory diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 219b2e8f9c..ef000be132 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -192,6 +192,7 @@ impl Interpreter { } pub fn insert_eofcreate_outcome(&mut self, create_outcome: EOFCreateOutcome) { + self.instruction_result = InstructionResult::Continue; let instruction_result = create_outcome.instruction_result(); self.return_data_buffer = if *instruction_result == InstructionResult::Revert { diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index bebd7bc57b..80d536598d 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -134,7 +134,6 @@ impl<'a, EXT, DB: Database> Evm<'a, EXT, DB> { } InterpreterAction::None => unreachable!("InterpreterAction::None is not expected"), }; - // handle result match frame_or_result { FrameOrResult::Frame(frame) => { diff --git a/crates/revm/src/frame.rs b/crates/revm/src/frame.rs index 1988705ab1..c36ffe0707 100644 --- a/crates/revm/src/frame.rs +++ b/crates/revm/src/frame.rs @@ -55,6 +55,7 @@ pub enum Frame { } #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug)] pub enum FrameResult { Call(CallOutcome), Create(CreateOutcome), @@ -135,6 +136,7 @@ impl FrameResult { /// Contains either a frame or a result. #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[derive(Debug)] pub enum FrameOrResult { /// Boxed call or create frame. Frame(Frame), From 569c981891511188535c9b9541427fd4f64336e1 Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Fri, 7 Jun 2024 16:34:46 -0400 Subject: [PATCH 50/88] chore: derive PartialEq and Hash on EnvKzgSettings (#1494) --- crates/primitives/src/kzg/env_settings.rs | 24 +---------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/crates/primitives/src/kzg/env_settings.rs b/crates/primitives/src/kzg/env_settings.rs index 849ec3c463..d9b5f24350 100644 --- a/crates/primitives/src/kzg/env_settings.rs +++ b/crates/primitives/src/kzg/env_settings.rs @@ -2,13 +2,12 @@ use super::{ trusted_setup_points::{G1_POINTS, G2_POINTS}, KzgSettings, }; -use core::hash::{Hash, Hasher}; use once_cell::race::OnceBox; use std::{boxed::Box, sync::Arc}; /// KZG Settings that allow us to specify a custom trusted setup. /// or use hardcoded default settings. -#[derive(Debug, Clone, Default, Eq)] +#[derive(Debug, Clone, Default, PartialEq, Eq, Hash)] pub enum EnvKzgSettings { /// Default mainnet trusted setup #[default] @@ -17,27 +16,6 @@ pub enum EnvKzgSettings { Custom(Arc), } -// Implement PartialEq and Hash manually because `c_kzg::KzgSettings` does not implement them -impl PartialEq for EnvKzgSettings { - fn eq(&self, other: &Self) -> bool { - match (self, other) { - (Self::Default, Self::Default) => true, - (Self::Custom(a), Self::Custom(b)) => Arc::ptr_eq(a, b), - _ => false, - } - } -} - -impl Hash for EnvKzgSettings { - fn hash(&self, state: &mut H) { - core::mem::discriminant(self).hash(state); - match self { - Self::Default => {} - Self::Custom(settings) => Arc::as_ptr(settings).hash(state), - } - } -} - impl EnvKzgSettings { /// Return set KZG settings. /// From 9955d9faa5ca4cefc30bde3eb37ba11af7ef474d Mon Sep 17 00:00:00 2001 From: frisitano <35734660+frisitano@users.noreply.github.com> Date: Sat, 8 Jun 2024 17:15:01 +0400 Subject: [PATCH 51/88] feat: Persist reverted account and storage slot lookups in `JournaledState` (#1437) * persist reverted account and storage slot lookups * journal cold loads from occupied journaled state entry --- crates/primitives/src/state.rs | 51 ++++++++++++++++++++++++ crates/revm/src/journaled_state.rs | 62 +++++++++++++++++++----------- 2 files changed, 90 insertions(+), 23 deletions(-) diff --git a/crates/primitives/src/state.rs b/crates/primitives/src/state.rs index 37315d3b68..d1f6c9df46 100644 --- a/crates/primitives/src/state.rs +++ b/crates/primitives/src/state.rs @@ -41,6 +41,8 @@ bitflags! { /// used only for pre spurious dragon hardforks where existing and empty were two separate states. /// it became same state after EIP-161: State trie clearing const LoadedAsNotExisting = 0b0001000; + /// used to mark account as cold + const Cold = 0b0010000; } } @@ -100,6 +102,21 @@ impl Account { self.status -= AccountStatus::Created; } + /// Mark account as cold. + pub fn mark_cold(&mut self) { + self.status |= AccountStatus::Cold; + } + + /// Mark account as warm and return true if it was previously cold. + pub fn mark_warm(&mut self) -> bool { + if self.status.contains(AccountStatus::Cold) { + self.status -= AccountStatus::Cold; + true + } else { + false + } + } + /// Is account loaded as not existing from database /// This is needed for pre spurious dragon hardforks where /// existing and empty were two separate states. @@ -143,6 +160,8 @@ pub struct EvmStorageSlot { pub original_value: U256, /// Present value of the storage slot. pub present_value: U256, + /// Represents if the storage slot is cold. + pub is_cold: bool, } impl EvmStorageSlot { @@ -151,6 +170,7 @@ impl EvmStorageSlot { Self { original_value: original, present_value: original, + is_cold: false, } } @@ -159,6 +179,7 @@ impl EvmStorageSlot { Self { original_value, present_value, + is_cold: false, } } /// Returns true if the present value differs from the original value @@ -175,6 +196,16 @@ impl EvmStorageSlot { pub fn present_value(&self) -> U256 { self.present_value } + + /// Marks the storage slot as cold. + pub fn mark_cold(&mut self) { + self.is_cold = true; + } + + /// Marks the storage slot as warm and returns a bool indicating if it was previously cold. + pub fn mark_warm(&mut self) -> bool { + core::mem::replace(&mut self.is_cold, false) + } } /// AccountInfo account information. @@ -343,4 +374,24 @@ mod tests { assert!(account.is_touched()); assert!(!account.is_selfdestructed()); } + + #[test] + fn account_is_cold() { + let mut account = Account::default(); + + // Account is not cold by default + assert!(!account.status.contains(crate::AccountStatus::Cold)); + + // When marking warm account as warm again, it should return false + assert!(!account.mark_warm()); + + // Mark account as cold + account.mark_cold(); + + // Account is cold + assert!(account.status.contains(crate::AccountStatus::Cold)); + + // When marking cold account as warm, it should return true + assert!(account.mark_warm()); + } } diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index 51b27b32b9..44ad44b958 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -322,7 +322,7 @@ impl JournaledState { for entry in journal_entries.into_iter().rev() { match entry { JournalEntry::AccountLoaded { address } => { - state.remove(&address); + state.get_mut(&address).unwrap().mark_cold(); } JournalEntry::AccountTouched { address } => { if is_spurious_dragon_enabled && address == PRECOMPILE3 { @@ -378,7 +378,7 @@ impl JournaledState { if let Some(had_value) = had_value { storage.get_mut(&key).unwrap().present_value = had_value; } else { - storage.remove(&key); + storage.get_mut(&key).unwrap().mark_cold(); } } JournalEntry::TransientStorageChange { @@ -555,8 +555,12 @@ impl JournaledState { address: Address, db: &mut DB, ) -> Result<(&mut Account, bool), EVMError> { - Ok(match self.state.entry(address) { - Entry::Occupied(entry) => (entry.into_mut(), false), + let (value, is_cold) = match self.state.entry(address) { + Entry::Occupied(entry) => { + let account = entry.into_mut(); + let is_cold = account.mark_warm(); + (account, is_cold) + } Entry::Vacant(vac) => { let account = if let Some(account) = db.basic(address).map_err(EVMError::Database)? { @@ -565,18 +569,22 @@ impl JournaledState { Account::new_not_existing() }; - // journal loading of account. AccessList touch. - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::AccountLoaded { address }); - // precompiles are warm loaded so we need to take that into account let is_cold = !self.warm_preloaded_addresses.contains(&address); (vac.insert(account), is_cold) } - }) + }; + + // journal loading of cold account. + if is_cold { + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::AccountLoaded { address }); + } + + Ok((value, is_cold)) } /// Load account from database to JournaledState. @@ -641,8 +649,12 @@ impl JournaledState { let account = self.state.get_mut(&address).unwrap(); // only if account is created in this tx we can assume that storage is empty. let is_newly_created = account.is_created(); - let load = match account.storage.entry(key) { - Entry::Occupied(occ) => (occ.get().present_value, false), + let (value, is_cold) = match account.storage.entry(key) { + Entry::Occupied(occ) => { + let slot = occ.into_mut(); + let is_cold = slot.mark_warm(); + (slot.present_value, is_cold) + } Entry::Vacant(vac) => { // if storage was cleared, we don't need to ping db. let value = if is_newly_created { @@ -650,22 +662,26 @@ impl JournaledState { } else { db.storage(address, key).map_err(EVMError::Database)? }; - // add it to journal as cold loaded. - self.journal - .last_mut() - .unwrap() - .push(JournalEntry::StorageChange { - address, - key, - had_value: None, - }); vac.insert(EvmStorageSlot::new(value)); (value, true) } }; - Ok(load) + + if is_cold { + // add it to journal as cold loaded. + self.journal + .last_mut() + .unwrap() + .push(JournalEntry::StorageChange { + address, + key, + had_value: None, + }); + } + + Ok((value, is_cold)) } /// Stores storage slot. From 8943b3a57aff7509be42a96f573beaf1efa5f13e Mon Sep 17 00:00:00 2001 From: Justin Traglia <95511699+jtraglia@users.noreply.github.com> Date: Sat, 8 Jun 2024 12:07:31 -0500 Subject: [PATCH 52/88] chore(precompiles): Fix some nits in bls12_381 (#1495) * Fix some nits in bls12_381 precompiles * Run cargo fmt --- crates/precompile/src/bls12_381/g1.rs | 6 +++--- crates/precompile/src/bls12_381/g1_msm.rs | 4 ++-- crates/precompile/src/bls12_381/g2.rs | 2 +- crates/precompile/src/bls12_381/g2_msm.rs | 4 ++-- crates/precompile/src/bls12_381/map_fp2_to_g2.rs | 2 +- crates/precompile/src/bls12_381/pairing.rs | 10 +++++----- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/crates/precompile/src/bls12_381/g1.rs b/crates/precompile/src/bls12_381/g1.rs index 6e4b73faab..30374b9688 100644 --- a/crates/precompile/src/bls12_381/g1.rs +++ b/crates/precompile/src/bls12_381/g1.rs @@ -69,7 +69,7 @@ pub(super) fn extract_g1_input( // As endomorphism acceleration requires input on the correct subgroup, implementers MAY // use endomorphism acceleration. if unsafe { !blst_p1_affine_in_g1(&out) } { - return Err(PrecompileError::Other("Element not in G2".to_string())); + return Err(PrecompileError::Other("Element not in G1".to_string())); } } else { // From EIP-2537: @@ -80,13 +80,13 @@ pub(super) fn extract_g1_input( // // NB: There is no subgroup check for the G1 addition precompile. // - // We use blst_p1_affine_on_curve instead of blst_p1_affine_in_g2 because the latter performs + // We use blst_p1_affine_on_curve instead of blst_p1_affine_in_g1 because the latter performs // the subgroup check. // // SAFETY: out is a blst value. if unsafe { !blst_p1_affine_on_curve(&out) } { return Err(PrecompileError::Other( - "Element not on G2 curve".to_string(), + "Element not on G1 curve".to_string(), )); } } diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index f0003a3295..c0e03b3b18 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -45,8 +45,8 @@ pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { let slice = &input[i * g1_mul::INPUT_LENGTH..i * g1_mul::INPUT_LENGTH + G1_INPUT_ITEM_LENGTH]; - // BLST batch API for p1_affines blows up when you pass it a point at infinity and returns - // point at infinity so we just skip the element, and return 128 bytes in the response + // BLST batch API for p1_affines blows up when you pass it a point at infinity, so we must + // filter points at infinity (and their corresponding scalars) from the input. if slice.iter().all(|i| *i == 0) { continue; } diff --git a/crates/precompile/src/bls12_381/g2.rs b/crates/precompile/src/bls12_381/g2.rs index 585368959e..c6520c6464 100644 --- a/crates/precompile/src/bls12_381/g2.rs +++ b/crates/precompile/src/bls12_381/g2.rs @@ -68,7 +68,7 @@ pub(super) fn extract_g2_input( ))); } - let mut input_fps: [&[u8; FP_LENGTH]; 4] = [&[0; FP_LENGTH]; 4]; + let mut input_fps = [&[0; FP_LENGTH]; 4]; for i in 0..4 { input_fps[i] = remove_padding(&input[i * PADDED_FP_LENGTH..(i + 1) * PADDED_FP_LENGTH])?; } diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index cedc73a147..c59a93e220 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -44,8 +44,8 @@ pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { for i in 0..k { let slice = &input[i * g2_mul::INPUT_LENGTH..i * g2_mul::INPUT_LENGTH + G2_INPUT_ITEM_LENGTH]; - // BLST batch API for p2_affines blows up when you pass it a point at infinity and returns - // point at infinity so we just skip the element, and return 256 bytes in the response + // BLST batch API for p2_affines blows up when you pass it a point at infinity, so we must + // filter points at infinity (and their corresponding scalars) from the input. if slice.iter().all(|i| *i == 0) { continue; } 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 30c3ab5b63..c914e844f8 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,7 @@ pub const ADDRESS: u64 = 0x13; /// Base gas fee for BLS12-381 map_fp2_to_g2 operation. const BASE_GAS_FEE: u64 = 75000; -/// Field-to-curve call expects 128 bytes as an input that is interpreted as a +/// 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 /// point. /// See also: diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index 2a699a0859..55767e2e0e 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -16,7 +16,7 @@ pub const ADDRESS: u64 = 0x11; const PAIRING_MULTIPLIER_BASE: u64 = 43000; /// Offset gas fee for BLS12-381 pairing operation. const PAIRING_OFFSET_BASE: u64 = 65000; -/// Input length of paitring operation. +/// Input length of pairing operation. const INPUT_LENGTH: usize = 384; /// Pairing call expects 384*k (k being a positive integer) bytes as an inputs @@ -25,7 +25,7 @@ const INPUT_LENGTH: usize = 384; /// * 128 bytes of G1 point encoding /// * 256 bytes of G2 point encoding /// Each point is expected to be in the subgroup of order q. -/// Output is a 32 bytes where first 31 bytes are equal to 0x00 and the last byte +/// Output is 32 bytes where first 31 bytes are equal to 0x00 and the last byte /// is 0x01 if pairing result is equal to the multiplicative identity in a pairing /// target field and 0x00 otherwise. /// See also: @@ -43,7 +43,7 @@ pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { return Err(PrecompileError::OutOfGas); } - // accumulator for the fp12 multiplications of the miller loops. + // Accumulator for the fp12 multiplications of the miller loops. let mut acc = blst_fp12::default(); for i in 0..k { // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. @@ -64,7 +64,7 @@ pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { )?; if i > 0 { - // after the first slice (i>0) we use cur_ml to store the current + // After the first slice (i>0) we use cur_ml to store the current // miller loop and accumulate with the previous results using a fp12 // multiplication. let mut cur_ml = blst_fp12::default(); @@ -76,7 +76,7 @@ pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { } acc = res; } else { - // on the first slice (i==0) there is no previous results and no need + // On the first slice (i==0) there is no previous results and no need // to accumulate. // SAFETY: acc, p1_aff and p2_aff are blst values. unsafe { From d3a4ef9161749c4790a71394379358c1d8dd234a Mon Sep 17 00:00:00 2001 From: Dan Cline <6798349+Rjected@users.noreply.github.com> Date: Sat, 8 Jun 2024 13:13:36 -0400 Subject: [PATCH 53/88] feat: add ecAdd to precompile bench (#1496) --- crates/precompile/benches/bench.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/crates/precompile/benches/bench.rs b/crates/precompile/benches/bench.rs index 48452b4abb..7fba133b50 100644 --- a/crates/precompile/benches/bench.rs +++ b/crates/precompile/benches/bench.rs @@ -1,8 +1,9 @@ use criterion::{black_box, criterion_group, criterion_main, Criterion}; use revm_precompile::{ bn128::{ + add::ISTANBUL_ADD_GAS_COST, pair::{ISTANBUL_PAIR_BASE, ISTANBUL_PAIR_PER_POINT}, - run_pair, + run_add, run_pair, }, kzg_point_evaluation::run, secp256k1::ec_recover_run, @@ -48,6 +49,20 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { println!("gas used by regular pairing call: {:?}", res); + // === BN128 ADD === + + let ecadd_input = hex::decode( + "\ + 18b18acfb4c2c30276db5411368e7185b311dd124691610c5d3b74034e093dc9\ + 063c909c4720840cb5134cb9f59fa749755796819658d32efc0d288198f37266\ + 07c2b7f58a84bd6145f00c9c2bc0bb1a187f20ff2c92963a88019e7c6a014eed\ + 06614e20c147e940f2d70da3f74c9a17df361706a4485c742bd6788478fa17d7", + ) + .unwrap(); + + let res = run_add(&ecadd_input, ISTANBUL_ADD_GAS_COST, 150).unwrap().0; + println!("gas used by bn128 add precompile: {:?}", res); + // === ECRECOVER === // generate secp256k1 signature @@ -71,7 +86,7 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { message_and_signature[64..128].copy_from_slice(&data); let message_and_signature = Bytes::from(message_and_signature); - let gas = ec_recover_run(&message_and_signature, u64::MAX).unwrap(); + let gas = ec_recover_run(&message_and_signature, u64::MAX).unwrap().0; println!("gas used by ecrecover precompile: {:?}", gas); // === POINT_EVALUATION === @@ -98,6 +113,13 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { }) }); + group.bench_function(group_name("bn128 add precompile"), |b| { + b.iter(|| { + run_add(&ecadd_input, ISTANBUL_ADD_GAS_COST, 150).unwrap(); + black_box(()) + }) + }); + group.bench_function(group_name("ecpairing precompile"), |b| { b.iter(|| { run_pair( From a832a4e9f17ce6876d98d5f53b7efbb18d27fb23 Mon Sep 17 00:00:00 2001 From: clabby Date: Sat, 8 Jun 2024 13:29:20 -0400 Subject: [PATCH 54/88] fix(op): Remove `U256::from()` (#1498) Specifies the type of `1e12` as `u64` in the `l1block.rs` module, removing the need for `UintTryFrom<{float}>`. --- crates/revm/src/optimism/l1block.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/revm/src/optimism/l1block.rs b/crates/revm/src/optimism/l1block.rs index 2dab41a4e4..631b9a5d25 100644 --- a/crates/revm/src/optimism/l1block.rs +++ b/crates/revm/src/optimism/l1block.rs @@ -223,7 +223,7 @@ impl L1BlockInfo { estimated_size .saturating_mul(l1_fee_scaled) - .wrapping_div(U256::from(1e12)) + .wrapping_div(U256::from(1000000000000u64)) } // l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar From 8103cc171f4471393f78559fecc645e0cb00c7b8 Mon Sep 17 00:00:00 2001 From: jpgonzalezra Date: Sat, 8 Jun 2024 16:09:31 -0300 Subject: [PATCH 55/88] feat(EOF): change oob behavior of RETURNDATALOAD and RETURNDATACOPY (#1476) * chore(interpreter): optimisation for BYTE, SHL, SHR and SAR * test: add RETURNDATACOPY test and update RETURNDATALOAD * feat: change oob behavior of returndataload * fix: stack order and name on returndatacopy test * feat: change oob behavior of RETURNDATACOPY * chore: remove unused function make_me_a_table * fix: revert interpreter check * chore: some tests * chore: use as_usize_or_fail! macro instead of as_usize_saturated! * fix: add backwards compatibility * fix: collapsible-else-if * self review * refactor code. use set_data in returndatacopy * remove local as it is used once --------- Co-authored-by: rakita --- crates/interpreter/src/instructions/system.rs | 174 +++++++++++++++--- .../src/interpreter/shared_memory.rs | 2 +- 2 files changed, 150 insertions(+), 26 deletions(-) diff --git a/crates/interpreter/src/instructions/system.rs b/crates/interpreter/src/instructions/system.rs index b00a82f617..513d334e12 100644 --- a/crates/interpreter/src/instructions/system.rs +++ b/crates/interpreter/src/instructions/system.rs @@ -125,22 +125,36 @@ pub fn returndatasize(interpreter: &mut Interprete pub fn returndatacopy(interpreter: &mut Interpreter, _host: &mut H) { check!(interpreter, BYZANTIUM); pop!(interpreter, memory_offset, offset, len); + let len = as_usize_or_fail!(interpreter, len); gas_or_fail!(interpreter, gas::verylowcopy_cost(len as u64)); + let data_offset = as_usize_saturated!(offset); let data_end = data_offset.saturating_add(len); - if data_end > interpreter.return_data_buffer.len() { + + // Old legacy behavior is to panic if data_end is out of scope of return buffer. + // This behavior is changed in EOF. + if data_end > interpreter.return_data_buffer.len() && !interpreter.is_eof { interpreter.instruction_result = InstructionResult::OutOfOffset; return; } - if len != 0 { - let memory_offset = as_usize_or_fail!(interpreter, memory_offset); - resize_memory!(interpreter, memory_offset, len); - interpreter.shared_memory.set( - memory_offset, - &interpreter.return_data_buffer[data_offset..data_end], - ); + + // if len is zero memory is not resized. + if len == 0 { + return; } + + // resize memory + let memory_offset = as_usize_or_fail!(interpreter, memory_offset); + resize_memory!(interpreter, memory_offset, len); + + // Note: this can't panic because we resized memory to fit. + interpreter.shared_memory.set_data( + memory_offset, + data_offset, + len, + &interpreter.return_data_buffer, + ); } /// Part of EOF ``. @@ -149,20 +163,20 @@ pub fn returndataload(interpreter: &mut Interpreter, _host: &m gas!(interpreter, gas::VERYLOW); pop_top!(interpreter, offset); let offset_usize = as_usize_or_fail!(interpreter, offset); - // TODO EOF needs to be padded with zeros, it is not correct to fail. - /* - if offset + 32 > len(returndata buffer) the result is zero-padded - (same behavior as CALLDATALOAD).see matching behavior of RETURNDATACOPY - in Modified Behavior section. - */ - if offset_usize.saturating_add(32) > interpreter.return_data_buffer.len() { - // TODO(EOF) proper error. - interpreter.instruction_result = InstructionResult::OutOfOffset; - return; + + let mut output = [0u8; 32]; + if let Some(available) = interpreter + .return_data_buffer + .len() + .checked_sub(offset_usize) + { + let copy_len = available.min(32); + output[..copy_len].copy_from_slice( + &interpreter.return_data_buffer[offset_usize..offset_usize + copy_len], + ); } - *offset = - B256::from_slice(&interpreter.return_data_buffer[offset_usize..offset_usize + 32]).into(); + *offset = B256::from(output).into(); } pub fn gas(interpreter: &mut Interpreter, _host: &mut H) { @@ -174,9 +188,9 @@ pub fn gas(interpreter: &mut Interpreter, _host: &mut H) { mod test { use super::*; use crate::{ - opcode::{make_instruction_table, RETURNDATALOAD}, + opcode::{make_instruction_table, RETURNDATACOPY, RETURNDATALOAD}, primitives::{bytes, Bytecode, PragueSpec}, - DummyHost, Gas, + DummyHost, Gas, InstructionResult, }; #[test] @@ -185,7 +199,13 @@ mod test { let mut host = DummyHost::default(); let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( - [RETURNDATALOAD, RETURNDATALOAD, RETURNDATALOAD].into(), + [ + RETURNDATALOAD, + RETURNDATALOAD, + RETURNDATALOAD, + RETURNDATALOAD, + ] + .into(), )); interp.is_eof = true; interp.gas = Gas::new(10000); @@ -210,8 +230,112 @@ mod test { ); let _ = interp.stack.pop(); - let _ = interp.stack.push(U256::from(2)); + let _ = interp.stack.push(U256::from(32)); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!( + interp.stack.data(), + &vec![U256::from_limbs([0x00, 0x00, 0x00, 0x00])] + ); + + // Offset right at the boundary of the return data buffer size + let _ = interp.stack.pop(); + let _ = interp + .stack + .push(U256::from(interp.return_data_buffer.len())); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!( + interp.stack.data(), + &vec![U256::from_limbs([0x00, 0x00, 0x00, 0x00])] + ); + } + + #[test] + fn returndatacopy() { + let table = make_instruction_table::<_, PragueSpec>(); + let mut host = DummyHost::default(); + + let mut interp = Interpreter::new_bytecode(Bytecode::LegacyRaw( + [ + RETURNDATACOPY, + RETURNDATACOPY, + RETURNDATACOPY, + RETURNDATACOPY, + RETURNDATACOPY, + RETURNDATACOPY, + ] + .into(), + )); + interp.is_eof = true; + interp.gas = Gas::new(10000); + + interp.return_data_buffer = + bytes!("000000000000000400000000000000030000000000000002000000000000000100"); + interp.shared_memory.resize(256); + + // Copying within bounds + interp.stack.push(U256::from(32)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); interp.step(&table, &mut host); - assert_eq!(interp.instruction_result, InstructionResult::OutOfOffset); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!( + interp.shared_memory.slice(0, 32), + &interp.return_data_buffer[0..32] + ); + + // Copying with partial out-of-bounds (should zero pad) + interp.stack.push(U256::from(64)).unwrap(); + interp.stack.push(U256::from(16)).unwrap(); + interp.stack.push(U256::from(64)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!( + interp.shared_memory.slice(64, 16), + &interp.return_data_buffer[16..32] + ); + assert_eq!(&interp.shared_memory.slice(80, 48), &[0u8; 48]); + + // Completely out-of-bounds (should be all zeros) + interp.stack.push(U256::from(32)).unwrap(); + interp.stack.push(U256::from(96)).unwrap(); + interp.stack.push(U256::from(128)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!(&interp.shared_memory.slice(128, 32), &[0u8; 32]); + + // Large offset + interp.stack.push(U256::from(32)).unwrap(); + interp.stack.push(U256::MAX).unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!(&interp.shared_memory.slice(0, 32), &[0u8; 32]); + + // Offset just before the boundary of the return data buffer size + interp.stack.push(U256::from(32)).unwrap(); + interp + .stack + .push(U256::from(interp.return_data_buffer.len() - 32)) + .unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!( + interp.shared_memory.slice(0, 32), + &interp.return_data_buffer[interp.return_data_buffer.len() - 32..] + ); + + // Offset right at the boundary of the return data buffer size + interp.stack.push(U256::from(32)).unwrap(); + interp + .stack + .push(U256::from(interp.return_data_buffer.len())) + .unwrap(); + interp.stack.push(U256::from(0)).unwrap(); + interp.step(&table, &mut host); + assert_eq!(interp.instruction_result, InstructionResult::Continue); + assert_eq!(&interp.shared_memory.slice(0, 32), &[0u8; 32]); } } diff --git a/crates/interpreter/src/interpreter/shared_memory.rs b/crates/interpreter/src/interpreter/shared_memory.rs index cc63e1bf07..601379b553 100644 --- a/crates/interpreter/src/interpreter/shared_memory.rs +++ b/crates/interpreter/src/interpreter/shared_memory.rs @@ -256,7 +256,7 @@ impl SharedMemory { /// /// # Panics /// - /// Panics on out of bounds. + /// Panics if memory is out of bounds. #[inline] #[cfg_attr(debug_assertions, track_caller)] pub fn set_data(&mut self, memory_offset: usize, data_offset: usize, len: usize, data: &[u8]) { From 95f2436c96aa515f3137d104b077ec7b7017abec Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 8 Jun 2024 21:30:19 +0200 Subject: [PATCH 56/88] chore: cargo update (#1500) --- Cargo.lock | 117 +++++++++++++++++++++++++---------------------------- 1 file changed, 55 insertions(+), 62 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b1717751ba..e199111439 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" dependencies = [ "gimli", ] @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8aa973e647ec336810a9356af8aea787249c9d00b1525359f3db29a68d231b" +checksum = "5277af0cbcc483ee6ad2c1e818090b5928d27f04fd6580680f31c1cf8068bcc2" dependencies = [ "alloy-rlp", "arbitrary", @@ -263,9 +263,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dbd17d67f3e89478c8a634416358e539e577899666c927bc3d2b1328ee9b6ca" +checksum = "30708a79919b082f2692423c8cc72fc250477e4a2ecb0d4a7244cd3cdb299965" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -277,13 +277,13 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c6da95adcf4760bb4b108fefa51d50096c5e5fdd29ee72fed3e86ee414f2e34" +checksum = "1c7a679ac01774ab7e00a567a918d4231ae692c5c8cedaf4e16956c3116d7896" dependencies = [ "alloy-sol-macro-input", "const-hex", - "heck 0.4.1", + "heck 0.5.0", "indexmap", "proc-macro-error", "proc-macro2", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32c8da04c1343871fb6ce5a489218f9c85323c8340a36e9106b5fc98d4dd59d5" +checksum = "356da0c2228aa6675a5faaa08a3e4061b967f924753983d72b9a18d9a3fad44e" dependencies = [ "const-hex", "dunce", @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40a64d2d2395c1ac636b62419a7b17ec39031d6b2367e66e9acbf566e6055e9c" +checksum = "6eb5e6234c0b62514992589fe1578f64d418dbc8ef5cd1ab2d7f2f568f599698" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -604,9 +604,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.71" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" dependencies = [ "addr2line", "cc", @@ -770,9 +770,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "96c51067fd44124faa7f870b4b1c969379ad32b2ba805aa959430ceaa384f695" [[package]] name = "cfg-if" @@ -833,18 +833,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.4" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" +checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.2" +version = "4.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" +checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" dependencies = [ "anstyle", "clap_lex", @@ -852,9 +852,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "console" @@ -871,9 +871,9 @@ dependencies = [ [[package]] name = "const-hex" -version = "1.11.4" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ff96486ccc291d36a958107caf2c0af8c78c0af7d31ae2f35ce055130de1a6" +checksum = "94fb8a24a26d37e1ffd45343323dc9fe6654ceea44c12f2fcb3d7ac29e610bc6" dependencies = [ "cfg-if", "cpufeatures", @@ -928,7 +928,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.4", + "clap 4.5.6", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1263,9 +1263,9 @@ dependencies = [ [[package]] name = "ethereum_ssz" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e61ffea29f26e8249d35128a82ec8d3bd4fbc80179ea5f5e5e3daafef6a80fcb" +checksum = "7d3627f83d8b87b432a5fad9934b4565260722a141a2c40f371f8080adec9425" dependencies = [ "ethereum-types", "itertools 0.10.5", @@ -1577,9 +1577,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" [[package]] name = "glob" @@ -1693,12 +1693,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - [[package]] name = "heck" version = "0.5.0" @@ -1814,9 +1808,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" dependencies = [ "bytes", "futures-channel", @@ -1864,7 +1858,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.28", + "hyper 0.14.29", "rustls", "tokio", "tokio-rustls", @@ -1888,9 +1882,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" dependencies = [ "bytes", "futures-channel", @@ -2181,11 +2175,10 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -2316,9 +2309,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.2" +version = "0.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" dependencies = [ "memchr", ] @@ -2700,9 +2693,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b33eb56c327dec362a9e55b3ad14f9d2f0904fb5a5b03b513ab5465399e9f43" +checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" dependencies = [ "unicode-ident", ] @@ -2876,7 +2869,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.28", + "hyper 0.14.29", "hyper-rustls", "ipnet", "js-sys", @@ -3164,9 +3157,9 @@ dependencies = [ [[package]] name = "ruint" -version = "1.12.1" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f308135fef9fc398342da5472ce7c484529df23743fb7c734e0f3d472971e62" +checksum = "2c3cc4c2511671f327125da14133d0c5c5d137f006a1017a16f557bc85b16286" dependencies = [ "alloy-rlp", "arbitrary", @@ -3189,9 +3182,9 @@ dependencies = [ [[package]] name = "ruint-macro" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" +checksum = "48fd7bd8a6377e15ad9d42a8ec25371b94ddc67abe7c8b9127bec79bebaaae18" [[package]] name = "rustc-demangle" @@ -3665,11 +3658,11 @@ dependencies = [ [[package]] name = "strum_macros" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6cf59daf282c0a494ba14fd21610a0325f9f90ec9d1231dea26bcb1d696c946" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck 0.4.1", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", @@ -3719,9 +3712,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8db114c44cf843a8bacd37a146e37987a0b823a0e8bc4fdc610c9c72ab397a5" +checksum = "e6fe08d08d84f2c0a77f1e7c46518789d745c2e87a2721791ed7c3c9bc78df28" dependencies = [ "paste", "proc-macro2", @@ -4148,9 +4141,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f5e5f3158ecfd4b8ff6fe086db7c8467a2dfdac97fe420f2b7c4aa97af66d6" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unicode-xid" @@ -4576,9 +4569,9 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ "zeroize_derive", ] From 561fbdbb117a5613475a8f099981a36fedd0104b Mon Sep 17 00:00:00 2001 From: rakita Date: Sat, 8 Jun 2024 21:42:55 +0200 Subject: [PATCH 57/88] feat(precompiles): fatal error for precompiles (#1499) --- crates/precompile/benches/bench.rs | 14 ++-- crates/precompile/src/blake2.rs | 10 +-- crates/precompile/src/bls12_381.rs | 15 ++-- crates/precompile/src/bls12_381/g1_add.rs | 9 ++- crates/precompile/src/bls12_381/g1_msm.rs | 11 +-- crates/precompile/src/bls12_381/g1_mul.rs | 9 ++- crates/precompile/src/bls12_381/g2_add.rs | 9 ++- crates/precompile/src/bls12_381/g2_msm.rs | 11 +-- crates/precompile/src/bls12_381/g2_mul.rs | 9 ++- .../precompile/src/bls12_381/map_fp2_to_g2.rs | 9 ++- .../precompile/src/bls12_381/map_fp_to_g1.rs | 11 +-- crates/precompile/src/bls12_381/pairing.rs | 14 +++- crates/precompile/src/bn128.rs | 75 +++++++++++-------- crates/precompile/src/hash.rs | 10 +-- crates/precompile/src/identity.rs | 6 +- crates/precompile/src/kzg_point_evaluation.rs | 18 ++--- crates/precompile/src/lib.rs | 18 +---- crates/precompile/src/modexp.rs | 29 +++---- crates/precompile/src/secp256k1.rs | 8 +- crates/precompile/src/secp256r1.rs | 19 +++-- crates/primitives/src/precompile.rs | 53 ++++++++++++- crates/primitives/src/result.rs | 6 +- crates/revm/src/builder.rs | 3 +- crates/revm/src/context/evm_context.rs | 29 ++++--- .../crates/interpreter/interpreter_action.md | 2 +- 25 files changed, 243 insertions(+), 164 deletions(-) diff --git a/crates/precompile/benches/bench.rs b/crates/precompile/benches/bench.rs index 7fba133b50..faae103a95 100644 --- a/crates/precompile/benches/bench.rs +++ b/crates/precompile/benches/bench.rs @@ -45,7 +45,7 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { u64::MAX, ) .unwrap() - .0; + .gas_used; println!("gas used by regular pairing call: {:?}", res); @@ -60,7 +60,9 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { ) .unwrap(); - let res = run_add(&ecadd_input, ISTANBUL_ADD_GAS_COST, 150).unwrap().0; + let res = run_add(&ecadd_input, ISTANBUL_ADD_GAS_COST, 150) + .unwrap() + .gas_used; println!("gas used by bn128 add precompile: {:?}", res); // === ECRECOVER === @@ -86,7 +88,9 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { message_and_signature[64..128].copy_from_slice(&data); let message_and_signature = Bytes::from(message_and_signature); - let gas = ec_recover_run(&message_and_signature, u64::MAX).unwrap().0; + let gas = ec_recover_run(&message_and_signature, u64::MAX) + .unwrap() + .gas_used; println!("gas used by ecrecover precompile: {:?}", gas); // === POINT_EVALUATION === @@ -103,8 +107,8 @@ pub fn benchmark_crypto_precompiles(c: &mut Criterion) { let gas = 50000; let env = Env::default(); - let (actual_gas, _actual_output) = run(&kzg_input, gas, &env).unwrap(); - println!("gas used by kzg precompile: {:?}", actual_gas); + let output = run(&kzg_input, gas, &env).unwrap(); + println!("gas used by kzg precompile: {:?}", output.gas_used); group.bench_function(group_name("ecrecover precompile"), |b| { b.iter(|| { diff --git a/crates/precompile/src/blake2.rs b/crates/precompile/src/blake2.rs index 057bba74d4..1b4ab9256a 100644 --- a/crates/precompile/src/blake2.rs +++ b/crates/precompile/src/blake2.rs @@ -1,5 +1,5 @@ use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; -use revm_primitives::Bytes; +use revm_primitives::{Bytes, PrecompileOutput}; const F_ROUND: u64 = 1; const INPUT_LENGTH: usize = 213; @@ -14,20 +14,20 @@ pub fn run(input: &Bytes, gas_limit: u64) -> PrecompileResult { let input = &input[..]; if input.len() != INPUT_LENGTH { - return Err(Error::Blake2WrongLength); + return Err(Error::Blake2WrongLength.into()); } let f = match input[212] { 1 => true, 0 => false, - _ => return Err(Error::Blake2WrongFinalIndicatorFlag), + _ => return Err(Error::Blake2WrongFinalIndicatorFlag.into()), }; // rounds 4 bytes let rounds = u32::from_be_bytes(input[..4].try_into().unwrap()) as usize; let gas_used = rounds as u64 * F_ROUND; if gas_used > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } let mut h = [0u64; 8]; @@ -51,7 +51,7 @@ pub fn run(input: &Bytes, gas_limit: u64) -> PrecompileResult { out[i..i + 8].copy_from_slice(&h.to_le_bytes()); } - Ok((gas_used, out.into())) + Ok(PrecompileOutput::new(gas_used, out.into())) } pub mod algo { diff --git a/crates/precompile/src/bls12_381.rs b/crates/precompile/src/bls12_381.rs index a020e8b13a..75e774ded4 100644 --- a/crates/precompile/src/bls12_381.rs +++ b/crates/precompile/src/bls12_381.rs @@ -109,20 +109,23 @@ mod test { let Some(gas) = vector.gas else { panic!("gas is missing in {test_name}"); }; - let (actual_gas, actual_output) = - res.unwrap_or_else(|e| panic!("precompile call failed for {test_name}: {e}")); + let outcome = res.unwrap_or_else(|e: revm_primitives::PrecompileErrors| { + panic!("precompile call failed for {test_name}: {e}") + }); assert_eq!( - gas, actual_gas, + gas, outcome.gas_used, "expected gas: {}, actual gas: {} in {test_name}", - gas, actual_gas + gas, outcome.gas_used ); let Some(expected) = vector.expected else { panic!("expected output is missing in {test_name}"); }; let expected_output = Bytes::from_hex(expected).unwrap(); assert_eq!( - expected_output, actual_output, - "expected output: {expected_output}, actual output: {actual_output} in {test_name}"); + expected_output, outcome.bytes, + "expected output: {expected_output}, actual output: {:?} in {test_name}", + outcome.bytes + ); } } } diff --git a/crates/precompile/src/bls12_381/g1_add.rs b/crates/precompile/src/bls12_381/g1_add.rs index 9fed002dfc..da671aab49 100644 --- a/crates/precompile/src/bls12_381/g1_add.rs +++ b/crates/precompile/src/bls12_381/g1_add.rs @@ -3,7 +3,7 @@ use crate::{u64_to_address, PrecompileWithAddress}; use blst::{ blst_p1, blst_p1_add_or_double_affine, blst_p1_affine, blst_p1_from_affine, blst_p1_to_affine, }; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1ADD precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -23,14 +23,15 @@ const INPUT_LENGTH: usize = 256; /// See also: pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } if input.len() != INPUT_LENGTH { return Err(PrecompileError::Other(format!( "G1ADD input should be {INPUT_LENGTH} bytes, was {}", input.len() - ))); + )) + .into()); } // NB: There is no subgroup check for the G1 addition precompile. @@ -52,5 +53,5 @@ pub(super) fn g1_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p1_to_affine(&mut p_aff, &p) }; let out = encode_g1_point(&p_aff); - Ok((BASE_GAS_FEE, out)) + Ok(PrecompileOutput::new(BASE_GAS_FEE, out)) } diff --git a/crates/precompile/src/bls12_381/g1_msm.rs b/crates/precompile/src/bls12_381/g1_msm.rs index c0e03b3b18..b62077c6c6 100644 --- a/crates/precompile/src/bls12_381/g1_msm.rs +++ b/crates/precompile/src/bls12_381/g1_msm.rs @@ -6,7 +6,7 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_p1, blst_p1_affine, blst_p1_from_affine, blst_p1_to_affine, p1_affines}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1MSM precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -30,13 +30,14 @@ pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { "G1MSM input length should be multiple of {}, was {}", g1_mul::INPUT_LENGTH, input_len - ))); + )) + .into()); } let k = input_len / g1_mul::INPUT_LENGTH; let required_gas = msm_required_gas(k, g1_mul::BASE_GAS_FEE); if required_gas > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } let mut g1_points: Vec = Vec::with_capacity(k); @@ -72,7 +73,7 @@ pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { // return infinity point if all points are infinity if g1_points.is_empty() { - return Ok((required_gas, [0; 128].into())); + return Ok(PrecompileOutput::new(required_gas, [0; 128].into())); } let points = p1_affines::from(&g1_points); @@ -83,5 +84,5 @@ pub(super) fn g1_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p1_to_affine(&mut multiexp_aff, &multiexp) }; let out = encode_g1_point(&multiexp_aff); - Ok((required_gas, out)) + Ok(PrecompileOutput::new(required_gas, out)) } diff --git a/crates/precompile/src/bls12_381/g1_mul.rs b/crates/precompile/src/bls12_381/g1_mul.rs index 2b62a39c1d..aee9524448 100644 --- a/crates/precompile/src/bls12_381/g1_mul.rs +++ b/crates/precompile/src/bls12_381/g1_mul.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_p1, blst_p1_affine, blst_p1_from_affine, blst_p1_mult, blst_p1_to_affine}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G1MUL precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -25,13 +25,14 @@ pub(super) const INPUT_LENGTH: usize = 160; /// See also: pub(super) fn g1_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } if input.len() != INPUT_LENGTH { return Err(PrecompileError::Other(format!( "G1MUL input should be {INPUT_LENGTH} bytes, was {}", input.len() - ))); + )) + .into()); } // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. @@ -55,5 +56,5 @@ pub(super) fn g1_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p1_to_affine(&mut p_aff, &p) }; let out = encode_g1_point(&p_aff); - Ok((BASE_GAS_FEE, out)) + Ok(PrecompileOutput::new(BASE_GAS_FEE, out)) } diff --git a/crates/precompile/src/bls12_381/g2_add.rs b/crates/precompile/src/bls12_381/g2_add.rs index a8f5b85a8e..9b1e26f184 100644 --- a/crates/precompile/src/bls12_381/g2_add.rs +++ b/crates/precompile/src/bls12_381/g2_add.rs @@ -3,7 +3,7 @@ use crate::{u64_to_address, PrecompileWithAddress}; use blst::{ blst_p2, blst_p2_add_or_double_affine, blst_p2_affine, blst_p2_from_affine, blst_p2_to_affine, }; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2ADD precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -24,14 +24,15 @@ const INPUT_LENGTH: usize = 512; /// See also pub(super) fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } if input.len() != INPUT_LENGTH { return Err(PrecompileError::Other(format!( "G2ADD input should be {INPUT_LENGTH} bytes, was {}", input.len() - ))); + )) + .into()); } // NB: There is no subgroup check for the G2 addition precompile. @@ -53,5 +54,5 @@ pub(super) fn g2_add(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p2_to_affine(&mut p_aff, &p) }; let out = encode_g2_point(&p_aff); - Ok((BASE_GAS_FEE, out)) + Ok(PrecompileOutput::new(BASE_GAS_FEE, out)) } diff --git a/crates/precompile/src/bls12_381/g2_msm.rs b/crates/precompile/src/bls12_381/g2_msm.rs index c59a93e220..456a66517b 100644 --- a/crates/precompile/src/bls12_381/g2_msm.rs +++ b/crates/precompile/src/bls12_381/g2_msm.rs @@ -6,7 +6,7 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_p2, blst_p2_affine, blst_p2_from_affine, blst_p2_to_affine, p2_affines}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2MSM precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -30,13 +30,14 @@ pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { "G2MSM input length should be multiple of {}, was {}", g2_mul::INPUT_LENGTH, input_len - ))); + )) + .into()); } let k = input_len / g2_mul::INPUT_LENGTH; let required_gas = msm_required_gas(k, g2_mul::BASE_GAS_FEE); if required_gas > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } let mut g2_points: Vec = Vec::with_capacity(k); @@ -72,7 +73,7 @@ pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { // return infinity point if all points are infinity if g2_points.is_empty() { - return Ok((required_gas, [0; 256].into())); + return Ok(PrecompileOutput::new(required_gas, [0; 256].into())); } let points = p2_affines::from(&g2_points); @@ -83,5 +84,5 @@ pub(super) fn g2_msm(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p2_to_affine(&mut multiexp_aff, &multiexp) }; let out = encode_g2_point(&multiexp_aff); - Ok((required_gas, out)) + Ok(PrecompileOutput::new(required_gas, out)) } diff --git a/crates/precompile/src/bls12_381/g2_mul.rs b/crates/precompile/src/bls12_381/g2_mul.rs index 62cb903e9b..e39edf0751 100644 --- a/crates/precompile/src/bls12_381/g2_mul.rs +++ b/crates/precompile/src/bls12_381/g2_mul.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_p2, blst_p2_affine, blst_p2_from_affine, blst_p2_mult, blst_p2_to_affine}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_G2MUL precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -25,13 +25,14 @@ pub(super) const INPUT_LENGTH: usize = 288; /// See also: pub(super) fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } if input.len() != INPUT_LENGTH { return Err(PrecompileError::Other(format!( "G2MUL input should be {INPUT_LENGTH} bytes, was {}", input.len() - ))); + )) + .into()); } // NB: Scalar multiplications, MSMs and pairings MUST perform a subgroup check. @@ -52,5 +53,5 @@ pub(super) fn g2_mul(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p2_to_affine(&mut p_aff, &p) }; let out = encode_g2_point(&p_aff); - Ok((BASE_GAS_FEE, out)) + Ok(PrecompileOutput::new(BASE_GAS_FEE, out)) } 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 c914e844f8..584008ec62 100644 --- a/crates/precompile/src/bls12_381/map_fp2_to_g2.rs +++ b/crates/precompile/src/bls12_381/map_fp2_to_g2.rs @@ -5,7 +5,7 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_map_to_g2, blst_p2, blst_p2_affine, blst_p2_to_affine}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP2_TO_G2 precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -23,14 +23,15 @@ const BASE_GAS_FEE: u64 = 75000; /// See also: pub(super) fn map_fp2_to_g2(input: &Bytes, gas_limit: u64) -> PrecompileResult { if BASE_GAS_FEE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } if input.len() != PADDED_FP2_LENGTH { return Err(PrecompileError::Other(format!( "MAP_FP2_TO_G2 input should be {PADDED_FP2_LENGTH} bytes, was {}", input.len() - ))); + )) + .into()); } let input_p0_x = remove_padding(&input[..PADDED_FP_LENGTH])?; @@ -47,5 +48,5 @@ pub(super) fn map_fp2_to_g2(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p2_to_affine(&mut p_aff, &p) }; let out = encode_g2_point(&p_aff); - Ok((BASE_GAS_FEE, out)) + Ok(PrecompileOutput::new(BASE_GAS_FEE, out)) } 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 26b5987322..b92df60a18 100644 --- a/crates/precompile/src/bls12_381/map_fp_to_g1.rs +++ b/crates/precompile/src/bls12_381/map_fp_to_g1.rs @@ -4,7 +4,7 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_map_to_g1, blst_p1, blst_p1_affine, blst_p1_to_affine}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult}; +use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_MAP_FP_TO_G1 precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -21,14 +21,15 @@ const MAP_FP_TO_G1_BASE: u64 = 5500; /// See also: pub(super) fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { if MAP_FP_TO_G1_BASE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } if input.len() != PADDED_FP_LENGTH { return Err(PrecompileError::Other(format!( "MAP_FP_TO_G1 input should be {PADDED_FP_LENGTH} bytes, was {}", input.len() - ))); + )) + .into()); } let input_p0 = remove_padding(input)?; @@ -44,7 +45,7 @@ pub(super) fn map_fp_to_g1(input: &Bytes, gas_limit: u64) -> PrecompileResult { unsafe { blst_p1_to_affine(&mut p_aff, &p) }; let out = encode_g1_point(&p_aff); - Ok((MAP_FP_TO_G1_BASE, out)) + Ok(PrecompileOutput::new(MAP_FP_TO_G1_BASE, out)) } #[cfg(test)] @@ -58,7 +59,7 @@ mod test { let fail = map_fp_to_g1(&input, MAP_FP_TO_G1_BASE); assert_eq!( fail, - Err(PrecompileError::Other("non-canonical fp value".to_string())) + Err(PrecompileError::Other("non-canonical fp value".to_string()).into()) ); } } diff --git a/crates/precompile/src/bls12_381/pairing.rs b/crates/precompile/src/bls12_381/pairing.rs index 55767e2e0e..e0c50dd834 100644 --- a/crates/precompile/src/bls12_381/pairing.rs +++ b/crates/precompile/src/bls12_381/pairing.rs @@ -4,7 +4,9 @@ use super::{ }; use crate::{u64_to_address, PrecompileWithAddress}; use blst::{blst_final_exp, blst_fp12, blst_fp12_is_one, blst_fp12_mul, blst_miller_loop}; -use revm_primitives::{Bytes, Precompile, PrecompileError, PrecompileResult, B256}; +use revm_primitives::{ + Bytes, Precompile, PrecompileError, PrecompileOutput, PrecompileResult, B256, +}; /// [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537#specification) BLS12_PAIRING precompile. pub const PRECOMPILE: PrecompileWithAddress = @@ -34,13 +36,14 @@ pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { if input_len == 0 || input_len % INPUT_LENGTH != 0 { return Err(PrecompileError::Other(format!( "Pairing input length should be multiple of {INPUT_LENGTH}, was {input_len}" - ))); + )) + .into()); } let k = input_len / INPUT_LENGTH; let required_gas: u64 = PAIRING_MULTIPLIER_BASE * k as u64 + PAIRING_OFFSET_BASE; if required_gas > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } // Accumulator for the fp12 multiplications of the miller loops. @@ -98,5 +101,8 @@ pub(super) fn pairing(input: &Bytes, gas_limit: u64) -> PrecompileResult { result = 1; } } - Ok((required_gas, B256::with_last_byte(result).into())) + Ok(PrecompileOutput::new( + required_gas, + B256::with_last_byte(result).into(), + )) } diff --git a/crates/precompile/src/bn128.rs b/crates/precompile/src/bn128.rs index ce08da7994..c9ce059d73 100644 --- a/crates/precompile/src/bn128.rs +++ b/crates/precompile/src/bn128.rs @@ -3,6 +3,7 @@ use crate::{ Address, Error, Precompile, PrecompileResult, PrecompileWithAddress, }; use bn::{AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; +use revm_primitives::PrecompileOutput; pub mod add { use super::*; @@ -122,7 +123,7 @@ pub fn new_g1_point(px: Fq, py: Fq) -> Result { pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } let input = right_pad::(input); @@ -135,12 +136,12 @@ pub fn run_add(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult sum.x().to_big_endian(&mut output[..32]).unwrap(); sum.y().to_big_endian(&mut output[32..]).unwrap(); } - Ok((gas_cost, output.into())) + Ok(PrecompileOutput::new(gas_cost, output.into())) } pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult { if gas_cost > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } let input = right_pad::(input); @@ -155,7 +156,7 @@ pub fn run_mul(input: &[u8], gas_cost: u64, gas_limit: u64) -> PrecompileResult mul.x().to_big_endian(&mut output[..32]).unwrap(); mul.y().to_big_endian(&mut output[32..]).unwrap(); } - Ok((gas_cost, output.into())) + Ok(PrecompileOutput::new(gas_cost, output.into())) } pub fn run_pair( @@ -166,11 +167,11 @@ pub fn run_pair( ) -> PrecompileResult { let gas_used = (input.len() / PAIR_ELEMENT_LEN) as u64 * pair_per_point_cost + pair_base_cost; if gas_used > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } if input.len() % PAIR_ELEMENT_LEN != 0 { - return Err(Error::Bn128PairLength); + return Err(Error::Bn128PairLength.into()); } let success = if input.is_empty() { @@ -211,7 +212,7 @@ pub fn run_pair( mul == Gt::one() }; - Ok((gas_used, bool_to_bytes32(success))) + Ok(PrecompileOutput::new(gas_used, bool_to_bytes32(success))) } #[cfg(test)] @@ -219,7 +220,7 @@ mod tests { use crate::bn128::add::BYZANTIUM_ADD_GAS_COST; use crate::bn128::mul::BYZANTIUM_MUL_GAS_COST; use crate::bn128::pair::{BYZANTIUM_PAIR_BASE, BYZANTIUM_PAIR_PER_POINT}; - use revm_primitives::hex; + use revm_primitives::{hex, PrecompileErrors}; use super::*; @@ -240,8 +241,8 @@ mod tests { ) .unwrap(); - let (_, res) = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); - assert_eq!(res, expected); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + assert_eq!(outcome.bytes, expected); // zero sum test let input = hex::decode( @@ -259,8 +260,8 @@ mod tests { ) .unwrap(); - let (_, res) = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); - assert_eq!(res, expected); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + assert_eq!(outcome.bytes, expected); // out of gas test let input = hex::decode( @@ -274,7 +275,7 @@ mod tests { let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 499); println!("{:?}", res); - assert!(matches!(res, Err(Error::OutOfGas))); + assert!(matches!(res, Err(PrecompileErrors::Error(Error::OutOfGas)))); // no input test let input = [0u8; 0]; @@ -285,8 +286,8 @@ mod tests { ) .unwrap(); - let (_, res) = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); - assert_eq!(res, expected); + let outcome = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500).unwrap(); + assert_eq!(outcome.bytes, expected); // point not on curve fail let input = hex::decode( @@ -299,7 +300,10 @@ mod tests { .unwrap(); let res = run_add(&input, BYZANTIUM_ADD_GAS_COST, 500); - assert!(matches!(res, Err(Error::Bn128AffineGFailedToCreate))); + assert!(matches!( + res, + Err(PrecompileErrors::Error(Error::Bn128AffineGFailedToCreate)) + )); } #[test] @@ -318,8 +322,8 @@ mod tests { ) .unwrap(); - let (_, res) = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); - assert_eq!(res, expected); + let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + assert_eq!(outcome.bytes, expected); // out of gas test let input = hex::decode( @@ -331,7 +335,7 @@ mod tests { .unwrap(); let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 39_999); - assert!(matches!(res, Err(Error::OutOfGas))); + assert!(matches!(res, Err(PrecompileErrors::Error(Error::OutOfGas)))); // zero multiplication test let input = hex::decode( @@ -348,8 +352,8 @@ mod tests { ) .unwrap(); - let (_, res) = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); - assert_eq!(res, expected); + let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + assert_eq!(outcome.bytes, expected); // no input test let input = [0u8; 0]; @@ -360,8 +364,8 @@ mod tests { ) .unwrap(); - let (_, res) = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); - assert_eq!(res, expected); + let outcome = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000).unwrap(); + assert_eq!(outcome.bytes, expected); // point not on curve fail let input = hex::decode( @@ -373,7 +377,10 @@ mod tests { .unwrap(); let res = run_mul(&input, BYZANTIUM_MUL_GAS_COST, 40_000); - assert!(matches!(res, Err(Error::Bn128AffineGFailedToCreate))); + assert!(matches!( + res, + Err(PrecompileErrors::Error(Error::Bn128AffineGFailedToCreate)) + )); } #[test] @@ -398,14 +405,14 @@ mod tests { hex::decode("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(); - let (_, res) = run_pair( + let outcome = run_pair( &input, BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, ) .unwrap(); - assert_eq!(res, expected); + assert_eq!(outcome.bytes, expected); // out of gas test let input = hex::decode( @@ -431,7 +438,7 @@ mod tests { BYZANTIUM_PAIR_BASE, 259_999, ); - assert!(matches!(res, Err(Error::OutOfGas))); + assert!(matches!(res, Err(PrecompileErrors::Error(Error::OutOfGas)))); // no input test let input = [0u8; 0]; @@ -439,14 +446,14 @@ mod tests { hex::decode("0000000000000000000000000000000000000000000000000000000000000001") .unwrap(); - let (_, res) = run_pair( + let outcome = run_pair( &input, BYZANTIUM_PAIR_PER_POINT, BYZANTIUM_PAIR_BASE, 260_000, ) .unwrap(); - assert_eq!(res, expected); + assert_eq!(outcome.bytes, expected); // point not on curve fail let input = hex::decode( @@ -466,7 +473,10 @@ mod tests { BYZANTIUM_PAIR_BASE, 260_000, ); - assert!(matches!(res, Err(Error::Bn128AffineGFailedToCreate))); + assert!(matches!( + res, + Err(PrecompileErrors::Error(Error::Bn128AffineGFailedToCreate)) + )); // invalid input length let input = hex::decode( @@ -484,6 +494,9 @@ mod tests { BYZANTIUM_PAIR_BASE, 260_000, ); - assert!(matches!(res, Err(Error::Bn128PairLength))); + assert!(matches!( + res, + Err(PrecompileErrors::Error(Error::Bn128PairLength)) + )); } } diff --git a/crates/precompile/src/hash.rs b/crates/precompile/src/hash.rs index 9fc6a8ae49..9457302b1a 100644 --- a/crates/precompile/src/hash.rs +++ b/crates/precompile/src/hash.rs @@ -1,6 +1,6 @@ use super::calc_linear_cost_u32; use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; -use revm_primitives::Bytes; +use revm_primitives::{Bytes, PrecompileOutput}; use sha2::Digest; pub const SHA256: PrecompileWithAddress = @@ -17,10 +17,10 @@ pub const RIPEMD160: PrecompileWithAddress = PrecompileWithAddress( pub fn sha256_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { let cost = calc_linear_cost_u32(input.len(), 60, 12); if cost > gas_limit { - Err(Error::OutOfGas) + Err(Error::OutOfGas.into()) } else { let output = sha2::Sha256::digest(input); - Ok((cost, output.to_vec().into())) + Ok(PrecompileOutput::new(cost, output.to_vec().into())) } } @@ -30,13 +30,13 @@ pub fn sha256_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { pub fn ripemd160_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { let gas_used = calc_linear_cost_u32(input.len(), 600, 120); if gas_used > gas_limit { - Err(Error::OutOfGas) + Err(Error::OutOfGas.into()) } else { let mut hasher = ripemd::Ripemd160::new(); hasher.update(input); let mut output = [0u8; 32]; hasher.finalize_into((&mut output[12..]).into()); - Ok((gas_used, output.to_vec().into())) + Ok(PrecompileOutput::new(gas_used, output.to_vec().into())) } } diff --git a/crates/precompile/src/identity.rs b/crates/precompile/src/identity.rs index 85722ea810..ab869cd047 100644 --- a/crates/precompile/src/identity.rs +++ b/crates/precompile/src/identity.rs @@ -1,6 +1,6 @@ use super::calc_linear_cost_u32; use crate::{Error, Precompile, PrecompileResult, PrecompileWithAddress}; -use revm_primitives::Bytes; +use revm_primitives::{Bytes, PrecompileOutput}; pub const FUN: PrecompileWithAddress = PrecompileWithAddress(crate::u64_to_address(4), Precompile::Standard(identity_run)); @@ -17,7 +17,7 @@ pub const IDENTITY_PER_WORD: u64 = 3; pub fn identity_run(input: &Bytes, 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(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } - Ok((gas_used, input.clone())) + Ok(PrecompileOutput::new(gas_used, input.clone())) } diff --git a/crates/precompile/src/kzg_point_evaluation.rs b/crates/precompile/src/kzg_point_evaluation.rs index 5790186a99..22192ce56d 100644 --- a/crates/precompile/src/kzg_point_evaluation.rs +++ b/crates/precompile/src/kzg_point_evaluation.rs @@ -1,6 +1,6 @@ use crate::{Address, Error, Precompile, PrecompileResult, PrecompileWithAddress}; use c_kzg::{Bytes32, Bytes48, KzgProof, KzgSettings}; -use revm_primitives::{hex_literal::hex, Bytes, Env}; +use revm_primitives::{hex_literal::hex, Bytes, Env, PrecompileOutput}; use sha2::{Digest, Sha256}; pub const POINT_EVALUATION: PrecompileWithAddress = @@ -26,19 +26,19 @@ pub const RETURN_VALUE: &[u8; 64] = &hex!( /// with z and y being padded 32 byte big endian values pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { if gas_limit < GAS_COST { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } // Verify input length. if input.len() != 192 { - return Err(Error::BlobInvalidInputLength); + return Err(Error::BlobInvalidInputLength.into()); } // Verify commitment matches versioned_hash let versioned_hash = &input[..32]; let commitment = &input[96..144]; if kzg_to_versioned_hash(commitment) != versioned_hash { - return Err(Error::BlobMismatchedVersion); + return Err(Error::BlobMismatchedVersion.into()); } // Verify KZG proof with z and y in big endian format @@ -47,11 +47,11 @@ pub fn run(input: &Bytes, gas_limit: u64, env: &Env) -> PrecompileResult { let y = as_bytes32(&input[64..96]); let proof = as_bytes48(&input[144..192]); if !verify_kzg_proof(commitment, z, y, proof, env.cfg.kzg_settings.get()) { - return Err(Error::BlobVerifyKzgProofFailed); + return Err(Error::BlobVerifyKzgProofFailed.into()); } // Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values - Ok((GAS_COST, RETURN_VALUE.into())) + Ok(PrecompileOutput::new(GAS_COST, RETURN_VALUE.into())) } /// `VERSIONED_HASH_VERSION_KZG ++ sha256(commitment)[1..]` @@ -113,8 +113,8 @@ mod tests { let expected_output = hex!("000000000000000000000000000000000000000000000000000000000000100073eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001"); let gas = 50000; let env = Env::default(); - let (actual_gas, actual_output) = run(&input.into(), gas, &env).unwrap(); - assert_eq!(actual_gas, gas); - assert_eq!(actual_output[..], expected_output); + let output = run(&input.into(), gas, &env).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 a6c57a44a0..6f85a874d0 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -30,28 +30,12 @@ pub use revm_primitives::{ precompile::{PrecompileError as Error, *}, Address, Bytes, HashMap, Log, B256, }; -use std::{boxed::Box, vec::Vec}; +use std::boxed::Box; pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { (len as u64 + 32 - 1) / 32 * word + base } -#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] -pub struct PrecompileOutput { - pub cost: u64, - pub output: Vec, - pub logs: Vec, -} - -impl PrecompileOutput { - pub fn without_logs(cost: u64, output: Vec) -> Self { - Self { - cost, - output, - logs: Vec::new(), - } - } -} #[derive(Clone, Default, Debug)] pub struct Precompiles { /// Precompiles. diff --git a/crates/precompile/src/modexp.rs b/crates/precompile/src/modexp.rs index a55b445912..8d9e5da8c0 100644 --- a/crates/precompile/src/modexp.rs +++ b/crates/precompile/src/modexp.rs @@ -5,7 +5,7 @@ use crate::{ }; use aurora_engine_modexp::modexp; use core::cmp::{max, min}; -use revm_primitives::Bytes; +use revm_primitives::{Bytes, PrecompileOutput}; pub const BYZANTIUM: PrecompileWithAddress = PrecompileWithAddress( crate::u64_to_address(5), @@ -50,7 +50,7 @@ where { // If there is no minimum gas, return error. if min_gas > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } // The format of input is: @@ -66,20 +66,20 @@ where // cast base and modulus to usize, it does not make sense to handle larger values let Ok(base_len) = usize::try_from(base_len) else { - return Err(Error::ModexpBaseOverflow); + return Err(Error::ModexpBaseOverflow.into()); }; let Ok(mod_len) = usize::try_from(mod_len) else { - return Err(Error::ModexpModOverflow); + return Err(Error::ModexpModOverflow.into()); }; // Handle a special case when both the base and mod length are zero. if base_len == 0 && mod_len == 0 { - return Ok((min_gas, Bytes::new())); + return Ok(PrecompileOutput::new(min_gas, Bytes::new())); } // Cast exponent length to usize, since it does not make sense to handle larger values. let Ok(exp_len) = usize::try_from(exp_len) else { - return Err(Error::ModexpModOverflow); + return Err(Error::ModexpModOverflow.into()); }; // Used to extract ADJUSTED_EXPONENT_LENGTH. @@ -99,7 +99,7 @@ where // Check if we have enough gas. let gas_cost = calc_gas(base_len as u64, exp_len as u64, mod_len as u64, &exp_highp); if gas_cost > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } // Padding is needed if the input does not contain all 3 values. @@ -113,7 +113,10 @@ where let output = modexp(base, exponent, modulus); // left pad the result to modulus length. bytes will always by less or equal to modulus length. - Ok((gas_cost, left_pad_vec(&output, mod_len).into_owned().into())) + Ok(PrecompileOutput::new( + gas_cost, + left_pad_vec(&output, mod_len).into_owned().into(), + )) } pub fn byzantium_gas_calc(base_len: u64, exp_len: u64, mod_len: u64, exp_highp: &U256) -> u64 { @@ -350,11 +353,11 @@ mod tests { let res = byzantium_run(&input, 100_000_000).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( - res.0, test_gas, + res.gas_used, test_gas, "used gas not matching for test: {}", test.name ); - assert_eq!(res.1, expected, "test:{}", test.name); + assert_eq!(res.bytes, expected, "test:{}", test.name); } } @@ -365,11 +368,11 @@ mod tests { let res = berlin_run(&input, 100_000_000).unwrap(); let expected = hex::decode(test.expected).unwrap(); assert_eq!( - res.0, test_gas, + res.gas_used, test_gas, "used gas not matching for test: {}", test.name ); - assert_eq!(res.1, expected, "test:{}", test.name); + assert_eq!(res.bytes, expected, "test:{}", test.name); } } @@ -377,6 +380,6 @@ mod tests { fn test_berlin_modexp_empty_input() { let res = berlin_run(&Bytes::new(), 100_000).unwrap(); let expected: Vec = Vec::new(); - assert_eq!(res.1, expected) + assert_eq!(res.bytes, expected) } } diff --git a/crates/precompile/src/secp256k1.rs b/crates/precompile/src/secp256k1.rs index 4ad079e1e7..86794b38db 100644 --- a/crates/precompile/src/secp256k1.rs +++ b/crates/precompile/src/secp256k1.rs @@ -1,5 +1,5 @@ use crate::{utilities::right_pad, Error, Precompile, PrecompileResult, PrecompileWithAddress}; -use revm_primitives::{alloy_primitives::B512, Bytes, B256}; +use revm_primitives::{alloy_primitives::B512, Bytes, PrecompileOutput, B256}; pub const ECRECOVER: PrecompileWithAddress = PrecompileWithAddress( crate::u64_to_address(1), @@ -70,14 +70,14 @@ pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { const ECRECOVER_BASE: u64 = 3_000; if ECRECOVER_BASE > gas_limit { - return Err(Error::OutOfGas); + return Err(Error::OutOfGas.into()); } let input = right_pad::<128>(input); // `v` must be a 32-byte big-endian integer equal to 27 or 28. if !(input[32..63].iter().all(|&b| b == 0) && matches!(input[63], 27 | 28)) { - return Ok((ECRECOVER_BASE, Bytes::new())); + return Ok(PrecompileOutput::new(ECRECOVER_BASE, Bytes::new())); } let msg = <&B256>::try_from(&input[0..32]).unwrap(); @@ -87,5 +87,5 @@ pub fn ec_recover_run(input: &Bytes, gas_limit: u64) -> PrecompileResult { let out = secp256k1::ecrecover(sig, recid, msg) .map(|o| o.to_vec().into()) .unwrap_or_default(); - Ok((ECRECOVER_BASE, out)) + Ok(PrecompileOutput::new(ECRECOVER_BASE, out)) } diff --git a/crates/precompile/src/secp256r1.rs b/crates/precompile/src/secp256r1.rs index e2c9951a21..46f00b7405 100644 --- a/crates/precompile/src/secp256r1.rs +++ b/crates/precompile/src/secp256r1.rs @@ -8,7 +8,7 @@ //! with the address that it is currently deployed at. use crate::{u64_to_address, Precompile, PrecompileWithAddress}; use p256::ecdsa::{signature::hazmat::PrehashVerifier, Signature, VerifyingKey}; -use revm_primitives::{Bytes, PrecompileError, PrecompileResult, B256}; +use revm_primitives::{Bytes, PrecompileError, PrecompileOutput, PrecompileResult, B256}; /// Base gas fee for secp256r1 p256verify operation. const P256VERIFY_BASE: u64 = 3450; @@ -33,14 +33,14 @@ pub const P256VERIFY: PrecompileWithAddress = /// | 32 | 32 | 32 | 32 | 32 | pub fn p256_verify(input: &Bytes, gas_limit: u64) -> PrecompileResult { if P256VERIFY_BASE > gas_limit { - return Err(PrecompileError::OutOfGas); + return Err(PrecompileError::OutOfGas.into()); } let result = if verify_impl(input).is_some() { B256::with_last_byte(1).into() } else { Bytes::new() }; - Ok((P256VERIFY_BASE, result)) + Ok(PrecompileOutput::new(P256VERIFY_BASE, result)) } /// Returns `Some(())` if the signature included in the input byte slice is @@ -73,7 +73,7 @@ pub fn verify_impl(input: &[u8]) -> Option<()> { #[cfg(test)] mod test { use super::*; - use revm_primitives::hex::FromHex; + use crate::primitives::{hex::FromHex, PrecompileErrors}; use rstest::rstest; #[rstest] @@ -96,14 +96,14 @@ 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 (gas_used, res) = p256_verify(&input, target_gas).unwrap(); - assert_eq!(gas_used, 3_450u64); + 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() } else { Bytes::new() }; - assert_eq!(res, expected_result); + assert_eq!(outcome.bytes, expected_result); } #[rstest] @@ -113,7 +113,10 @@ mod test { let result = p256_verify(&input, target_gas); assert!(result.is_err()); - assert_eq!(result.err(), Some(PrecompileError::OutOfGas)); + assert_eq!( + result.err(), + Some(PrecompileErrors::Error(PrecompileError::OutOfGas)) + ); } #[rstest] diff --git a/crates/primitives/src/precompile.rs b/crates/primitives/src/precompile.rs index e585377537..275244f849 100644 --- a/crates/primitives/src/precompile.rs +++ b/crates/primitives/src/precompile.rs @@ -1,12 +1,28 @@ use crate::{Bytes, Env}; -use core::fmt; +use core::fmt::{self}; use dyn_clone::DynClone; use std::{boxed::Box, string::String, sync::Arc}; /// A precompile operation result. /// /// Returns either `Ok((gas_used, return_bytes))` or `Err(error)`. -pub type PrecompileResult = Result<(u64, Bytes), PrecompileError>; +pub type PrecompileResult = Result; + +/// Precompile execution output +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub struct PrecompileOutput { + /// Gas used by the precompile. + pub gas_used: u64, + /// Output bytes. + pub bytes: Bytes, +} + +impl PrecompileOutput { + /// Returns new precompile output with the given gas used and output bytes. + pub fn new(gas_used: u64, bytes: Bytes) -> Self { + Self { gas_used, bytes } + } +} pub type StandardPrecompileFn = fn(&Bytes, u64) -> PrecompileResult; pub type EnvPrecompileFn = fn(&Bytes, u64, env: &Env) -> PrecompileResult; @@ -103,6 +119,25 @@ impl Precompile { } } +/// Precompile errors. +#[derive(Clone, Debug, PartialEq, Eq, Hash)] +pub enum PrecompileErrors { + Error(PrecompileError), + Fatal { msg: String }, +} + +#[cfg(feature = "std")] +impl std::error::Error for PrecompileErrors {} + +impl fmt::Display for PrecompileErrors { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Error(e) => e.fmt(f), + Self::Fatal { msg } => f.write_str(msg), + } + } +} + #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum PrecompileError { /// out of gas is the main error. Others are here just for completeness @@ -130,9 +165,21 @@ pub enum PrecompileError { } impl PrecompileError { + /// Returns an other error with the given message. pub fn other(err: impl Into) -> Self { Self::Other(err.into()) } + + /// Returns true if the error is out of gas. + pub fn is_oog(&self) -> bool { + matches!(self, Self::OutOfGas) + } +} + +impl From for PrecompileErrors { + fn from(err: PrecompileError) -> Self { + PrecompileErrors::Error(err) + } } #[cfg(feature = "std")] @@ -175,7 +222,7 @@ mod test { _gas_price: u64, _env: &Env, ) -> PrecompileResult { - PrecompileResult::Err(PrecompileError::OutOfGas) + Err(PrecompileError::OutOfGas.into()) } } diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 36cd0db90d..28f35ce82c 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -148,6 +148,8 @@ pub enum EVMError { /// /// Useful for handler registers where custom logic would want to return their own custom error. Custom(String), + /// Precompile error. + Precompile(String), } #[cfg(feature = "std")] @@ -157,7 +159,7 @@ impl std::error::Error for EVMError Some(e), Self::Header(e) => Some(e), Self::Database(e) => Some(e), - Self::Custom(_) => None, + Self::Precompile(_) | Self::Custom(_) => None, } } } @@ -168,7 +170,7 @@ impl fmt::Display for EVMError { Self::Transaction(e) => write!(f, "transaction validation error: {e}"), Self::Header(e) => write!(f, "header validation error: {e}"), Self::Database(e) => write!(f, "database error: {e}"), - Self::Custom(e) => f.write_str(e), + Self::Precompile(e) | Self::Custom(e) => f.write_str(e), } } } diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index 4b2a81ec4f..a09f7c0bf5 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -449,6 +449,7 @@ mod test { Context, ContextPrecompile, ContextStatefulPrecompile, Evm, InMemoryDB, InnerEvmContext, }; use revm_interpreter::{gas, Host, Interpreter}; + use revm_precompile::PrecompileOutput; use std::{cell::RefCell, rc::Rc, sync::Arc}; /// Custom evm context @@ -614,7 +615,7 @@ mod test { _gas_price: u64, _context: &mut InnerEvmContext, ) -> PrecompileResult { - Ok((10, Bytes::new())) + Ok(PrecompileOutput::new(10, Bytes::new())) } } diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index b92d711da8..0cb969f6f6 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -1,4 +1,5 @@ use revm_interpreter::CallValue; +use revm_precompile::PrecompileErrors; use super::inner_evm_context::InnerEvmContext; use crate::{ @@ -107,10 +108,13 @@ impl EvmContext { address: Address, input_data: &Bytes, gas: Gas, - ) -> Option { - let out = self - .precompiles - .call(address, input_data, gas.limit(), &mut self.inner)?; + ) -> Result, EVMError> { + let Some(outcome) = + self.precompiles + .call(address, input_data, gas.limit(), &mut self.inner) + else { + return Ok(None); + }; let mut result = InterpreterResult { result: InstructionResult::Return, @@ -118,24 +122,25 @@ impl EvmContext { output: Bytes::new(), }; - match out { - Ok((gas_used, data)) => { - if result.gas.record_cost(gas_used) { + match outcome { + Ok(output) => { + if result.gas.record_cost(output.gas_used) { result.result = InstructionResult::Return; - result.output = data; + result.output = output.bytes; } else { result.result = InstructionResult::PrecompileOOG; } } - Err(e) => { - result.result = if e == crate::precompile::Error::OutOfGas { + Err(PrecompileErrors::Error(e)) => { + result.result = if e.is_oog() { InstructionResult::PrecompileOOG } else { InstructionResult::PrecompileError }; } + Err(PrecompileErrors::Fatal { msg }) => return Err(EVMError::Precompile(msg)), } - Some(result) + Ok(Some(result)) } /// Make call frame @@ -194,7 +199,7 @@ impl EvmContext { _ => {} }; - if let Some(result) = self.call_precompile(inputs.bytecode_address, &inputs.input, gas) { + if let Some(result) = self.call_precompile(inputs.bytecode_address, &inputs.input, gas)? { if matches!(result.result, return_ok!()) { self.journaled_state.checkpoint_commit(); } else { diff --git a/documentation/src/crates/interpreter/interpreter_action.md b/documentation/src/crates/interpreter/interpreter_action.md index 9654b43e16..2cc7599aea 100644 --- a/documentation/src/crates/interpreter/interpreter_action.md +++ b/documentation/src/crates/interpreter/interpreter_action.md @@ -1,6 +1,6 @@ # The `interpreter_action.rs` Module in the Rust Ethereum Virtual Machine (EVM) -The `interpreter_action.rs` module within this Rust EVM implementation encompasses a collection of datastructures used as internal models within the EVM. These models represent various aspects of EVM operations such as call and create inputs, call context, value transfers, and the result of self-destruction operations. +The `interpreter_action.rs` module within this Rust EVM implementation encompasses a collection of data structures used as internal models within the EVM. These models represent various aspects of EVM operations such as call and create inputs, call context, value transfers, and the result of self-destruction operations. ## Data Structures From 733bf5ec64108636eb7678c09bcc9f04c2811416 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 10 Jun 2024 13:27:16 +0200 Subject: [PATCH 58/88] feat: add helpers for working with instruction tables (#1493) --- crates/interpreter/src/opcode.rs | 129 +------- crates/interpreter/src/opcode/tables.rs | 179 +++++++++++ crates/revm/src/inspector.rs | 2 +- crates/revm/src/inspector/handler_register.rs | 287 +++++++----------- crates/revm/src/lib.rs | 4 +- 5 files changed, 306 insertions(+), 295 deletions(-) create mode 100644 crates/interpreter/src/opcode/tables.rs diff --git a/crates/interpreter/src/opcode.rs b/crates/interpreter/src/opcode.rs index b5b6ffd17c..5617a0d73c 100644 --- a/crates/interpreter/src/opcode.rs +++ b/crates/interpreter/src/opcode.rs @@ -2,128 +2,15 @@ pub mod eof_printer; -use crate::{instructions::*, primitives::Spec, Host, Interpreter}; +mod tables; +pub use tables::{ + make_boxed_instruction_table, make_instruction_table, update_boxed_instruction, + BoxedInstruction, BoxedInstructionTable, DynInstruction, Instruction, InstructionTable, + InstructionTables, +}; + +use crate::{instructions::*, primitives::Spec, Host}; use core::{fmt, ptr::NonNull}; -use std::boxed::Box; - -/// EVM opcode function signature. -pub type Instruction = fn(&mut Interpreter, &mut H); - -/// Instruction table is list of instruction function pointers mapped to -/// 256 EVM opcodes. -pub type InstructionTable = [Instruction; 256]; - -/// EVM opcode function signature. -pub type BoxedInstruction<'a, H> = Box; - -/// A table of instructions. -pub type BoxedInstructionTable<'a, H> = [BoxedInstruction<'a, H>; 256]; - -/// Instruction set that contains plain instruction table that contains simple `fn` function pointer. -/// and Boxed `Fn` variant that contains `Box` function pointer that can be used with closured. -/// -/// Note that `Plain` variant gives us 10-20% faster Interpreter execution. -/// -/// Boxed variant can be used to wrap plain function pointer with closure. -pub enum InstructionTables<'a, H> { - Plain(InstructionTable), - Boxed(BoxedInstructionTable<'a, H>), -} - -impl InstructionTables<'_, H> { - /// Creates a plain instruction table for the given spec. - #[inline] - pub const fn new_plain() -> Self { - Self::Plain(make_instruction_table::()) - } -} - -impl<'a, H: Host + 'a> InstructionTables<'a, H> { - /// Inserts a boxed instruction into the table with the specified index. - /// - /// This will convert the table into the [BoxedInstructionTable] variant if it is currently a - /// plain instruction table, before inserting the instruction. - #[inline] - pub fn insert_boxed(&mut self, opcode: u8, instruction: BoxedInstruction<'a, H>) { - // first convert the table to boxed variant - self.convert_boxed(); - - // now we can insert the instruction - match self { - Self::Plain(_) => { - unreachable!("we already converted the table to boxed variant"); - } - Self::Boxed(table) => { - table[opcode as usize] = Box::new(instruction); - } - } - } - - /// Inserts the instruction into the table with the specified index. - #[inline] - pub fn insert(&mut self, opcode: u8, instruction: Instruction) { - match self { - Self::Plain(table) => { - table[opcode as usize] = instruction; - } - Self::Boxed(table) => { - table[opcode as usize] = Box::new(instruction); - } - } - } - - /// Converts the current instruction table to a boxed variant. If the table is already boxed, - /// this is a no-op. - #[inline] - pub fn convert_boxed(&mut self) { - match self { - Self::Plain(table) => { - *self = Self::Boxed(core::array::from_fn(|i| { - let instruction: BoxedInstruction<'a, H> = Box::new(table[i]); - instruction - })); - } - Self::Boxed(_) => {} - }; - } -} - -/// Make instruction table. -#[inline] -pub const fn make_instruction_table() -> InstructionTable { - // Force const-eval of the table creation, making this function trivial. - // TODO: Replace this with a `const {}` block once it is stable. - struct ConstTable { - _host: core::marker::PhantomData, - _spec: core::marker::PhantomData, - } - impl ConstTable { - const NEW: InstructionTable = { - let mut tables: InstructionTable = [control::unknown; 256]; - let mut i = 0; - while i < 256 { - tables[i] = instruction::(i as u8); - i += 1; - } - tables - }; - } - ConstTable::::NEW -} - -/// Make boxed instruction table that calls `outer` closure for every instruction. -#[inline] -pub fn make_boxed_instruction_table<'a, H, SPEC, FN>( - table: InstructionTable, - mut outer: FN, -) -> BoxedInstructionTable<'a, H> -where - H: Host, - SPEC: Spec + 'a, - FN: FnMut(Instruction) -> BoxedInstruction<'a, H>, -{ - core::array::from_fn(|i| outer(table[i])) -} /// An error indicating that an opcode is invalid. #[derive(Debug, PartialEq, Eq)] diff --git a/crates/interpreter/src/opcode/tables.rs b/crates/interpreter/src/opcode/tables.rs new file mode 100644 index 0000000000..48a1b6cca8 --- /dev/null +++ b/crates/interpreter/src/opcode/tables.rs @@ -0,0 +1,179 @@ +#![allow(clippy::wrong_self_convention)] + +use super::instruction; +use crate::{instructions::control, primitives::Spec, Host, Interpreter}; +use std::boxed::Box; + +/// EVM opcode function signature. +pub type Instruction = fn(&mut Interpreter, &mut H); + +/// Instruction table is list of instruction function pointers mapped to 256 EVM opcodes. +pub type InstructionTable = [Instruction; 256]; + +/// EVM dynamic opcode function signature. +pub type DynInstruction<'a, H> = dyn Fn(&mut Interpreter, &mut H) + 'a; + +/// EVM boxed dynamic opcode function signature. +pub type BoxedInstruction<'a, H> = Box>; + +/// A table of boxed instructions. +pub type BoxedInstructionTable<'a, H> = [BoxedInstruction<'a, H>; 256]; + +/// Either a plain, static instruction table, or a boxed, dynamic instruction table. +/// +/// Note that `Plain` variant is about 10-20% faster in Interpreter execution. +pub enum InstructionTables<'a, H: ?Sized> { + Plain(InstructionTable), + Boxed(BoxedInstructionTable<'a, H>), +} + +impl<'a, H: Host + ?Sized> InstructionTables<'a, H> { + /// Creates a plain instruction table for the given spec. See [`make_instruction_table`]. + #[inline] + pub const fn new_plain() -> Self { + Self::Plain(make_instruction_table::()) + } +} + +impl<'a, H: Host + ?Sized + 'a> InstructionTables<'a, H> { + /// Inserts the instruction into the table with the specified index. + #[inline] + pub fn insert(&mut self, opcode: u8, instruction: Instruction) { + match self { + Self::Plain(table) => table[opcode as usize] = instruction, + Self::Boxed(table) => table[opcode as usize] = Box::new(instruction), + } + } + + /// Converts the current instruction table to a boxed variant if it is not already, and returns + /// a mutable reference to the boxed table. + #[inline] + pub fn to_boxed(&mut self) -> &mut BoxedInstructionTable<'a, H> { + self.to_boxed_with(|i| Box::new(i)) + } + + /// Converts the current instruction table to a boxed variant if it is not already with `f`, + /// and returns a mutable reference to the boxed table. + #[inline] + pub fn to_boxed_with(&mut self, f: F) -> &mut BoxedInstructionTable<'a, H> + where + F: FnMut(Instruction) -> BoxedInstruction<'a, H>, + { + match self { + Self::Plain(_) => self.to_boxed_with_slow(f), + Self::Boxed(boxed) => boxed, + } + } + + #[cold] + fn to_boxed_with_slow(&mut self, f: F) -> &mut BoxedInstructionTable<'a, H> + where + F: FnMut(Instruction) -> BoxedInstruction<'a, H>, + { + let Self::Plain(table) = self else { + unreachable!() + }; + *self = Self::Boxed(make_boxed_instruction_table(table, f)); + let Self::Boxed(boxed) = self else { + unreachable!() + }; + boxed + } + + /// Returns a mutable reference to the boxed instruction at the specified index. + #[inline] + pub fn get_boxed(&mut self, opcode: u8) -> &mut BoxedInstruction<'a, H> { + &mut self.to_boxed()[opcode as usize] + } + + /// Inserts a boxed instruction into the table at the specified index. + #[inline] + pub fn insert_boxed(&mut self, opcode: u8, instruction: BoxedInstruction<'a, H>) { + *self.get_boxed(opcode) = instruction; + } + + /// Replaces a boxed instruction into the table at the specified index, returning the previous + /// instruction. + #[inline] + pub fn replace_boxed( + &mut self, + opcode: u8, + instruction: BoxedInstruction<'a, H>, + ) -> BoxedInstruction<'a, H> { + core::mem::replace(self.get_boxed(opcode), instruction) + } + + /// Updates a single instruction in the table at the specified index with `f`. + #[inline] + pub fn update_boxed(&mut self, opcode: u8, f: F) + where + F: Fn(&DynInstruction<'a, H>, &mut Interpreter, &mut H) + 'a, + { + update_boxed_instruction(self.get_boxed(opcode), f) + } + + /// Updates every instruction in the table by calling `f`. + #[inline] + pub fn update_all(&mut self, f: F) + where + F: Fn(&DynInstruction<'a, H>, &mut Interpreter, &mut H) + Copy + 'a, + { + // Don't go through `to_boxed` to avoid allocating the plain table twice. + match self { + Self::Plain(_) => { + self.to_boxed_with(|prev| Box::new(move |i, h| f(&prev, i, h))); + } + Self::Boxed(boxed) => boxed + .iter_mut() + .for_each(|instruction| update_boxed_instruction(instruction, f)), + } + } +} + +/// Make instruction table. +#[inline] +pub const fn make_instruction_table() -> InstructionTable { + // Force const-eval of the table creation, making this function trivial. + // TODO: Replace this with a `const {}` block once it is stable. + struct ConstTable { + _host: core::marker::PhantomData, + _spec: core::marker::PhantomData, + } + impl ConstTable { + const NEW: InstructionTable = { + let mut tables: InstructionTable = [control::unknown; 256]; + let mut i = 0; + while i < 256 { + tables[i] = instruction::(i as u8); + i += 1; + } + tables + }; + } + ConstTable::::NEW +} + +/// Make boxed instruction table that calls `f` closure for every instruction. +#[inline] +pub fn make_boxed_instruction_table<'a, H, FN>( + table: &InstructionTable, + mut f: FN, +) -> BoxedInstructionTable<'a, H> +where + H: Host + ?Sized, + FN: FnMut(Instruction) -> BoxedInstruction<'a, H>, +{ + core::array::from_fn(|i| f(table[i])) +} + +/// Updates a boxed instruction with a new one. +#[inline] +pub fn update_boxed_instruction<'a, H, F>(instruction: &mut BoxedInstruction<'a, H>, f: F) +where + H: Host + ?Sized + 'a, + F: Fn(&DynInstruction<'a, H>, &mut Interpreter, &mut H) + 'a, +{ + // NOTE: This first allocation gets elided by the compiler. + let prev = core::mem::replace(instruction, Box::new(|_, _| {})); + *instruction = Box::new(move |i, h| f(&prev, i, h)); +} diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 6fb8eca427..2754aee822 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -15,7 +15,7 @@ mod noop; // Exports. -pub use handler_register::{inspector_handle_register, inspector_instruction, GetInspector}; +pub use handler_register::{inspector_handle_register, GetInspector}; use revm_interpreter::{CallOutcome, CreateOutcome}; /// [Inspector] implementations. diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index a0ab7befa1..0c50058885 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -1,16 +1,13 @@ use crate::{ db::Database, handler::register::EvmHandler, - interpreter::{ - opcode::{self, BoxedInstruction}, - InstructionResult, Interpreter, - }, + interpreter::{opcode, InstructionResult, Interpreter}, primitives::EVMError, Context, FrameOrResult, FrameResult, Inspector, JournalEntry, }; use core::cell::RefCell; -use revm_interpreter::opcode::InstructionTables; -use std::{boxed::Box, rc::Rc, sync::Arc, vec::Vec}; +use revm_interpreter::opcode::DynInstruction; +use std::{rc::Rc, sync::Arc, vec::Vec}; /// Provides access to an `Inspector` instance. pub trait GetInspector { @@ -40,85 +37,56 @@ impl> GetInspector for INSP { pub fn inspector_handle_register>( handler: &mut EvmHandler<'_, EXT, DB>, ) { - // Every instruction inside flat table that is going to be wrapped by inspector calls. - let table = handler.take_instruction_table(); - let mut table = match table { - InstructionTables::Plain(table) => table - .into_iter() - .map(|i| inspector_instruction(i)) - .collect::>(), - InstructionTables::Boxed(table) => table - .into_iter() - .map(|i| inspector_instruction(i)) - .collect::>(), - }; - - // Register inspector Log instruction. - let mut inspect_log = |index: u8| { - if let Some(i) = table.get_mut(index as usize) { - let old = core::mem::replace(i, Box::new(|_, _| ())); - *i = Box::new( - move |interpreter: &mut Interpreter, host: &mut Context| { - let old_log_len = host.evm.journaled_state.logs.len(); - old(interpreter, host); - // check if log was added. It is possible that revert happened - // cause of gas or stack underflow. - if host.evm.journaled_state.logs.len() == old_log_len + 1 { - // clone log. - // TODO decide if we should remove this and leave the comment - // that log can be found as journaled_state. - let last_log = host.evm.journaled_state.logs.last().unwrap().clone(); - // call Inspector - host.external.get_inspector().log(&mut host.evm, &last_log); - } - }, - ) - } - }; - - inspect_log(opcode::LOG0); - inspect_log(opcode::LOG1); - inspect_log(opcode::LOG2); - inspect_log(opcode::LOG3); - inspect_log(opcode::LOG4); - - // // register selfdestruct function. - if let Some(i) = table.get_mut(opcode::SELFDESTRUCT as usize) { - let old = core::mem::replace(i, Box::new(|_, _| ())); - *i = Box::new( - move |interpreter: &mut Interpreter, host: &mut Context| { - // execute selfdestruct - old(interpreter, host); - // check if selfdestruct was successful and if journal entry is made. - if let Some(JournalEntry::AccountDestroyed { - address, - target, - had_balance, - .. - }) = host.evm.journaled_state.journal.last().unwrap().last() - { - host.external - .get_inspector() - .selfdestruct(*address, *target, *had_balance); - } - }, - ) + let table = &mut handler.instruction_table; + + // Update all instructions to call inspector step and step_end. + table.update_all(inspector_instruction); + + // Register inspector LOG* instructions. + for opcode in opcode::LOG0..=opcode::LOG4 { + table.update_boxed(opcode, move |prev, interpreter, host| { + let prev_log_len = host.evm.journaled_state.logs.len(); + prev(interpreter, host); + // check if log was added. It is possible that revert happened + // cause of gas or stack underflow. + if host.evm.journaled_state.logs.len() == prev_log_len + 1 { + // clone log. + // TODO decide if we should remove this and leave the comment + // that log can be found as journaled_state. + let last_log = host.evm.journaled_state.logs.last().unwrap().clone(); + // call Inspector + host.external.get_inspector().log(&mut host.evm, &last_log); + } + }); } - // cast vector to array. - handler.set_instruction_table(InstructionTables::Boxed( - table.try_into().unwrap_or_else(|_| unreachable!()), - )); + // Register selfdestruct function. + table.update_boxed(opcode::SELFDESTRUCT, |prev, interpreter, host| { + // execute selfdestruct + prev(interpreter, host); + // check if selfdestruct was successful and if journal entry is made. + if let Some(JournalEntry::AccountDestroyed { + address, + target, + had_balance, + .. + }) = host.evm.journaled_state.journal.last().unwrap().last() + { + host.external + .get_inspector() + .selfdestruct(*address, *target, *had_balance); + } + }); // call and create input stack shared between handlers. They are used to share // inputs in *_end Inspector calls. - let call_input_stack = Rc::>>::new(RefCell::new(Vec::new())); - let create_input_stack = Rc::>>::new(RefCell::new(Vec::new())); - let eofcreate_input_stack = Rc::>>::new(RefCell::new(Vec::new())); + let call_input_stack = Rc::>>::default(); + let create_input_stack = Rc::>>::default(); + let eofcreate_input_stack = Rc::>>::default(); // Create handler let create_input_stack_inner = create_input_stack.clone(); - let old_handle = handler.execution.create.clone(); + let prev_handle = handler.execution.create.clone(); handler.execution.create = Arc::new( move |ctx, mut inputs| -> Result> { let inspector = ctx.external.get_inspector(); @@ -129,7 +97,7 @@ pub fn inspector_handle_register>( } create_input_stack_inner.borrow_mut().push(inputs.clone()); - let mut frame_or_result = old_handle(ctx, inputs); + let mut frame_or_result = prev_handle(ctx, inputs); if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { ctx.external .get_inspector() @@ -141,71 +109,67 @@ pub fn inspector_handle_register>( // Call handler let call_input_stack_inner = call_input_stack.clone(); - let old_handle = handler.execution.call.clone(); - handler.execution.call = Arc::new( - move |ctx, mut inputs| -> Result> { - // Call inspector to change input or return outcome. - let outcome = ctx.external.get_inspector().call(&mut ctx.evm, &mut inputs); - call_input_stack_inner.borrow_mut().push(inputs.clone()); - if let Some(outcome) = outcome { - return Ok(FrameOrResult::Result(FrameResult::Call(outcome))); - } + let prev_handle = handler.execution.call.clone(); + handler.execution.call = Arc::new(move |ctx, mut inputs| { + // Call inspector to change input or return outcome. + let outcome = ctx.external.get_inspector().call(&mut ctx.evm, &mut inputs); + call_input_stack_inner.borrow_mut().push(inputs.clone()); + if let Some(outcome) = outcome { + return Ok(FrameOrResult::Result(FrameResult::Call(outcome))); + } - let mut frame_or_result = old_handle(ctx, inputs); - if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { - ctx.external - .get_inspector() - .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) - } - frame_or_result - }, - ); + let mut frame_or_result = prev_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }); // Calls inspector `eofcreate` and `initialize_interp` functions. Queues the inputs for the `eofcreate_end`` function. // Calls the old handler, and in case of inspector returning outcome, // returns the outcome without executing eofcreate. let eofcreate_input_stack_inner = eofcreate_input_stack.clone(); - let old_handle = handler.execution.eofcreate.clone(); - handler.execution.eofcreate = Arc::new( - move |ctx, mut inputs| -> Result> { - // Call inspector to change input or return outcome. - let outcome = ctx - .external - .get_inspector() - .eofcreate(&mut ctx.evm, &mut inputs); - eofcreate_input_stack_inner - .borrow_mut() - .push(inputs.clone()); - if let Some(outcome) = outcome { - return Ok(FrameOrResult::Result(FrameResult::EOFCreate(outcome))); - } + let prev_handle = handler.execution.eofcreate.clone(); + handler.execution.eofcreate = Arc::new(move |ctx, mut inputs| { + // Call inspector to change input or return outcome. + let outcome = ctx + .external + .get_inspector() + .eofcreate(&mut ctx.evm, &mut inputs); + eofcreate_input_stack_inner + .borrow_mut() + .push(inputs.clone()); + if let Some(outcome) = outcome { + return Ok(FrameOrResult::Result(FrameResult::EOFCreate(outcome))); + } - let mut frame_or_result = old_handle(ctx, inputs); - if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { - ctx.external - .get_inspector() - .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) - } - frame_or_result - }, - ); + let mut frame_or_result = prev_handle(ctx, inputs); + if let Ok(FrameOrResult::Frame(frame)) = &mut frame_or_result { + ctx.external + .get_inspector() + .initialize_interp(frame.interpreter_mut(), &mut ctx.evm) + } + frame_or_result + }); // Pops eofcreate input from the stack and calls inspector `eofcreate_end` function. // preserve the old handler and calls it with the outcome. let eofcreate_input_stack_inner = eofcreate_input_stack.clone(); - let old_handle = handler.execution.insert_eofcreate_outcome.clone(); + let prev_handle = handler.execution.insert_eofcreate_outcome.clone(); handler.execution.insert_eofcreate_outcome = Arc::new(move |ctx, frame, mut outcome| { let create_inputs = eofcreate_input_stack_inner.borrow_mut().pop().unwrap(); outcome = ctx .external .get_inspector() .eofcreate_end(&mut ctx.evm, &create_inputs, outcome); - old_handle(ctx, frame, outcome) + prev_handle(ctx, frame, outcome) }); // call outcome let call_input_stack_inner = call_input_stack.clone(); - let old_handle = handler.execution.insert_call_outcome.clone(); + let prev_handle = handler.execution.insert_call_outcome.clone(); handler.execution.insert_call_outcome = Arc::new(move |ctx, frame, shared_memory, mut outcome| { let call_inputs = call_input_stack_inner.borrow_mut().pop().unwrap(); @@ -213,23 +177,23 @@ pub fn inspector_handle_register>( .external .get_inspector() .call_end(&mut ctx.evm, &call_inputs, outcome); - old_handle(ctx, frame, shared_memory, outcome) + prev_handle(ctx, frame, shared_memory, outcome) }); // create outcome let create_input_stack_inner = create_input_stack.clone(); - let old_handle = handler.execution.insert_create_outcome.clone(); + let prev_handle = handler.execution.insert_create_outcome.clone(); handler.execution.insert_create_outcome = Arc::new(move |ctx, frame, mut outcome| { let create_inputs = create_input_stack_inner.borrow_mut().pop().unwrap(); outcome = ctx .external .get_inspector() .create_end(&mut ctx.evm, &create_inputs, outcome); - old_handle(ctx, frame, outcome) + prev_handle(ctx, frame, outcome) }); // last frame outcome - let old_handle = handler.execution.last_frame_return.clone(); + let prev_handle = handler.execution.last_frame_return.clone(); handler.execution.last_frame_return = Arc::new(move |ctx, frame_result| { let inspector = ctx.external.get_inspector(); match frame_result { @@ -247,68 +211,51 @@ pub fn inspector_handle_register>( inspector.eofcreate_end(&mut ctx.evm, &eofcreate_inputs, outcome.clone()); } } - old_handle(ctx, frame_result) + prev_handle(ctx, frame_result) }); } -/// Outer closure that calls Inspector for every instruction. -pub fn inspector_instruction< - 'a, +fn inspector_instruction( + prev: &DynInstruction<'_, Context>, + interpreter: &mut Interpreter, + host: &mut Context, +) where INSP: GetInspector, DB: Database, - Instruction: Fn(&mut Interpreter, &mut Context) + 'a, ->( - instruction: Instruction, -) -> BoxedInstruction<'a, Context> { - Box::new( - move |interpreter: &mut Interpreter, host: &mut Context| { - // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the - // old Inspector behavior. - interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.sub(1) }; - - host.external - .get_inspector() - .step(interpreter, &mut host.evm); - if interpreter.instruction_result != InstructionResult::Continue { - return; - } +{ + // SAFETY: as the PC was already incremented we need to subtract 1 to preserve the + // old Inspector behavior. + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.sub(1) }; + + // Call step. + host.external + .get_inspector() + .step(interpreter, &mut host.evm); + if interpreter.instruction_result != InstructionResult::Continue { + return; + } - // return PC to old value - interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.add(1) }; + // Reset PC to previous value. + interpreter.instruction_pointer = unsafe { interpreter.instruction_pointer.add(1) }; - // execute instruction. - instruction(interpreter, host); + // Execute instruction. + prev(interpreter, host); - host.external - .get_inspector() - .step_end(interpreter, &mut host.evm); - }, - ) + // Call step_end. + host.external + .get_inspector() + .step_end(interpreter, &mut host.evm); } #[cfg(test)] mod tests { use super::*; use crate::{ - db::EmptyDB, inspectors::NoOpInspector, - interpreter::{opcode::*, CallInputs, CallOutcome, CreateInputs, CreateOutcome}, - primitives::BerlinSpec, + interpreter::{CallInputs, CallOutcome, CreateInputs, CreateOutcome}, Evm, EvmContext, }; - // Test that this pattern builds. - #[test] - fn test_make_boxed_instruction_table() { - type MyContext = Context; - let table: InstructionTable = make_instruction_table::(); - let _boxed_table: BoxedInstructionTable<'_, MyContext> = - make_boxed_instruction_table::<'_, MyContext, BerlinSpec, _>( - table, - inspector_instruction, - ); - } - #[derive(Default, Debug)] struct StackInspector { initialize_interp_called: bool, diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index 6b69b5bd2a..5097388526 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -38,9 +38,7 @@ pub use db::{Database, DatabaseCommit, DatabaseRef, InMemoryDB}; pub use evm::{Evm, CALL_STACK_LIMIT}; pub use frame::{CallFrame, CreateFrame, Frame, FrameData, FrameOrResult, FrameResult}; pub use handler::Handler; -pub use inspector::{ - inspector_handle_register, inspector_instruction, inspectors, GetInspector, Inspector, -}; +pub use inspector::{inspector_handle_register, inspectors, GetInspector, Inspector}; pub use journaled_state::{JournalCheckpoint, JournalEntry, JournaledState}; // export Optimism types, helpers, and constants #[cfg(feature = "optimism")] From e734537afc1b88323b5d071c65dd3ac6df25ad0d Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Jun 2024 15:20:16 +0200 Subject: [PATCH 59/88] chore(revme): add new line in revme EOF printer (#1503) * chore(revme): add new line in revme EOF printer * format * clippy --- crates/interpreter/src/interpreter/analysis.rs | 15 +++++++++++++++ crates/interpreter/src/opcode/eof_printer.rs | 12 +++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/crates/interpreter/src/interpreter/analysis.rs b/crates/interpreter/src/interpreter/analysis.rs index 2b2d89f796..73d33d090d 100644 --- a/crates/interpreter/src/interpreter/analysis.rs +++ b/crates/interpreter/src/interpreter/analysis.rs @@ -589,4 +589,19 @@ mod test { )) ); } + + #[test] + fn test4() { + //0xef0001010004020001000e04000000008000045f6000e100025f5f6000e1fffd00 + // result:Result { result: false, exception: Some("EOF_InvalidNumberOfOutputs") } + let err = validate_raw_eof( + hex!("ef0001010004020001000e04000000008000045f6000e100025f5f6000e1fffd00").into(), + ); + assert_eq!( + err, + Err(EofError::Validation( + EofValidationError::BackwardJumpBiggestNumMismatch + )) + ); + } } diff --git a/crates/interpreter/src/opcode/eof_printer.rs b/crates/interpreter/src/opcode/eof_printer.rs index dc22688222..e48f153dae 100644 --- a/crates/interpreter/src/opcode/eof_printer.rs +++ b/crates/interpreter/src/opcode/eof_printer.rs @@ -26,11 +26,13 @@ pub fn print_eof_code(code: &[u8]) { print!("{}", opcode.name()); if opcode.immediate_size() != 0 { - print!( - " : 0x{:}", - hex::encode(&code[i + 1..i + 1 + opcode.immediate_size() as usize]) - ); + let immediate = &code[i + 1..i + 1 + opcode.immediate_size() as usize]; + print!(" : 0x{:}", hex::encode(immediate)); + if opcode.immediate_size() == 2 { + print!(" ({})", i16::from_be_bytes(immediate.try_into().unwrap())); + } } + println!(); let mut rjumpv_additional_immediates = 0; if op == RJUMPV { @@ -47,7 +49,7 @@ pub fn print_eof_code(code: &[u8]) { for vtablei in 0..len { let offset = unsafe { read_i16(code.as_ptr().add(i + 2 + 2 * vtablei)) } as isize; - println!("RJUMPV[{vtablei}]: 0x{offset:04X}({offset})"); + println!("RJUMPV[{vtablei}]: 0x{offset:04X} ({offset})"); } } From e244ac4055308ec5fa6cdb0a95652960c006b025 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 10 Jun 2024 17:01:17 +0200 Subject: [PATCH 60/88] chore(deps): bump regex from 1.10.4 to 1.10.5 (#1502) Bumps [regex](https://github.com/rust-lang/regex) from 1.10.4 to 1.10.5. - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.10.4...1.10.5) --- updated-dependencies: - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- bins/revm-test/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e199111439..ce648c9552 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2822,9 +2822,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.4" +version = "1.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" +checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", diff --git a/bins/revm-test/Cargo.toml b/bins/revm-test/Cargo.toml index ef50c94059..01a5ab9ab8 100644 --- a/bins/revm-test/Cargo.toml +++ b/bins/revm-test/Cargo.toml @@ -11,7 +11,7 @@ revm = { path = "../../crates/revm", version = "9.0.0", default-features=false } microbench = "0.5" alloy-sol-macro = "0.7.0" alloy-sol-types = "0.7.0" -regex = "1.10.4" +regex = "1.10.5" eyre = "0.6.12" From 649b7c59a57d53d85140ca504e1916e21554ee49 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 10 Jun 2024 17:06:37 +0200 Subject: [PATCH 61/88] feat(EOF): EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support (#1504) * feat(EOF): EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support * eof magic bytes from array * clippy --- crates/interpreter/src/host.rs | 4 ++-- crates/interpreter/src/host/dummy.rs | 7 +++--- crates/interpreter/src/instructions/host.rs | 2 +- crates/primitives/src/bytecode.rs | 2 +- crates/primitives/src/bytecode/eof.rs | 12 +++++++++- crates/revm/src/context.rs | 4 ++-- crates/revm/src/context/inner_evm_context.rs | 24 ++++++++++++++++---- 7 files changed, 40 insertions(+), 15 deletions(-) diff --git a/crates/interpreter/src/host.rs b/crates/interpreter/src/host.rs index 49ffbd02a6..b432209bde 100644 --- a/crates/interpreter/src/host.rs +++ b/crates/interpreter/src/host.rs @@ -1,4 +1,4 @@ -use crate::primitives::{Address, Bytecode, Env, Log, B256, U256}; +use crate::primitives::{Address, Bytes, Env, Log, B256, U256}; mod dummy; pub use dummy::DummyHost; @@ -23,7 +23,7 @@ pub trait Host { fn balance(&mut self, address: Address) -> Option<(U256, bool)>; /// Get code of `address` and if the account is cold. - fn code(&mut self, address: Address) -> Option<(Bytecode, bool)>; + fn code(&mut self, address: Address) -> Option<(Bytes, bool)>; /// Get code hash of `address` and if the account is cold. fn code_hash(&mut self, address: Address) -> Option<(B256, bool)>; diff --git a/crates/interpreter/src/host/dummy.rs b/crates/interpreter/src/host/dummy.rs index 4a069bfa63..47320b0863 100644 --- a/crates/interpreter/src/host/dummy.rs +++ b/crates/interpreter/src/host/dummy.rs @@ -1,6 +1,5 @@ -use crate::primitives::{hash_map::Entry, Bytecode, HashMap, U256}; use crate::{ - primitives::{Address, Env, Log, B256, KECCAK_EMPTY}, + primitives::{hash_map::Entry, Address, Bytes, Env, HashMap, Log, B256, KECCAK_EMPTY, U256}, Host, SStoreResult, SelfDestructResult, }; use std::vec::Vec; @@ -61,8 +60,8 @@ impl Host for DummyHost { } #[inline] - fn code(&mut self, _address: Address) -> Option<(Bytecode, bool)> { - Some((Bytecode::default(), false)) + fn code(&mut self, _address: Address) -> Option<(Bytes, bool)> { + Some((Bytes::default(), false)) } #[inline] diff --git a/crates/interpreter/src/instructions/host.rs b/crates/interpreter/src/instructions/host.rs index 0bc777c341..a25f514842 100644 --- a/crates/interpreter/src/instructions/host.rs +++ b/crates/interpreter/src/instructions/host.rs @@ -99,7 +99,7 @@ pub fn extcodecopy(interpreter: &mut Interpreter, // Note: this can't panic because we resized memory to fit. interpreter .shared_memory - .set_data(memory_offset, code_offset, len, &code.original_bytes()); + .set_data(memory_offset, code_offset, len, &code); } pub fn blockhash(interpreter: &mut Interpreter, host: &mut H) { diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index 232d61f66d..c5587ea651 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -1,7 +1,7 @@ pub mod eof; pub mod legacy; -pub use eof::Eof; +pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; pub use legacy::{JumpTable, LegacyAnalyzedBytecode}; use crate::{keccak256, Bytes, B256, KECCAK_EMPTY}; diff --git a/crates/primitives/src/bytecode/eof.rs b/crates/primitives/src/bytecode/eof.rs index 3f78bc26da..db6814b793 100644 --- a/crates/primitives/src/bytecode/eof.rs +++ b/crates/primitives/src/bytecode/eof.rs @@ -7,10 +7,20 @@ pub use body::EofBody; pub use header::EofHeader; pub use types_section::TypesSection; -use crate::Bytes; +use crate::{b256, bytes, Bytes, B256}; use core::cmp::min; use std::{vec, vec::Vec}; +/// Hash of EF00 bytes that is used for EXTCODEHASH when called from legacy bytecode. +pub const EOF_MAGIC_HASH: B256 = + b256!("9dbf3648db8210552e9c4f75c6a1c3057c0ca432043bd648be15fe7be05646f5"); + +/// EOF Magic in u16 form. +pub const EOF_MAGIC: u16 = 0xEF00; + +/// EOF magic number in array form. +pub static EOF_MAGIC_BYTES: Bytes = bytes!("ef00"); + /// EOF - Ethereum Object Format. /// /// It consist of a header, body and raw original bytes Specified in EIP. diff --git a/crates/revm/src/context.rs b/crates/revm/src/context.rs index 40107651cb..cc1fd20df9 100644 --- a/crates/revm/src/context.rs +++ b/crates/revm/src/context.rs @@ -13,7 +13,7 @@ use revm_interpreter::as_usize_saturated; use crate::{ db::{Database, EmptyDB}, interpreter::{Host, LoadAccountResult, SStoreResult, SelfDestructResult}, - primitives::{Address, Bytecode, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256}, + primitives::{Address, Bytes, Env, HandlerCfg, Log, B256, BLOCK_HASH_HISTORY, U256}, }; use std::boxed::Box; @@ -146,7 +146,7 @@ impl Host for Context { .ok() } - fn code(&mut self, address: Address) -> Option<(Bytecode, bool)> { + fn code(&mut self, address: Address) -> Option<(Bytes, bool)> { self.evm .code(address) .map_err(|e| self.evm.error = Err(e)) diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index d12e90c148..3272b0e82e 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -10,7 +10,7 @@ use crate::{ keccak256, Account, Address, AnalysisKind, Bytecode, Bytes, CreateScheme, EVMError, Env, Eof, HashSet, Spec, SpecId::{self, *}, - B256, U256, + B256, EOF_MAGIC_BYTES, EOF_MAGIC_HASH, U256, }, FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT, }; @@ -160,21 +160,37 @@ impl InnerEvmContext { .map(|(acc, is_cold)| (acc.info.balance, is_cold)) } - /// Return account code and if address is cold loaded. + /// Return account code bytes and if address is cold loaded. + /// + /// In case of EOF account it will return `EOF_MAGIC` (0xEF00) as code. #[inline] - pub fn code(&mut self, address: Address) -> Result<(Bytecode, bool), EVMError> { + pub fn code(&mut self, address: Address) -> Result<(Bytes, bool), EVMError> { self.journaled_state .load_code(address, &mut self.db) - .map(|(a, is_cold)| (a.info.code.clone().unwrap(), is_cold)) + .map(|(a, is_cold)| { + // SAFETY: safe to unwrap as load_code will insert code if it is empty. + let code = a.info.code.as_ref().unwrap(); + if code.is_eof() { + (EOF_MAGIC_BYTES.clone(), is_cold) + } else { + (code.original_bytes().clone(), is_cold) + } + }) } /// Get code hash of address. + /// + /// In case of EOF account it will return `EOF_MAGIC_HASH` + /// (the hash of `0xEF00`). #[inline] pub fn code_hash(&mut self, address: Address) -> Result<(B256, bool), EVMError> { let (acc, is_cold) = self.journaled_state.load_code(address, &mut self.db)?; if acc.is_empty() { return Ok((B256::ZERO, is_cold)); } + if let Some(true) = acc.info.code.as_ref().map(|code| code.is_eof()) { + return Ok((EOF_MAGIC_HASH, is_cold)); + } Ok((acc.info.code_hash, is_cold)) } From d7538fc711fae1c1c5a188299f386c0de5c1fe7d Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 11 Jun 2024 18:28:11 +0200 Subject: [PATCH 62/88] feat(revme): add prague spec (#1506) --- bins/revme/src/cmd/statetest/models/spec.rs | 2 ++ bins/revme/src/cmd/statetest/runner.rs | 15 +++++++++++---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/bins/revme/src/cmd/statetest/models/spec.rs b/bins/revme/src/cmd/statetest/models/spec.rs index 53c134e479..dac05f04a9 100644 --- a/bins/revme/src/cmd/statetest/models/spec.rs +++ b/bins/revme/src/cmd/statetest/models/spec.rs @@ -23,6 +23,7 @@ pub enum SpecName { Merge, Shanghai, Cancun, + Prague, #[serde(other)] Unknown, } @@ -44,6 +45,7 @@ impl SpecName { Self::Merge => SpecId::MERGE, Self::Shanghai => SpecId::SHANGHAI, Self::Cancun => SpecId::CANCUN, + Self::Prague => SpecId::PRAGUE, Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => { panic!("Overridden with PETERSBURG") } diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index 85764f6aef..b8892096e2 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -9,8 +9,8 @@ use revm::{ inspector_handle_register, inspectors::TracerEip3155, primitives::{ - calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, Env, ExecutionResult, - SpecId, TransactTo, B256, U256, + calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, Env, Eof, + ExecutionResult, SpecId, TransactTo, B256, EOF_MAGIC_BYTES, U256, }, Evm, State, }; @@ -257,10 +257,17 @@ pub fn execute_test_suite( // Create database and insert cache let mut cache_state = revm::CacheState::new(false); for (address, info) in unit.pre { + let code_hash = keccak256(&info.code); + let bytecode = match info.code.get(..2) { + Some(magic) if magic == &EOF_MAGIC_BYTES => { + Bytecode::Eof(Eof::decode(info.code.clone()).unwrap()) + } + _ => Bytecode::new_raw(info.code), + }; let acc_info = revm::primitives::AccountInfo { balance: info.balance, - code_hash: keccak256(&info.code), - code: Some(Bytecode::new_raw(info.code)), + code_hash, + code: Some(bytecode), nonce: info.nonce, }; cache_state.insert_account_with_storage(address, acc_info, info.storage); From 8d9188609e509ba63165201ecb91c379abcc5a5e Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 11 Jun 2024 18:31:26 +0200 Subject: [PATCH 63/88] fix(EOF): jumpf gas was changes (#1507) --- crates/interpreter/src/gas/constants.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/gas/constants.rs b/crates/interpreter/src/gas/constants.rs index 9475e3b33a..7d7956a4e5 100644 --- a/crates/interpreter/src/gas/constants.rs +++ b/crates/interpreter/src/gas/constants.rs @@ -5,7 +5,7 @@ pub const VERYLOW: u64 = 3; pub const DATA_LOADN_GAS: u64 = 3; pub const CONDITION_JUMP_GAS: u64 = 4; -pub const RETF_GAS: u64 = 4; +pub const RETF_GAS: u64 = 3; pub const DATA_LOAD_GAS: u64 = 4; pub const LOW: u64 = 5; From 4902ffa95df222e2a253b48391e59479e0190f78 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 11 Jun 2024 18:34:07 +0200 Subject: [PATCH 64/88] fix(EOF): extstaticcall make static (#1508) --- crates/interpreter/src/instructions/contract.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 4c0b13ed1a..e0df6c99ac 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -197,6 +197,8 @@ pub fn extcall(interpreter: &mut Interpreter, host require_eof!(interpreter); pop_address!(interpreter, target_address); + // TODO check if target is left paddded with zeroes. + // input call let Some(input) = extcall_input(interpreter) else { return; @@ -232,6 +234,8 @@ pub fn extdelegatecall(interpreter: &mut Interpret require_eof!(interpreter); pop_address!(interpreter, target_address); + // TODO check if target is left paddded with zeroes. + // input call let Some(input) = extcall_input(interpreter) else { return; @@ -265,6 +269,8 @@ pub fn extstaticcall(interpreter: &mut Interpreter, host: &mut require_eof!(interpreter); pop_address!(interpreter, target_address); + // TODO check if target is left paddded with zeroes. + // input call let Some(input) = extcall_input(interpreter) else { return; @@ -284,7 +290,7 @@ pub fn extstaticcall(interpreter: &mut Interpreter, host: &mut bytecode_address: target_address, value: CallValue::Transfer(U256::ZERO), scheme: CallScheme::Call, - is_static: interpreter.is_static, + is_static: true, is_eof: true, return_memory_offset: 0..0, }), From d008720c698d6af90c8ab3c21e3b3a70308dce56 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 11 Jun 2024 19:09:11 +0200 Subject: [PATCH 65/88] fix(EOF): add DATACOPY copy gas (#1510) --- crates/interpreter/src/instructions/data.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index 5d18a89899..65df8a702e 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -1,5 +1,5 @@ use crate::{ - gas::{BASE, DATA_LOAD_GAS, VERYLOW}, + gas::{cost_per_word, BASE, DATA_LOAD_GAS, VERYLOW}, instructions::utility::read_u16, interpreter::Interpreter, primitives::U256, @@ -70,6 +70,8 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) let mem_offset = as_usize_or_fail!(interpreter, mem_offset); resize_memory!(interpreter, mem_offset, size); + gas_or_fail!(interpreter, cost_per_word(size as u64, VERYLOW)); + let offset = as_usize_saturated!(offset); let data = interpreter.contract.bytecode.eof().expect("EOF").data(); From 0768ec68f2462e725ab2ee9e519199086382dd72 Mon Sep 17 00:00:00 2001 From: impactdni2 <53975240+impactdni2@users.noreply.github.com> Date: Tue, 11 Jun 2024 15:03:51 -0400 Subject: [PATCH 66/88] Removed .clone() in ExecutionHandler::call, and reusing output buffer in Interpreter (#1512) --- crates/interpreter/src/interpreter.rs | 14 +++++++------- crates/revm/src/handler/handle_types/execution.rs | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index ef000be132..9c7872c2ba 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -250,24 +250,24 @@ impl Interpreter { call_outcome: CallOutcome, ) { self.instruction_result = InstructionResult::Continue; - self.return_data_buffer.clone_from(call_outcome.output()); let out_offset = call_outcome.memory_start(); let out_len = call_outcome.memory_length(); + let out_ins_result = *call_outcome.instruction_result(); + let out_gas = call_outcome.gas(); + self.return_data_buffer = call_outcome.result.output; let target_len = min(out_len, self.return_data_buffer.len()); - match call_outcome.instruction_result() { + match out_ins_result { return_ok!() => { // return unspend gas. - let remaining = call_outcome.gas().remaining(); - let refunded = call_outcome.gas().refunded(); - self.gas.erase_cost(remaining); - self.gas.record_refund(refunded); + self.gas.erase_cost(out_gas.remaining()); + self.gas.record_refund(out_gas.refunded()); shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); push!(self, U256::from(1)); } return_revert!() => { - self.gas.erase_cost(call_outcome.gas().remaining()); + self.gas.erase_cost(out_gas.remaining()); shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); push!(self, U256::ZERO); } diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index b69354a591..b671631732 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -192,7 +192,7 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { context: &mut Context, inputs: Box, ) -> Result> { - (self.call)(context, inputs.clone()) + (self.call)(context, inputs) } /// Call registered handler for call return. From 8742fc7e779e70214a66a262b37a2b90025b3429 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 11 Jun 2024 21:30:59 +0200 Subject: [PATCH 67/88] fix(EOF): Remove redundunt ext call gas cost (#1513) * feat(revme): add prague spec * fix(EOF): jumpf gas was changes * fix(EOF): extstaticcall make static * fix(EOF): add DATACOPY copy gas * fix(EOF): Remove redundunt ext call gas cost --- crates/interpreter/src/instructions/contract.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index e0df6c99ac..f41d1b7f14 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -162,10 +162,6 @@ pub fn extcall_gas_calc( return None; }; - if load_result.is_cold { - gas!(interpreter, gas::COLD_ACCOUNT_ACCESS_COST, None); - } - // TODO(EOF) is_empty should only be checked on delegatecall let call_cost = gas::call_cost( BerlinSpec::SPEC_ID, @@ -187,8 +183,6 @@ pub fn extcall_gas_calc( return None; } - // TODO check remaining gas more then N - gas!(interpreter, gas_limit, None); Some(gas_limit) } From 75c3d0837f4beb607ddbe8251fad6386aa891c44 Mon Sep 17 00:00:00 2001 From: rakita Date: Wed, 12 Jun 2024 10:15:21 +0200 Subject: [PATCH 68/88] fix(EOF): ext*call return values (#1515) --- crates/interpreter/src/interpreter.rs | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 9c7872c2ba..4c3f6b841f 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -264,18 +264,39 @@ impl Interpreter { self.gas.erase_cost(out_gas.remaining()); self.gas.record_refund(out_gas.refunded()); shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); - push!(self, U256::from(1)); + push!( + self, + if self.is_eof { + U256::ZERO + } else { + U256::from(1) + } + ); } return_revert!() => { self.gas.erase_cost(out_gas.remaining()); shared_memory.set(out_offset, &self.return_data_buffer[..target_len]); - push!(self, U256::ZERO); + push!( + self, + if self.is_eof { + U256::from(1) + } else { + U256::ZERO + } + ); } InstructionResult::FatalExternalError => { panic!("Fatal external error in insert_call_outcome"); } _ => { - push!(self, U256::ZERO); + push!( + self, + if self.is_eof { + U256::from(2) + } else { + U256::ZERO + } + ); } } } From 5a4ef14e22030f260642df5dec1acbd40adc1f88 Mon Sep 17 00:00:00 2001 From: Dave Bryson Date: Thu, 13 Jun 2024 18:02:56 -0500 Subject: [PATCH 69/88] docs: added simular to used-by (#1521) --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 0d748be079..254952bbad 100644 --- a/README.md +++ b/README.md @@ -115,6 +115,7 @@ cargo run -p revm --features std,serde-json,ethersdb --example generate_block_tr * [VERBS](https://github.com/simtopia/verbs) an open-source Ethereum agent-based modelling and simulation library with a Python API. * [Hardhat](https://github.com/NomicFoundation/hardhat) is a development environment to compile, deploy, test, and debug your Ethereum software. * [Trin](https://github.com/ethereum/trin) is Portal Network client. An execution and consensus layer Ethereum light client written in Rust. Portal Network client's provide complete, provable, and distributed execution archival access. +* [Simular](https://github.com/simular-fi/simular/) is a Python smart-contract API with a fast, embedded, Ethereum Virtual Machine. * ... (If you want to add project to the list, ping me or open the PR) From 8f99f72ec44b285fb87d45ae6a9557024fc28407 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 14 Jun 2024 01:09:37 +0200 Subject: [PATCH 70/88] fix(revm): remove storage reset that clears is_cold flag (#1518) * fix(revm): remove storage reset that clears is_cold flag * docs --- crates/revm/src/context/evm_context.rs | 2 +- crates/revm/src/journaled_state.rs | 68 ++++++++++++++------------ 2 files changed, 37 insertions(+), 33 deletions(-) diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 0cb969f6f6..580759c2d3 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -358,7 +358,7 @@ mod tests { result.interpreter_result().result, InstructionResult::OutOfFunds ); - let checkpointed = vec![vec![JournalEntry::AccountLoaded { address: contract }]]; + let checkpointed = vec![vec![JournalEntry::AccountWarmed { address: contract }]]; assert_eq!(evm_context.journaled_state.journal, checkpointed); assert_eq!(evm_context.journaled_state.depth, 0); } diff --git a/crates/revm/src/journaled_state.rs b/crates/revm/src/journaled_state.rs index 44ad44b958..6ed29e8ba6 100644 --- a/crates/revm/src/journaled_state.rs +++ b/crates/revm/src/journaled_state.rs @@ -270,15 +270,6 @@ impl JournaledState { last_journal.push(JournalEntry::AccountCreated { address }); account.info.code = None; - // Set all storages to default value. They need to be present to act as accessed slots in access list. - // it shouldn't be possible for them to have different values then zero as code is not existing for this account, - // but because tests can change that assumption we are doing it. - let empty = EvmStorageSlot::default(); - account - .storage - .iter_mut() - .for_each(|(_, slot)| *slot = empty.clone()); - // touch account. This is important as for pre SpuriousDragon account could be // saved even empty. Self::touch_account(last_journal, &address, account); @@ -321,7 +312,7 @@ impl JournaledState { ) { for entry in journal_entries.into_iter().rev() { match entry { - JournalEntry::AccountLoaded { address } => { + JournalEntry::AccountWarmed { address } => { state.get_mut(&address).unwrap().mark_cold(); } JournalEntry::AccountTouched { address } => { @@ -367,19 +358,33 @@ impl JournaledState { JournalEntry::AccountCreated { address } => { let account = &mut state.get_mut(&address).unwrap(); account.unmark_created(); + account + .storage + .values_mut() + .for_each(|slot| slot.mark_cold()); account.info.nonce = 0; } - JournalEntry::StorageChange { + JournalEntry::StorageWarmed { address, key } => { + state + .get_mut(&address) + .unwrap() + .storage + .get_mut(&key) + .unwrap() + .mark_cold(); + } + JournalEntry::StorageChanged { address, key, had_value, } => { - let storage = &mut state.get_mut(&address).unwrap().storage; - if let Some(had_value) = had_value { - storage.get_mut(&key).unwrap().present_value = had_value; - } else { - storage.get_mut(&key).unwrap().mark_cold(); - } + state + .get_mut(&address) + .unwrap() + .storage + .get_mut(&key) + .unwrap() + .present_value = had_value; } JournalEntry::TransientStorageChange { address, @@ -581,7 +586,7 @@ impl JournaledState { self.journal .last_mut() .unwrap() - .push(JournalEntry::AccountLoaded { address }); + .push(JournalEntry::AccountWarmed { address }); } Ok((value, is_cold)) @@ -674,11 +679,7 @@ impl JournaledState { self.journal .last_mut() .unwrap() - .push(JournalEntry::StorageChange { - address, - key, - had_value: None, - }); + .push(JournalEntry::StorageWarmed { address, key }); } Ok((value, is_cold)) @@ -718,10 +719,10 @@ impl JournaledState { self.journal .last_mut() .unwrap() - .push(JournalEntry::StorageChange { + .push(JournalEntry::StorageChanged { address, key, - had_value: Some(present), + had_value: present, }); // insert value into present state. slot.present_value = new; @@ -800,7 +801,7 @@ pub enum JournalEntry { /// Used to mark account that is warm inside EVM in regards to EIP-2929 AccessList. /// Action: We will add Account to state. /// Revert: we will remove account from state. - AccountLoaded { address: Address }, + AccountWarmed { address: Address }, /// Mark account to be destroyed and journal balance to be reverted /// Action: Mark account and transfer the balance /// Revert: Unmark the account and transfer balance back @@ -833,15 +834,18 @@ pub enum JournalEntry { /// Actions: Mark account as created /// Revert: Unmart account as created and reset nonce to zero. AccountCreated { address: Address }, - /// It is used to track both storage change and warm load of storage slot. For warm load in regard - /// to EIP-2929 AccessList had_value will be None - /// Action: Storage change or warm load - /// Revert: Revert to previous value or remove slot from storage - StorageChange { + /// Entry used to track storage changes + /// Action: Storage change + /// Revert: Revert to previous value + StorageChanged { address: Address, key: U256, - had_value: Option, //if none, storage slot was cold loaded from db and needs to be removed + had_value: U256, }, + /// Entry used to track storage warming introduced by EIP-2929. + /// Action: Storage warmed + /// Revert: Revert to cold state + StorageWarmed { address: Address, key: U256 }, /// It is used to track an EIP-1153 transient storage change. /// Action: Transient storage changed. /// Revert: Revert to previous value. From b988a0f1253cd8b63a7dbf76f038758cc851bb6a Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Fri, 14 Jun 2024 14:59:49 +0200 Subject: [PATCH 71/88] chore: pluralize EOFCreateInput (#1523) --- crates/interpreter/src/instructions/contract.rs | 4 ++-- crates/interpreter/src/interpreter_action.rs | 4 ++-- .../src/interpreter_action/eof_create_inputs.rs | 10 +++++----- crates/interpreter/src/lib.rs | 2 +- crates/revm/src/context/inner_evm_context.rs | 4 ++-- crates/revm/src/evm.rs | 4 ++-- crates/revm/src/handler/handle_types/execution.rs | 6 +++--- crates/revm/src/handler/mainnet/execution.rs | 4 ++-- crates/revm/src/inspector.rs | 6 +++--- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index f41d1b7f14..8457fb2afc 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -7,7 +7,7 @@ use crate::{ gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD}, interpreter::Interpreter, primitives::{Address, Bytes, Eof, Spec, SpecId::*, U256}, - CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInput, Host, + CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInputs, Host, InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE, }; use core::cmp::max; @@ -68,7 +68,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) // Send container for execution container is preverified. interpreter.next_action = InterpreterAction::EOFCreate { - inputs: Box::new(EOFCreateInput::new( + inputs: Box::new(EOFCreateInputs::new( interpreter.contract.target_address, created_address, value, diff --git a/crates/interpreter/src/interpreter_action.rs b/crates/interpreter/src/interpreter_action.rs index 0581e220e4..1459b0226e 100644 --- a/crates/interpreter/src/interpreter_action.rs +++ b/crates/interpreter/src/interpreter_action.rs @@ -9,7 +9,7 @@ pub use call_inputs::{CallInputs, CallScheme, CallValue}; pub use call_outcome::CallOutcome; pub use create_inputs::{CreateInputs, CreateScheme}; pub use create_outcome::CreateOutcome; -pub use eof_create_inputs::EOFCreateInput; +pub use eof_create_inputs::EOFCreateInputs; pub use eof_create_outcome::EOFCreateOutcome; use crate::InterpreterResult; @@ -24,7 +24,7 @@ pub enum InterpreterAction { /// CREATE or CREATE2 instruction called. Create { inputs: Box }, /// EOF CREATE instruction called. - EOFCreate { inputs: Box }, + EOFCreate { inputs: Box }, /// Interpreter finished execution. Return { result: InterpreterResult }, /// No action diff --git a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs index 28a1a471b9..4dc8190be5 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs @@ -4,7 +4,7 @@ use std::boxed::Box; /// Inputs for EOF create call. #[derive(Debug, Default, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct EOFCreateInput { +pub struct EOFCreateInputs { /// Caller of Eof Craate pub caller: Address, /// New contract address. @@ -19,7 +19,7 @@ pub struct EOFCreateInput { pub gas_limit: u64, } -impl EOFCreateInput { +impl EOFCreateInputs { /// Returns boxed EOFCreateInput or error. /// Internally calls [`Self::new_tx`]. pub fn new_tx_boxed(tx: &TxEnv, nonce: u64) -> Result, EofDecodeError> { @@ -31,7 +31,7 @@ impl EOFCreateInput { /// Legacy transaction still have optional nonce so we need to obtain it. pub fn new_tx(tx: &TxEnv, nonce: u64) -> Result { let (eof_init_code, input) = Eof::decode_dangling(tx.data.clone())?; - Ok(EOFCreateInput { + Ok(EOFCreateInputs { caller: tx.caller, created_address: tx.caller.create(nonce), value: tx.value, @@ -49,8 +49,8 @@ impl EOFCreateInput { eof_init_code: Eof, gas_limit: u64, input: Bytes, - ) -> EOFCreateInput { - EOFCreateInput { + ) -> EOFCreateInputs { + EOFCreateInputs { caller, created_address, value, diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 01db032788..64167dd410 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -37,7 +37,7 @@ pub use interpreter::{ }; pub use interpreter_action::{ CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, CreateScheme, - EOFCreateInput, EOFCreateOutcome, InterpreterAction, + EOFCreateInputs, EOFCreateOutcome, InterpreterAction, }; pub use opcode::{Instruction, OpCode, OPCODE_INFO_JUMPTABLE}; pub use primitives::{MAX_CODE_SIZE, MAX_INITCODE_SIZE}; diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 3272b0e82e..73fda3af32 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -1,7 +1,7 @@ use crate::{ db::Database, interpreter::{ - analysis::to_analysed, gas, return_ok, Contract, CreateInputs, EOFCreateInput, Gas, + analysis::to_analysed, gas, return_ok, Contract, CreateInputs, EOFCreateInputs, Gas, InstructionResult, Interpreter, InterpreterResult, LoadAccountResult, SStoreResult, SelfDestructResult, MAX_CODE_SIZE, }, @@ -245,7 +245,7 @@ impl InnerEvmContext { pub fn make_eofcreate_frame( &mut self, spec_id: SpecId, - inputs: &EOFCreateInput, + inputs: &EOFCreateInputs, ) -> Result> { let return_error = |e| { Ok(FrameOrResult::new_eofcreate_result( diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 80d536598d..d5b853d220 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -3,7 +3,7 @@ use crate::{ db::{Database, DatabaseCommit, EmptyDB}, handler::Handler, interpreter::{ - analysis::validate_eof, CallInputs, CreateInputs, EOFCreateInput, EOFCreateOutcome, Gas, + analysis::validate_eof, CallInputs, CreateInputs, EOFCreateInputs, EOFCreateOutcome, Gas, Host, InstructionResult, InterpreterAction, InterpreterResult, SharedMemory, }, primitives::{ @@ -374,7 +374,7 @@ impl Evm<'_, EXT, DB> { }); // Create EOFCreateInput from transaction initdata. - let eofcreate = EOFCreateInput::new_tx_boxed(&ctx.evm.env.tx, nonce) + let eofcreate = EOFCreateInputs::new_tx_boxed(&ctx.evm.env.tx, nonce) .ok() .and_then(|eofcreate| { // validate EOF initcode diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index b671631732..9e17def07c 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -6,7 +6,7 @@ use crate::{ CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ - opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInput, EOFCreateOutcome, + opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInputs, EOFCreateOutcome, InterpreterAction, InterpreterResult, }; use std::{boxed::Box, sync::Arc}; @@ -91,7 +91,7 @@ pub type InsertCreateOutcomeHandle<'a, EXT, DB> = Arc< pub type FrameEOFCreateHandle<'a, EXT, DB> = Arc< dyn Fn( &mut Context, - Box, + Box, ) -> Result::Error>> + 'a, >; @@ -255,7 +255,7 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { pub fn eofcreate( &self, context: &mut Context, - inputs: Box, + inputs: Box, ) -> Result> { (self.eofcreate)(context, inputs) } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index e55d6c4474..4ee557f81b 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -10,7 +10,7 @@ use crate::{ }; use core::mem; use revm_interpreter::{ - opcode::InstructionTables, CallOutcome, EOFCreateInput, EOFCreateOutcome, InterpreterAction, + opcode::InstructionTables, CallOutcome, EOFCreateInputs, EOFCreateOutcome, InterpreterAction, InterpreterResult, EMPTY_SHARED_MEMORY, }; use std::boxed::Box; @@ -164,7 +164,7 @@ pub fn insert_create_outcome( #[inline] pub fn eofcreate( context: &mut Context, - inputs: Box, + inputs: Box, ) -> Result> { context.evm.make_eofcreate_frame(SPEC::SPEC_ID, &inputs) } diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 2754aee822..26551c8d8d 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,5 +1,5 @@ use crate::{ - interpreter::{CallInputs, CreateInputs, EOFCreateInput, EOFCreateOutcome, Interpreter}, + interpreter::{CallInputs, CreateInputs, EOFCreateInputs, EOFCreateOutcome, Interpreter}, primitives::{db::Database, Address, Log, U256}, EvmContext, }; @@ -141,7 +141,7 @@ pub trait Inspector { fn eofcreate( &mut self, context: &mut EvmContext, - inputs: &mut EOFCreateInput, + inputs: &mut EOFCreateInputs, ) -> Option { let _ = context; let _ = inputs; @@ -152,7 +152,7 @@ pub trait Inspector { fn eofcreate_end( &mut self, context: &mut EvmContext, - inputs: &EOFCreateInput, + inputs: &EOFCreateInputs, outcome: EOFCreateOutcome, ) -> EOFCreateOutcome { let _ = context; From af6797eacc9e43e796e7b9f2fe848f0e03871f8c Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Sat, 15 Jun 2024 17:38:32 +0200 Subject: [PATCH 72/88] chore(interpreter): use U256::arithmetic_shr in SAR (#1525) --- .../interpreter/src/instructions/bitwise.rs | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/crates/interpreter/src/instructions/bitwise.rs b/crates/interpreter/src/instructions/bitwise.rs index 62edf11c5a..a02058419f 100644 --- a/crates/interpreter/src/instructions/bitwise.rs +++ b/crates/interpreter/src/instructions/bitwise.rs @@ -112,25 +112,12 @@ pub fn sar(interpreter: &mut Interpreter, _host: & pop_top!(interpreter, op1, op2); let shift = as_usize_saturated!(op1); - *op2 = if shift >= 256 { - // If the shift is 256 or more, the result depends on the sign of the last bit. - if op2.bit(255) { - U256::MAX // Negative number, all bits set to one. - } else { - U256::ZERO // Non-negative number, all bits set to zero. - } + *op2 = if shift < 256 { + op2.arithmetic_shr(shift) + } else if op2.bit(255) { + U256::MAX } else { - // Normal shift - if op2.bit(255) { - // Check the most significant bit. - // Arithmetic right shift for negative numbers. - let shifted_value = *op2 >> shift; - let mask = U256::MAX << (256 - shift); // Mask for the sign bits. - shifted_value | mask // Apply the mask to simulate the filling of sign bits. - } else { - // Logical right shift for non-negative numbers. - *op2 >> shift - } + U256::ZERO }; } From e32591e82bd36987e5541ae8538768ea31203f8b Mon Sep 17 00:00:00 2001 From: jpgonzalezra Date: Sat, 15 Jun 2024 14:04:13 -0300 Subject: [PATCH 73/88] feat(EOF): Put EOF bytecode behind an Arc (#1517) --- bins/revme/src/cmd/statetest/runner.rs | 2 +- .../interpreter/src/instructions/control.rs | 4 ++- crates/interpreter/src/instructions/data.rs | 5 ++-- crates/interpreter/src/interpreter.rs | 3 +- crates/primitives/src/bytecode.rs | 29 +++++++++++++++++-- crates/revm/src/context/inner_evm_context.rs | 6 ++-- 6 files changed, 39 insertions(+), 10 deletions(-) diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index b8892096e2..df14560a1f 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -260,7 +260,7 @@ pub fn execute_test_suite( let code_hash = keccak256(&info.code); let bytecode = match info.code.get(..2) { Some(magic) if magic == &EOF_MAGIC_BYTES => { - Bytecode::Eof(Eof::decode(info.code.clone()).unwrap()) + Bytecode::Eof(Eof::decode(info.code.clone()).unwrap().into()) } _ => Bytecode::new_raw(info.code), }; diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index db2bc70adf..4aacffd9e4 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -204,6 +204,8 @@ pub fn unknown(interpreter: &mut Interpreter, _host: &mut H) { #[cfg(test)] mod test { + use std::sync::Arc; + use revm_primitives::{bytes, eof::TypesSection, Bytecode, Eof, PragueSpec}; use super::*; @@ -322,7 +324,7 @@ mod test { eof.body.code_section.push(bytes2.clone()); eof.body.types_section.push(types); - let mut interp = Interpreter::new_bytecode(Bytecode::Eof(eof)); + let mut interp = Interpreter::new_bytecode(Bytecode::Eof(Arc::new(eof))); interp.gas = Gas::new(10000); interp } diff --git a/crates/interpreter/src/instructions/data.rs b/crates/interpreter/src/instructions/data.rs index 65df8a702e..dada108c1d 100644 --- a/crates/interpreter/src/instructions/data.rs +++ b/crates/interpreter/src/instructions/data.rs @@ -73,7 +73,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) gas_or_fail!(interpreter, cost_per_word(size as u64, VERYLOW)); let offset = as_usize_saturated!(offset); - let data = interpreter.contract.bytecode.eof().expect("EOF").data(); + let data = interpreter.contract.bytecode.eof().expect("eof").data(); // set data from the eof to the shared memory. Padd it with zeros. interpreter @@ -84,6 +84,7 @@ pub fn data_copy(interpreter: &mut Interpreter, _host: &mut H) #[cfg(test)] mod test { use revm_primitives::{b256, bytes, Bytecode, Bytes, Eof, PragueSpec}; + use std::sync::Arc; use super::*; use crate::{ @@ -101,7 +102,7 @@ mod test { eof.header.code_sizes[0] = code_bytes.len() as u16; eof.body.code_section[0] = code_bytes; - Bytecode::Eof(eof) + Bytecode::Eof(Arc::new(eof)) } #[test] diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index 4c3f6b841f..d74f7d08bc 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -17,6 +17,7 @@ use crate::{ use core::cmp::min; use revm_primitives::{Bytecode, Eof, U256}; use std::borrow::ToOwned; +use std::sync::Arc; /// EVM bytecode interpreter. #[derive(Debug)] @@ -100,7 +101,7 @@ impl Interpreter { } #[inline] - pub fn eof(&self) -> Option<&Eof> { + pub fn eof(&self) -> Option<&Arc> { self.contract.bytecode.eof() } diff --git a/crates/primitives/src/bytecode.rs b/crates/primitives/src/bytecode.rs index c5587ea651..75abcdd631 100644 --- a/crates/primitives/src/bytecode.rs +++ b/crates/primitives/src/bytecode.rs @@ -3,6 +3,7 @@ pub mod legacy; pub use eof::{Eof, EOF_MAGIC, EOF_MAGIC_BYTES, EOF_MAGIC_HASH}; pub use legacy::{JumpTable, LegacyAnalyzedBytecode}; +use std::sync::Arc; use crate::{keccak256, Bytes, B256, KECCAK_EMPTY}; @@ -15,7 +16,7 @@ pub enum Bytecode { /// The bytecode has been analyzed for valid jump destinations. LegacyAnalyzed(LegacyAnalyzedBytecode), /// Ethereum Object Format - Eof(Eof), + Eof(Arc), } impl Default for Bytecode { @@ -53,7 +54,7 @@ impl Bytecode { /// Return reference to the EOF if bytecode is EOF. #[inline] - pub const fn eof(&self) -> Option<&Eof> { + pub const fn eof(&self) -> Option<&Arc> { match self { Self::Eof(eof) => Some(eof), _ => None, @@ -166,3 +167,27 @@ impl Bytecode { self.len() == 0 } } + +#[cfg(test)] +mod tests { + use super::*; + use std::sync::Arc; + + #[test] + fn eof_arc_clone() { + let eof = Arc::new(Eof::default()); + let bytecode = Bytecode::Eof(Arc::clone(&eof)); + + // Cloning the Bytecode should not clone the underlying Eof + let cloned_bytecode = bytecode.clone(); + if let Bytecode::Eof(original_arc) = bytecode { + if let Bytecode::Eof(cloned_arc) = cloned_bytecode { + assert!(Arc::ptr_eq(&original_arc, &cloned_arc)); + } else { + panic!("Cloned bytecode is not Eof"); + } + } else { + panic!("Original bytecode is not Eof"); + } + } +} diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 73fda3af32..200345dc77 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -14,7 +14,7 @@ use crate::{ }, FrameOrResult, JournalCheckpoint, CALL_STACK_LIMIT, }; -use std::boxed::Box; +use std::{boxed::Box, sync::Arc}; /// EVM contexts contains data that EVM needs for execution. #[derive(Debug)] @@ -297,7 +297,7 @@ impl InnerEvmContext { let contract = Contract::new( inputs.input.clone(), // fine to clone as it is Bytes. - Bytecode::Eof(inputs.eof_init_code.clone()), + Bytecode::Eof(Arc::new(inputs.eof_init_code.clone())), None, inputs.created_address, inputs.caller, @@ -343,7 +343,7 @@ impl InnerEvmContext { // eof bytecode is going to be hashed. self.journaled_state - .set_code(address, Bytecode::Eof(bytecode)); + .set_code(address, Bytecode::Eof(Arc::new(bytecode))); } /// Make create frame. From 8f4c153a02d94d9e1e9275ba3cf73f599e23c6b6 Mon Sep 17 00:00:00 2001 From: jpgonzalezra Date: Sun, 16 Jun 2024 09:01:55 -0300 Subject: [PATCH 74/88] feat: mutable access for all fields in BundleBuilder (#1524) * feat: mutable access to state_storage and revert_storage in BundleBuilder * self review * Revert "self review" This reverts commit 20e46eea13285d17096d54f120d27db041ffa90f. * Revert "feat: mutable access to state_storage and revert_storage in BundleBuilder" This reverts commit 824e33fb29fdfa4d5e8f5eb616f6b3a53c6a0699. * feat: Add mutable getters for bundle state fields --- crates/revm/src/db/states/bundle_state.rs | 111 ++++++++++++++++++++++ 1 file changed, 111 insertions(+) diff --git a/crates/revm/src/db/states/bundle_state.rs b/crates/revm/src/db/states/bundle_state.rs index 8dd4edfe26..bd916b7ad6 100644 --- a/crates/revm/src/db/states/bundle_state.rs +++ b/crates/revm/src/db/states/bundle_state.rs @@ -233,6 +233,53 @@ impl BundleBuilder { pub fn get_states(&self) -> &HashSet
{ &self.states } + + /// Mutable getter for `states` field + pub fn get_states_mut(&mut self) -> &mut HashSet
{ + &mut self.states + } + + /// Mutable getter for `state_original` field + pub fn get_state_original_mut(&mut self) -> &mut HashMap { + &mut self.state_original + } + + /// Mutable getter for `state_present` field + pub fn get_state_present_mut(&mut self) -> &mut HashMap { + &mut self.state_present + } + + /// Mutable getter for `state_storage` field + pub fn get_state_storage_mut(&mut self) -> &mut HashMap> { + &mut self.state_storage + } + + /// Mutable getter for `reverts` field + pub fn get_reverts_mut(&mut self) -> &mut BTreeSet<(u64, Address)> { + &mut self.reverts + } + + /// Mutable getter for `revert_range` field + pub fn get_revert_range_mut(&mut self) -> &mut RangeInclusive { + &mut self.revert_range + } + + /// Mutable getter for `revert_account` field + pub fn get_revert_account_mut( + &mut self, + ) -> &mut HashMap<(u64, Address), Option>> { + &mut self.revert_account + } + + /// Mutable getter for `revert_storage` field + pub fn get_revert_storage_mut(&mut self) -> &mut HashMap<(u64, Address), Vec<(U256, U256)>> { + &mut self.revert_storage + } + + /// Mutable getter for `contracts` field + pub fn get_contracts_mut(&mut self) -> &mut HashMap { + &mut self.contracts + } } /// Bundle retention policy for applying substate to the bundle. @@ -1102,4 +1149,68 @@ mod tests { // account2 got inserted assert_eq!(test.state.get(&address2).unwrap().info, Some(account2)); } + + #[test] + fn test_getters() { + let mut builder = BundleBuilder::new(0..=3); + + // Test get_states and get_states_mut + assert!(builder.get_states().is_empty()); + builder.get_states_mut().insert(account1()); + assert!(builder.get_states().contains(&account1())); + + // Test get_state_original_mut + assert!(builder.get_state_original_mut().is_empty()); + builder + .get_state_original_mut() + .insert(account1(), AccountInfo::default()); + assert!(builder.get_state_original_mut().contains_key(&account1())); + + // Test get_state_present_mut + assert!(builder.get_state_present_mut().is_empty()); + builder + .get_state_present_mut() + .insert(account1(), AccountInfo::default()); + assert!(builder.get_state_present_mut().contains_key(&account1())); + + // Test get_state_storage_mut + assert!(builder.get_state_storage_mut().is_empty()); + builder + .get_state_storage_mut() + .insert(account1(), HashMap::new()); + assert!(builder.get_state_storage_mut().contains_key(&account1())); + + // Test get_reverts_mut + assert!(builder.get_reverts_mut().is_empty()); + builder.get_reverts_mut().insert((0, account1())); + assert!(builder.get_reverts_mut().contains(&(0, account1()))); + + // Test get_revert_range_mut + assert_eq!(builder.get_revert_range_mut().clone(), 0..=3); + + // Test get_revert_account_mut + assert!(builder.get_revert_account_mut().is_empty()); + builder + .get_revert_account_mut() + .insert((0, account1()), Some(None)); + assert!(builder + .get_revert_account_mut() + .contains_key(&(0, account1()))); + + // Test get_revert_storage_mut + assert!(builder.get_revert_storage_mut().is_empty()); + builder + .get_revert_storage_mut() + .insert((0, account1()), vec![(slot1(), U256::from(0))]); + assert!(builder + .get_revert_storage_mut() + .contains_key(&(0, account1()))); + + // Test get_contracts_mut + assert!(builder.get_contracts_mut().is_empty()); + builder + .get_contracts_mut() + .insert(B256::default(), Bytecode::default()); + assert!(builder.get_contracts_mut().contains_key(&B256::default())); + } } From dd98b3bb977396d23966e0a2f40d97678d931573 Mon Sep 17 00:00:00 2001 From: Thomas Coratger <60488569+tcoratger@users.noreply.github.com> Date: Sun, 16 Jun 2024 23:28:21 +0200 Subject: [PATCH 75/88] db: add setters to `BundleBuilder` with `&mut self` (#1527) * db: add settes to BundleBuilder with &mut self * fix comments --- crates/revm/src/db/states/bundle_state.rs | 111 +++++++++++++++++++--- 1 file changed, 99 insertions(+), 12 deletions(-) diff --git a/crates/revm/src/db/states/bundle_state.rs b/crates/revm/src/db/states/bundle_state.rs index bd916b7ad6..0b5c655c6d 100644 --- a/crates/revm/src/db/states/bundle_state.rs +++ b/crates/revm/src/db/states/bundle_state.rs @@ -79,30 +79,44 @@ impl BundleBuilder { } } + /// Apply a transformation to the builder. + pub fn apply(self, f: F) -> Self + where + F: FnOnce(Self) -> Self, + { + f(self) + } + + /// Apply a mutable transformation to the builder. + pub fn apply_mut(&mut self, f: F) -> &mut Self + where + F: FnOnce(&mut Self), + { + f(self); + self + } + /// Collect address info of BundleState state pub fn state_address(mut self, address: Address) -> Self { - self.states.insert(address); + self.set_state_address(address); self } /// Collect account info of BundleState state pub fn state_original_account_info(mut self, address: Address, original: AccountInfo) -> Self { - self.states.insert(address); - self.state_original.insert(address, original); + self.set_state_original_account_info(address, original); self } /// Collect account info of BundleState state pub fn state_present_account_info(mut self, address: Address, present: AccountInfo) -> Self { - self.states.insert(address); - self.state_present.insert(address, present); + self.set_state_present_account_info(address, present); self } /// Collect storage info of BundleState state pub fn state_storage(mut self, address: Address, storage: HashMap) -> Self { - self.states.insert(address); - self.state_storage.insert(address, storage); + self.set_state_storage(address, storage); self } @@ -111,7 +125,7 @@ impl BundleBuilder { /// `block_number` must respect `revert_range`, or the input /// will be ignored during the final build process pub fn revert_address(mut self, block_number: u64, address: Address) -> Self { - self.reverts.insert((block_number, address)); + self.set_revert_address(block_number, address); self } @@ -125,8 +139,7 @@ impl BundleBuilder { address: Address, account: Option>, ) -> Self { - self.reverts.insert((block_number, address)); - self.revert_account.insert((block_number, address), account); + self.set_revert_account_info(block_number, address, account); self } @@ -140,13 +153,87 @@ impl BundleBuilder { address: Address, storage: Vec<(U256, U256)>, ) -> Self { - self.reverts.insert((block_number, address)); - self.revert_storage.insert((block_number, address), storage); + self.set_revert_storage(block_number, address, storage); self } /// Collect contracts info pub fn contract(mut self, address: B256, bytecode: Bytecode) -> Self { + self.set_contract(address, bytecode); + self + } + + /// Set address info of BundleState state. + pub fn set_state_address(&mut self, address: Address) -> &mut Self { + self.states.insert(address); + self + } + + /// Set original account info of BundleState state. + pub fn set_state_original_account_info( + &mut self, + address: Address, + original: AccountInfo, + ) -> &mut Self { + self.states.insert(address); + self.state_original.insert(address, original); + self + } + + /// Set present account info of BundleState state. + pub fn set_state_present_account_info( + &mut self, + address: Address, + present: AccountInfo, + ) -> &mut Self { + self.states.insert(address); + self.state_present.insert(address, present); + self + } + + /// Set storage info of BundleState state. + pub fn set_state_storage( + &mut self, + address: Address, + storage: HashMap, + ) -> &mut Self { + self.states.insert(address); + self.state_storage.insert(address, storage); + self + } + + /// Set address info of BundleState reverts. + pub fn set_revert_address(&mut self, block_number: u64, address: Address) -> &mut Self { + self.reverts.insert((block_number, address)); + self + } + + /// Set account info of BundleState reverts. + pub fn set_revert_account_info( + &mut self, + block_number: u64, + address: Address, + account: Option>, + ) -> &mut Self { + self.reverts.insert((block_number, address)); + self.revert_account.insert((block_number, address), account); + self + } + + /// Set storage info of BundleState reverts. + pub fn set_revert_storage( + &mut self, + block_number: u64, + address: Address, + storage: Vec<(U256, U256)>, + ) -> &mut Self { + self.reverts.insert((block_number, address)); + self.revert_storage.insert((block_number, address), storage); + self + } + + /// Set contracts info. + pub fn set_contract(&mut self, address: B256, bytecode: Bytecode) -> &mut Self { self.contracts.insert(address, bytecode); self } From dc6e49758a3f7dfdf5dddc6e7c98a36dccedd9d5 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 17 Jun 2024 13:52:02 +0200 Subject: [PATCH 76/88] fix(EOF): target needed for EOFCREATE created address (#1536) --- crates/interpreter/src/instructions/contract.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 8457fb2afc..0b33efb939 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -59,7 +59,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) let created_address = interpreter .contract - .caller + .target_address .create2(salt.to_be_bytes(), keccak256(sub_container)); let gas_reduce = max(interpreter.gas.remaining() / 64, 5000); From dbbcec0156d0f4d0317540b1a9b717403b9df851 Mon Sep 17 00:00:00 2001 From: rakita Date: Mon, 17 Jun 2024 13:52:30 +0200 Subject: [PATCH 77/88] fix(EOF): set CallOrCreate result in EOFCREATE (#1535) --- crates/interpreter/src/instructions/contract.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index 0b33efb939..f57a786962 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -67,6 +67,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) gas!(interpreter, gas_limit); // Send container for execution container is preverified. + interpreter.instruction_result = InstructionResult::CallOrCreate; interpreter.next_action = InterpreterAction::EOFCreate { inputs: Box::new(EOFCreateInputs::new( interpreter.contract.target_address, From 3a62540e034bbd51ed10cb4375cdf5af670ebbc3 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:53:08 +0200 Subject: [PATCH 78/88] feat: bump alloy, re-enable alloydb (#1533) --- Cargo.lock | 484 ++++++++++++++++++++++++--------- crates/revm/Cargo.toml | 34 +-- crates/revm/src/db.rs | 10 +- crates/revm/src/db/alloydb.rs | 36 ++- crates/revm/src/db/ethersdb.rs | 5 +- 5 files changed, 400 insertions(+), 169 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce648c9552..5087985f71 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -44,10 +44,21 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "alloy-chains" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2feb5f466b3a786d5a622d8926418bc6a0d38bf632909f6ee9298a4a1d8c6e0" +dependencies = [ + "num_enum", + "strum", +] + [[package]] name = "alloy-consensus" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cc7579e4fb5558af44810f542c90d1145dba8b92c08211c215196160c48d2ea" dependencies = [ "alloy-eips", "alloy-primitives", @@ -59,8 +70,9 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bdbc8d98cc36ebe17bb5b42d0873137bc76628a4ee0f7e7acad5b8fc59d3597" dependencies = [ "alloy-primitives", "alloy-rlp", @@ -71,21 +83,11 @@ dependencies = [ "sha2", ] -[[package]] -name = "alloy-genesis" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" -dependencies = [ - "alloy-primitives", - "alloy-serde", - "serde", - "serde_json", -] - [[package]] name = "alloy-json-rpc" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d06d33b79246313c4103ef9596c721674a926f1ddc8b605aa2bac4d8ba94ee34" dependencies = [ "alloy-primitives", "serde", @@ -96,26 +98,29 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef742b478a2db5c27063cde82128dfbecffcd38237d7f682a91d3ecf6aa1836c" dependencies = [ "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-primitives", - "alloy-rpc-types", + "alloy-rpc-types-eth", + "alloy-serde", "alloy-signer", "alloy-sol-types", "async-trait", + "auto_impl", "futures-utils-wasm", "thiserror", ] [[package]] name = "alloy-primitives" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5277af0cbcc483ee6ad2c1e818090b5928d27f04fd6580680f31c1cf8068bcc2" +checksum = "f783611babedbbe90db3478c120fb5f5daacceffc210b39adc0af4fe0da70bad" dependencies = [ "alloy-rlp", "arbitrary", @@ -140,16 +145,18 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b786259a17acf318b9c423afe9669bec24ce9cdf59de153ff9a4009914bb6" dependencies = [ + "alloy-chains", + "alloy-consensus", "alloy-eips", "alloy-json-rpc", "alloy-network", "alloy-primitives", "alloy-rpc-client", - "alloy-rpc-types", - "alloy-rpc-types-trace", + "alloy-rpc-types-eth", "alloy-transport", "alloy-transport-http", "async-stream", @@ -159,7 +166,9 @@ dependencies = [ "futures", "futures-utils-wasm", "lru", + "pin-project", "reqwest 0.12.4", + "serde", "serde_json", "tokio", "tracing", @@ -190,8 +199,9 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "328a6a14aba6152ddf6d01bac5e17a70dbe9d6f343bf402b995c30bac63a1fbf" dependencies = [ "alloy-json-rpc", "alloy-transport", @@ -209,39 +219,28 @@ dependencies = [ ] [[package]] -name = "alloy-rpc-types" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +name = "alloy-rpc-types-eth" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bce0676f144be1eae71122d1d417885a3b063add0353b35e46cdf1440d6b33b1" dependencies = [ "alloy-consensus", "alloy-eips", - "alloy-genesis", "alloy-primitives", "alloy-rlp", "alloy-serde", "alloy-sol-types", - "itertools 0.12.1", + "itertools 0.13.0", "serde", "serde_json", "thiserror", ] -[[package]] -name = "alloy-rpc-types-trace" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" -dependencies = [ - "alloy-primitives", - "alloy-rpc-types", - "alloy-serde", - "serde", - "serde_json", -] - [[package]] name = "alloy-serde" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c224916316519558d8c2b6a60dc7626688c08f1b8951774702562dbcb8666ee" dependencies = [ "alloy-primitives", "serde", @@ -250,8 +249,9 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "227c5fd0ed6e06e1ccc30593f8ff6d9fb907ac5f03a709a6d687f0943494a229" dependencies = [ "alloy-primitives", "async-trait", @@ -263,9 +263,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30708a79919b082f2692423c8cc72fc250477e4a2ecb0d4a7244cd3cdb299965" +checksum = "4bad41a7c19498e3f6079f7744656328699f8ea3e783bdd10d85788cd439f572" dependencies = [ "alloy-sol-macro-expander", "alloy-sol-macro-input", @@ -277,9 +277,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c7a679ac01774ab7e00a567a918d4231ae692c5c8cedaf4e16956c3116d7896" +checksum = "fd9899da7d011b4fe4c406a524ed3e3f963797dbc93b45479d60341d3a27b252" dependencies = [ "alloy-sol-macro-input", "const-hex", @@ -295,9 +295,9 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "356da0c2228aa6675a5faaa08a3e4061b967f924753983d72b9a18d9a3fad44e" +checksum = "d32d595768fdc61331a132b6f65db41afae41b9b97d36c21eb1b955c422a7e60" dependencies = [ "const-hex", "dunce", @@ -310,9 +310,9 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6eb5e6234c0b62514992589fe1578f64d418dbc8ef5cd1ab2d7f2f568f599698" +checksum = "a49042c6d3b66a9fe6b2b5a8bf0d39fc2ae1ee0310a2a26ffedd79fb097878dd" dependencies = [ "alloy-primitives", "alloy-sol-macro", @@ -322,8 +322,9 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3628d81530263fe837a09cd527022f5728202a669973f04270942f4d390b5f5" dependencies = [ "alloy-json-rpc", "base64 0.22.1", @@ -335,19 +336,20 @@ dependencies = [ "tokio", "tower", "url", - "wasm-bindgen-futures", ] [[package]] name = "alloy-transport-http" -version = "0.1.0" -source = "git+https://github.com/alloy-rs/alloy.git?rev=44b8a6d#44b8a6da656602fd9fd2c52f28ecffa4acaed96c" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f35d34e7a51503c9ff267404a5850bd58f991b7ab524b892f364901e3576376" dependencies = [ "alloy-json-rpc", "alloy-transport", "reqwest 0.12.4", "serde_json", "tower", + "tracing", "url", ] @@ -604,9 +606,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "backtrace" -version = "0.3.72" +version = "0.3.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17c6a35df3749d2e8bb1b7b21a976d82b15548788d2735b9d82f329268f71a11" +checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" dependencies = [ "addr2line", "cc", @@ -833,18 +835,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.6" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9689a29b593160de5bc4aacab7b5d54fb52231de70122626c178e6a368994c7" +checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.5.6" +version = "4.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5387378c84f6faa26890ebf9f0a92989f8873d4d380467bcd0d8d8620424df" +checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" dependencies = [ "anstyle", "clap_lex", @@ -928,7 +930,7 @@ dependencies = [ "anes", "cast", "ciborium", - "clap 4.5.6", + "clap 4.5.7", "criterion-plot", "is-terminal", "itertools 0.10.5", @@ -1070,15 +1072,15 @@ dependencies = [ [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version 0.4.0", - "syn 1.0.109", + "syn 2.0.66", ] [[package]] @@ -1102,6 +1104,17 @@ dependencies = [ "subtle", ] +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "dunce" version = "1.0.4" @@ -1783,12 +1796,12 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", "http-body 1.0.0", "pin-project-lite", @@ -1796,9 +1809,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "d0e7a4dd27b9476dc40cb050d3632d3bba3a70ddbff012285f7f8559a1e7e545" [[package]] name = "httpdate" @@ -1900,14 +1913,134 @@ dependencies = [ "tracing", ] +[[package]] +name = "icu_collections" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "idna" -version = "0.5.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", + "smallvec", + "utf8_iter", ] [[package]] @@ -2014,9 +2147,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] @@ -2110,6 +2243,12 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +[[package]] +name = "litemap" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" + [[package]] name = "lock_api" version = "0.4.12" @@ -2137,9 +2276,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "microbench" @@ -2309,9 +2448,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.35.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8ec7ab813848ba4522158d5517a6093db1ded27575b070f4177b8d12b41db5e" +checksum = "576dfe1fc8f9df304abb159d767a29d0476f7750fbf8aa7ad07816004a207434" dependencies = [ "memchr", ] @@ -2813,9 +2952,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" dependencies = [ "bitflags 2.5.0", ] @@ -2834,9 +2973,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -2845,9 +2984,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "relative-path" @@ -2942,9 +3081,10 @@ dependencies = [ name = "revm" version = "9.0.0" dependencies = [ + "alloy-eips", "alloy-provider", "alloy-sol-types", - "alloy-transport-http", + "alloy-transport", "anyhow", "auto_impl", "cfg-if", @@ -3611,6 +3751,12 @@ dependencies = [ "der", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_assertions" version = "1.1.0" @@ -3712,9 +3858,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.7.5" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6fe08d08d84f2c0a77f1e7c46518789d745c2e87a2721791ed7c3c9bc78df28" +checksum = "8d71e19bca02c807c9faa67b5a47673ff231b6e7449b251695188522f1dc44b2" dependencies = [ "paste", "proc-macro2", @@ -3728,6 +3874,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -3846,30 +4003,25 @@ dependencies = [ ] [[package]] -name = "tinytemplate" -version = "1.2.1" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "serde", - "serde_json", + "displaydoc", + "zerovec", ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinytemplate" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc" dependencies = [ - "tinyvec_macros", + "serde", + "serde_json", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" version = "1.38.0" @@ -4112,27 +4264,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eaea85b334db583fe3274d12b4cd1880032beab409c0d774be044d4480ab9a94" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" -[[package]] -name = "unicode-normalization" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] - [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -4165,9 +4302,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" dependencies = [ "form_urlencoded", "idna", @@ -4180,6 +4317,18 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[package]] name = "valuable" version = "0.1.0" @@ -4519,6 +4668,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "ws_stream_wasm" version = "0.7.4" @@ -4547,6 +4708,30 @@ dependencies = [ "tap", ] +[[package]] +name = "yoke" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zerocopy" version = "0.7.34" @@ -4567,6 +4752,27 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "zerofrom" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", + "synstructure", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -4586,3 +4792,25 @@ dependencies = [ "quote", "syn 2.0.66", ] + +[[package]] +name = "zerovec" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 4655f27a33..7ca55cd73b 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -49,9 +49,9 @@ ethers-providers = { version = "2.0", optional = true } ethers-core = { version = "2.0", optional = true } # alloydb -# alloy-provider = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d", optional = true, default-features = false } -# alloy-rpc-types = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d", optional = true, default-features = false } -# alloy-transport = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d", optional = true, default-features = false } +alloy-provider = { version = "0.1", optional = true, default-features = false } +alloy-eips = { version = "0.1", optional = true, default-features = false } +alloy-transport = { version = "0.1", optional = true, default-features = false } [dev-dependencies] alloy-sol-types = { version = "0.7.0", default-features = false, features = [ @@ -64,11 +64,7 @@ indicatif = "0.17" reqwest = { version = "0.12" } rstest = "0.21.0" -alloy-provider = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d", default-features = false, features = [ - "reqwest", -] } -# needed for enabling TLS to use HTTPS connections when testing alloy DB -alloy-transport-http = { git = "https://github.com/alloy-rs/alloy.git", rev = "44b8a6d" } +alloy-provider = "0.1" [features] default = ["std", "c-kzg", "secp256k1", "portable", "blst"] @@ -100,21 +96,15 @@ negate-optimism-default-handler = [ "revm-interpreter/negate-optimism-default-handler", ] -ethersdb = [ +ethersdb = ["std", "dep:tokio", "dep:ethers-providers", "dep:ethers-core"] + +alloydb = [ "std", - "tokio", - "ethers-providers", - "ethers-core", -] # Negate optimism default handler - -# -# alloydb = [ -# "std", -# "tokio", -# "alloy-provider", -# "alloy-rpc-types", -# "alloy-transport", -# ] + "dep:tokio", + "dep:alloy-provider", + "dep:alloy-eips", + "dep:alloy-transport", +] dev = [ "memory_limit", diff --git a/crates/revm/src/db.rs b/crates/revm/src/db.rs index 03dd5ac0a3..f7c4904ab4 100644 --- a/crates/revm/src/db.rs +++ b/crates/revm/src/db.rs @@ -1,16 +1,16 @@ //! [Database] implementations. -//#[cfg(feature = "alloydb")] -//pub mod alloydb; +#[cfg(feature = "alloydb")] +mod alloydb; pub mod emptydb; #[cfg(feature = "ethersdb")] -pub mod ethersdb; +mod ethersdb; pub mod in_memory_db; pub mod states; pub use crate::primitives::db::*; -//#[cfg(feature = "alloydb")] -//pub use alloydb::AlloyDB; +#[cfg(feature = "alloydb")] +pub use alloydb::AlloyDB; pub use emptydb::{EmptyDB, EmptyDBTyped}; #[cfg(feature = "ethersdb")] pub use ethersdb::EthersDB; diff --git a/crates/revm/src/db/alloydb.rs b/crates/revm/src/db/alloydb.rs index 932fc32dbe..40945c68b0 100644 --- a/crates/revm/src/db/alloydb.rs +++ b/crates/revm/src/db/alloydb.rs @@ -2,9 +2,10 @@ use crate::{ db::{Database, DatabaseRef}, primitives::{AccountInfo, Address, Bytecode, B256, KECCAK_EMPTY, U256}, }; +use alloy_eips::BlockId; use alloy_provider::{Network, Provider}; -use alloy_rpc_types::BlockId; use alloy_transport::{Transport, TransportError}; +use std::future::IntoFuture; use tokio::runtime::{Builder, Handle}; /// An alloy-powered REVM [Database]. @@ -75,10 +76,21 @@ impl> DatabaseRef for AlloyD let f = async { let nonce = self .provider - .get_transaction_count(address, self.block_number); - let balance = self.provider.get_balance(address, self.block_number); - let code = self.provider.get_code_at(address, self.block_number); - tokio::join!(nonce, balance, code) + .get_transaction_count(address) + .block_id(self.block_number); + let balance = self + .provider + .get_balance(address) + .block_id(self.block_number); + let code = self + .provider + .get_code_at(address) + .block_id(self.block_number); + tokio::join!( + nonce.into_future(), + balance.into_future(), + code.into_future() + ) }; let (nonce, balance, code) = Self::block_on(f); @@ -112,11 +124,11 @@ impl> DatabaseRef for AlloyD } fn storage_ref(&self, address: Address, index: U256) -> Result { - let slot_val = Self::block_on(self.provider.get_storage_at( - address, - index, - self.block_number, - ))?; + let f = self + .provider + .get_storage_at(address, index) + .block_id(self.block_number); + let slot_val = Self::block_on(f.into_future())?; Ok(slot_val) } } @@ -147,11 +159,11 @@ impl> Database for AlloyDB::try_from( "https://mainnet.infura.io/v3/c60b0bb42f8a4c6481ecd229eddaca27", ) From de540b61330dc2448a679fc35b547323fe6e86de Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Mon, 17 Jun 2024 13:53:26 +0200 Subject: [PATCH 79/88] perf: avoid cloning precompiles (#1486) * perf: avoid cloning precompiles twice * perf: cow it up * pedantic changes, unsafe removed, nit renames * into string * nits * Make to_mut call cold fn on owned mutation * doc update --- crates/precompile/src/bls12_381/utils.rs | 3 +- crates/precompile/src/lib.rs | 41 +++- crates/primitives/src/precompile.rs | 20 +- .../revm/src/context/context_precompiles.rs | 211 +++++++++++++----- crates/revm/src/context/evm_context.rs | 11 +- .../revm/src/handler/mainnet/pre_execution.rs | 6 +- crates/revm/src/optimism/handler_register.rs | 6 +- 7 files changed, 218 insertions(+), 80 deletions(-) diff --git a/crates/precompile/src/bls12_381/utils.rs b/crates/precompile/src/bls12_381/utils.rs index ba18475c67..a2ed3cd885 100644 --- a/crates/precompile/src/bls12_381/utils.rs +++ b/crates/precompile/src/bls12_381/utils.rs @@ -1,8 +1,7 @@ -use core::cmp::Ordering; - use blst::{ blst_bendian_from_fp, blst_fp, blst_fp_from_bendian, blst_scalar, blst_scalar_from_bendian, }; +use core::cmp::Ordering; use revm_primitives::PrecompileError; /// Number of bits used in the BLS12-381 curve finite field elements. diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index 6f85a874d0..e930f2cdfc 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -28,9 +28,9 @@ use once_cell::race::OnceBox; pub use revm_primitives as primitives; pub use revm_primitives::{ precompile::{PrecompileError as Error, *}, - Address, Bytes, HashMap, Log, B256, + Address, Bytes, HashMap, HashSet, Log, B256, }; -use std::boxed::Box; +use std::{boxed::Box, vec::Vec}; pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { (len as u64 + 32 - 1) / 32 * word + base @@ -39,7 +39,9 @@ pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { #[derive(Clone, Default, Debug)] pub struct Precompiles { /// Precompiles. - pub inner: HashMap, + inner: HashMap, + /// Addresses of precompile. + addresses: HashSet
, } impl Precompiles { @@ -71,6 +73,11 @@ impl Precompiles { }) } + /// Returns inner HashMap of precompiles. + pub fn inner(&self) -> &HashMap { + &self.inner + } + /// Returns precompiles for Byzantium spec. pub fn byzantium() -> &'static Self { static INSTANCE: OnceBox = OnceBox::new(); @@ -168,13 +175,13 @@ impl Precompiles { /// Returns an iterator over the precompiles addresses. #[inline] - pub fn addresses(&self) -> impl Iterator { + pub fn addresses(&self) -> impl ExactSizeIterator { self.inner.keys() } /// Consumes the type and returns all precompile addresses. #[inline] - pub fn into_addresses(self) -> impl Iterator { + pub fn into_addresses(self) -> impl ExactSizeIterator { self.inner.into_keys() } @@ -206,11 +213,19 @@ impl Precompiles { self.inner.len() } + /// Returns the precompiles addresses as a set. + pub fn addresses_set(&self) -> &HashSet
{ + &self.addresses + } + /// Extends the precompiles with the given precompiles. /// /// Other precompiles with overwrite existing precompiles. + #[inline] pub fn extend(&mut self, other: impl IntoIterator) { - self.inner.extend(other.into_iter().map(Into::into)); + let items = other.into_iter().collect::>(); + self.addresses.extend(items.iter().map(|p| *p.address())); + self.inner.extend(items.into_iter().map(Into::into)); } } @@ -229,6 +244,20 @@ impl From for (Address, Precompile) { } } +impl PrecompileWithAddress { + /// Returns reference of address. + #[inline] + pub fn address(&self) -> &Address { + &self.0 + } + + /// Returns reference of precompile. + #[inline] + pub fn precompile(&self) -> &Precompile { + &self.1 + } +} + #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Ord, PartialOrd)] pub enum PrecompileSpecId { HOMESTEAD, diff --git a/crates/primitives/src/precompile.rs b/crates/primitives/src/precompile.rs index 275244f849..58f7cfe953 100644 --- a/crates/primitives/src/precompile.rs +++ b/crates/primitives/src/precompile.rs @@ -110,11 +110,25 @@ impl Precompile { /// Call the precompile with the given input and gas limit and return the result. pub fn call(&mut self, bytes: &Bytes, gas_price: u64, env: &Env) -> PrecompileResult { - match self { + match *self { + Precompile::Standard(p) => p(bytes, gas_price), + Precompile::Env(p) => p(bytes, gas_price, env), + Precompile::Stateful(ref p) => p.call(bytes, gas_price, env), + Precompile::StatefulMut(ref mut p) => p.call_mut(bytes, gas_price, env), + } + } + + /// Call the precompile with the given input and gas limit and return the result. + /// + /// Returns an error if the precompile is mutable. + pub fn call_ref(&self, bytes: &Bytes, gas_price: u64, env: &Env) -> PrecompileResult { + match *self { Precompile::Standard(p) => p(bytes, gas_price), Precompile::Env(p) => p(bytes, gas_price, env), - Precompile::Stateful(p) => p.call(bytes, gas_price, env), - Precompile::StatefulMut(p) => p.call_mut(bytes, gas_price, env), + Precompile::Stateful(ref p) => p.call(bytes, gas_price, env), + Precompile::StatefulMut(_) => Err(PrecompileErrors::Fatal { + msg: "call_ref on mutable stateful precompile".into(), + }), } } } diff --git a/crates/revm/src/context/context_precompiles.rs b/crates/revm/src/context/context_precompiles.rs index a6fdc5e67e..a47cef7132 100644 --- a/crates/revm/src/context/context_precompiles.rs +++ b/crates/revm/src/context/context_precompiles.rs @@ -1,15 +1,13 @@ +use super::InnerEvmContext; use crate::{ precompile::{Precompile, PrecompileResult}, - primitives::{db::Database, Address, Bytes, HashMap}, + primitives::{db::Database, Address, Bytes, HashMap, HashSet}, }; -use core::ops::{Deref, DerefMut}; use dyn_clone::DynClone; -use revm_precompile::Precompiles; +use revm_precompile::{PrecompileSpecId, PrecompileWithAddress, Precompiles}; use std::{boxed::Box, sync::Arc}; -use super::InnerEvmContext; - -/// Precompile and its handlers. +/// A single precompile handler. pub enum ContextPrecompile { /// Ordinary precompiles Ordinary(Precompile), @@ -24,53 +22,160 @@ pub enum ContextPrecompile { impl Clone for ContextPrecompile { fn clone(&self) -> Self { match self { - Self::Ordinary(arg0) => Self::Ordinary(arg0.clone()), - Self::ContextStateful(arg0) => Self::ContextStateful(arg0.clone()), - Self::ContextStatefulMut(arg0) => Self::ContextStatefulMut(arg0.clone()), + Self::Ordinary(p) => Self::Ordinary(p.clone()), + Self::ContextStateful(p) => Self::ContextStateful(p.clone()), + Self::ContextStatefulMut(p) => Self::ContextStatefulMut(p.clone()), } } } -#[derive(Clone)] +enum PrecompilesCow { + /// Default precompiles, returned by `Precompiles::new`. Used to fast-path the default case. + StaticRef(&'static Precompiles), + Owned(HashMap>), +} + +impl Clone for PrecompilesCow { + fn clone(&self) -> Self { + match *self { + PrecompilesCow::StaticRef(p) => PrecompilesCow::StaticRef(p), + PrecompilesCow::Owned(ref inner) => PrecompilesCow::Owned(inner.clone()), + } + } +} + +/// Precompiles context. pub struct ContextPrecompiles { - inner: HashMap>, + inner: PrecompilesCow, +} + +impl Clone for ContextPrecompiles { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } } impl ContextPrecompiles { - /// Returns precompiles addresses. + /// Creates a new precompiles context at the given spec ID. + /// + /// This is a cheap operation that does not allocate by reusing the global precompiles. #[inline] - pub fn addresses(&self) -> impl Iterator { - self.inner.keys() + pub fn new(spec_id: PrecompileSpecId) -> Self { + Self::from_static_precompiles(Precompiles::new(spec_id)) } - /// Extends the precompiles with the given precompiles. + /// Creates a new precompiles context from the given static precompiles. /// - /// Other precompiles with overwrite existing precompiles. + /// NOTE: The internal precompiles must not be `StatefulMut` or `call` will panic. + /// This is done because the default precompiles are not stateful. #[inline] - pub fn extend( - &mut self, - other: impl IntoIterator)>>, - ) { - self.inner.extend(other.into_iter().map(Into::into)); + pub fn from_static_precompiles(precompiles: &'static Precompiles) -> Self { + Self { + inner: PrecompilesCow::StaticRef(precompiles), + } + } + + /// Creates a new precompiles context from the given precompiles. + #[inline] + pub fn from_precompiles(precompiles: HashMap>) -> Self { + Self { + inner: PrecompilesCow::Owned(precompiles), + } + } + + /// Returns precompiles addresses as a HashSet. + pub fn addresses_set(&self) -> HashSet
{ + match self.inner { + PrecompilesCow::StaticRef(inner) => inner.addresses_set().clone(), + PrecompilesCow::Owned(ref inner) => inner.keys().cloned().collect(), + } + } + + /// Returns precompiles addresses. + #[inline] + pub fn addresses<'a>(&'a self) -> Box + 'a> { + match self.inner { + PrecompilesCow::StaticRef(inner) => Box::new(inner.addresses()), + PrecompilesCow::Owned(ref inner) => Box::new(inner.keys()), + } + } + + /// Returns `true` if the precompiles contains the given address. + #[inline] + pub fn contains(&self, address: &Address) -> bool { + match self.inner { + PrecompilesCow::StaticRef(inner) => inner.contains(address), + PrecompilesCow::Owned(ref inner) => inner.contains_key(address), + } } /// Call precompile and executes it. Returns the result of the precompile execution. - /// None if the precompile does not exist. + /// + /// Returns `None` if the precompile does not exist. #[inline] pub fn call( &mut self, - addess: Address, + address: &Address, bytes: &Bytes, gas_price: u64, evmctx: &mut InnerEvmContext, ) -> Option { - let precompile = self.inner.get_mut(&addess)?; + Some(match self.inner { + PrecompilesCow::StaticRef(p) => p.get(address)?.call_ref(bytes, gas_price, &evmctx.env), + PrecompilesCow::Owned(ref mut owned) => match owned.get_mut(address)? { + ContextPrecompile::Ordinary(p) => p.call(bytes, gas_price, &evmctx.env), + ContextPrecompile::ContextStateful(p) => p.call(bytes, gas_price, evmctx), + ContextPrecompile::ContextStatefulMut(p) => p.call_mut(bytes, gas_price, evmctx), + }, + }) + } - match precompile { - ContextPrecompile::Ordinary(p) => Some(p.call(bytes, gas_price, &evmctx.env)), - ContextPrecompile::ContextStatefulMut(p) => Some(p.call_mut(bytes, gas_price, evmctx)), - ContextPrecompile::ContextStateful(p) => Some(p.call(bytes, gas_price, evmctx)), + /// Returns a mutable reference to the precompiles map. + /// + /// Clones the precompiles map if it is shared. + #[inline] + pub fn to_mut(&mut self) -> &mut HashMap> { + if let PrecompilesCow::StaticRef(_) = self.inner { + self.mutate_into_owned(); } + + let PrecompilesCow::Owned(inner) = &mut self.inner else { + unreachable!("self is mutated to Owned.") + }; + inner + } + + /// Mutates Self into Owned variant, or do nothing if it is already Owned. + /// Mutation will clone all precompiles. + #[cold] + fn mutate_into_owned(&mut self) { + let PrecompilesCow::StaticRef(precompiles) = self.inner else { + return; + }; + self.inner = PrecompilesCow::Owned( + precompiles + .inner() + .iter() + .map(|(k, v)| (*k, v.clone().into())) + .collect(), + ); + } +} + +impl Extend<(Address, ContextPrecompile)> for ContextPrecompiles { + fn extend)>>(&mut self, iter: T) { + self.to_mut().extend(iter.into_iter().map(Into::into)) + } +} + +impl Extend for ContextPrecompiles { + fn extend>(&mut self, iter: T) { + self.to_mut().extend(iter.into_iter().map(|precompile| { + let (address, precompile) = precompile.into(); + (address, precompile.into()) + })); } } @@ -82,17 +187,9 @@ impl Default for ContextPrecompiles { } } -impl Deref for ContextPrecompiles { - type Target = HashMap>; - - fn deref(&self) -> &Self::Target { - &self.inner - } -} - -impl DerefMut for ContextPrecompiles { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.inner +impl Default for PrecompilesCow { + fn default() -> Self { + Self::Owned(Default::default()) } } @@ -132,22 +229,24 @@ impl From for ContextPrecompile { } } -impl From for ContextPrecompiles { - fn from(p: Precompiles) -> Self { - ContextPrecompiles { - inner: p.inner.into_iter().map(|(k, v)| (k, v.into())).collect(), - } - } -} - -impl From<&Precompiles> for ContextPrecompiles { - fn from(p: &Precompiles) -> Self { - ContextPrecompiles { - inner: p - .inner - .iter() - .map(|(&k, v)| (k, v.clone().into())) - .collect(), - } +#[cfg(test)] +mod tests { + use super::*; + use crate::db::EmptyDB; + + #[test] + fn test_precompiles_context() { + let custom_address = Address::with_last_byte(0xff); + + let mut precompiles = ContextPrecompiles::::new(PrecompileSpecId::HOMESTEAD); + assert_eq!(precompiles.addresses().count(), 4); + assert!(matches!(precompiles.inner, PrecompilesCow::StaticRef(_))); + assert!(!precompiles.contains(&custom_address)); + + let precompile = Precompile::Standard(|_, _| panic!()); + precompiles.extend([(custom_address, precompile.into())]); + assert_eq!(precompiles.addresses().count(), 5); + assert!(matches!(precompiles.inner, PrecompilesCow::Owned(_))); + assert!(precompiles.contains(&custom_address)); } } diff --git a/crates/revm/src/context/evm_context.rs b/crates/revm/src/context/evm_context.rs index 580759c2d3..e297579b46 100644 --- a/crates/revm/src/context/evm_context.rs +++ b/crates/revm/src/context/evm_context.rs @@ -7,7 +7,7 @@ use crate::{ interpreter::{ return_ok, CallInputs, Contract, Gas, InstructionResult, Interpreter, InterpreterResult, }, - primitives::{Address, Bytes, EVMError, Env, HashSet, U256}, + primitives::{Address, Bytes, EVMError, Env, U256}, ContextPrecompiles, FrameOrResult, CALL_STACK_LIMIT, }; use core::{ @@ -96,8 +96,7 @@ impl EvmContext { #[inline] pub fn set_precompiles(&mut self, precompiles: ContextPrecompiles) { // set warm loaded addresses. - self.journaled_state.warm_preloaded_addresses = - precompiles.addresses().copied().collect::>(); + self.journaled_state.warm_preloaded_addresses = precompiles.addresses_set(); self.precompiles = precompiles; } @@ -105,7 +104,7 @@ impl EvmContext { #[inline] fn call_precompile( &mut self, - address: Address, + address: &Address, input_data: &Bytes, gas: Gas, ) -> Result, EVMError> { @@ -199,7 +198,7 @@ impl EvmContext { _ => {} }; - if let Some(result) = self.call_precompile(inputs.bytecode_address, &inputs.input, gas)? { + if let Some(result) = self.call_precompile(&inputs.bytecode_address, &inputs.input, gas)? { if matches!(result.result, return_ok!()) { self.journaled_state.checkpoint_commit(); } else { @@ -232,7 +231,7 @@ pub(crate) mod test_utils { use crate::{ db::{CacheDB, EmptyDB}, journaled_state::JournaledState, - primitives::{address, SpecId, B256}, + primitives::{address, HashSet, SpecId, B256}, }; /// Mock caller address. diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index c0f4fe7bde..d3b9759dcf 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -3,7 +3,7 @@ //! They handle initial setup of the EVM, call loop and the final return of the EVM use crate::{ - precompile::{PrecompileSpecId, Precompiles}, + precompile::PrecompileSpecId, primitives::{ db::Database, Account, EVMError, Env, Spec, @@ -16,9 +16,7 @@ use crate::{ /// Main precompile load #[inline] pub fn load_precompiles() -> ContextPrecompiles { - Precompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) - .clone() - .into() + ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)) } /// Main load handle diff --git a/crates/revm/src/optimism/handler_register.rs b/crates/revm/src/optimism/handler_register.rs index d4996cca21..899ba41279 100644 --- a/crates/revm/src/optimism/handler_register.rs +++ b/crates/revm/src/optimism/handler_register.rs @@ -14,7 +14,7 @@ use crate::{ Context, ContextPrecompiles, FrameResult, }; use core::ops::Mul; -use revm_precompile::{secp256r1, PrecompileSpecId, Precompiles}; +use revm_precompile::{secp256r1, PrecompileSpecId}; use std::string::ToString; use std::sync::Arc; @@ -143,7 +143,7 @@ pub fn last_frame_return( /// Load precompiles for Optimism chain. #[inline] pub fn load_precompiles() -> ContextPrecompiles { - let mut precompiles = Precompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)).clone(); + let mut precompiles = ContextPrecompiles::new(PrecompileSpecId::from_spec_id(SPEC::SPEC_ID)); if SPEC::enabled(SpecId::FJORD) { precompiles.extend([ @@ -152,7 +152,7 @@ pub fn load_precompiles() -> ContextPrecompiles Date: Mon, 17 Jun 2024 16:11:56 +0100 Subject: [PATCH 80/88] feat(revm): derive serde for `BundleState` (#1539) --- crates/revm/src/db/states/account_status.rs | 1 + crates/revm/src/db/states/bundle_account.rs | 1 + crates/revm/src/db/states/bundle_state.rs | 1 + crates/revm/src/db/states/reverts.rs | 4 ++++ 4 files changed, 7 insertions(+) diff --git a/crates/revm/src/db/states/account_status.rs b/crates/revm/src/db/states/account_status.rs index aaf0b5b48e..5902ed9819 100644 --- a/crates/revm/src/db/states/account_status.rs +++ b/crates/revm/src/db/states/account_status.rs @@ -2,6 +2,7 @@ /// while we execute multiple transaction and even blocks over account that is in memory. /// This structure models all possible states that account can be in. #[derive(Clone, Copy, Default, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AccountStatus { #[default] LoadedNotExisting, diff --git a/crates/revm/src/db/states/bundle_account.rs b/crates/revm/src/db/states/bundle_account.rs index 9916139d12..5abf397bf7 100644 --- a/crates/revm/src/db/states/bundle_account.rs +++ b/crates/revm/src/db/states/bundle_account.rs @@ -15,6 +15,7 @@ use revm_precompile::HashMap; /// /// On selfdestruct storage original value is ignored. #[derive(Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BundleAccount { pub info: Option, pub original_info: Option, diff --git a/crates/revm/src/db/states/bundle_state.rs b/crates/revm/src/db/states/bundle_state.rs index 0b5c655c6d..22797c8761 100644 --- a/crates/revm/src/db/states/bundle_state.rs +++ b/crates/revm/src/db/states/bundle_state.rs @@ -393,6 +393,7 @@ impl BundleRetention { /// Reverts and created when TransitionState is applied to BundleState. /// And can be used to revert BundleState to the state before transition. #[derive(Default, Clone, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct BundleState { /// Account state. pub state: HashMap, diff --git a/crates/revm/src/db/states/reverts.rs b/crates/revm/src/db/states/reverts.rs index 5be2c932fd..4d8d3f402d 100644 --- a/crates/revm/src/db/states/reverts.rs +++ b/crates/revm/src/db/states/reverts.rs @@ -8,6 +8,7 @@ use std::vec::Vec; /// Contains reverts of multiple account in multiple transitions (Transitions as a block). #[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Reverts(Vec>); impl Deref for Reverts { @@ -80,6 +81,7 @@ impl Reverts { /// AccountRevert is structured in this way as we need to save it inside database. /// And we need to be able to read it from database. #[derive(Clone, Default, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct AccountRevert { pub account: AccountInfoRevert, pub storage: HashMap, @@ -182,6 +184,7 @@ impl AccountRevert { /// Depending on previous state of account info this /// will tell us what to do on revert. #[derive(Clone, Default, Debug, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum AccountInfoRevert { #[default] /// Nothing changed @@ -200,6 +203,7 @@ pub enum AccountInfoRevert { /// Note: It is completely different state if Storage is Zero or Some or if Storage was /// Destroyed. Because if it is destroyed, previous values can be found in database or it can be zero. #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum RevertToSlot { Some(U256), Destroyed, From c2a04cbb2ba5862e56212caa6ceca2c11bcac3d0 Mon Sep 17 00:00:00 2001 From: rakita Date: Tue, 18 Jun 2024 12:23:11 +0200 Subject: [PATCH 81/88] fix(eof): output gas for eofcreate (#1540) --- crates/interpreter/src/gas.rs | 5 +++++ crates/interpreter/src/instructions/contract.rs | 4 +--- .../interpreter/src/instructions/contract/call_helpers.rs | 6 ++++-- crates/revm/src/context/inner_evm_context.rs | 8 ++++++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/crates/interpreter/src/gas.rs b/crates/interpreter/src/gas.rs index 01a3ebeafe..1407ae7bc6 100644 --- a/crates/interpreter/src/gas.rs +++ b/crates/interpreter/src/gas.rs @@ -72,6 +72,11 @@ impl Gas { self.remaining } + /// Return remaining gas after subtracting 63/64 parts. + pub const fn remaining_63_of_64_parts(&self) -> u64 { + self.remaining - self.remaining / 64 + } + /// Erases a gas cost from the totals. #[inline] pub fn erase_cost(&mut self, returned: u64) { diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index f57a786962..aac3d38f76 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -62,10 +62,8 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) .target_address .create2(salt.to_be_bytes(), keccak256(sub_container)); - let gas_reduce = max(interpreter.gas.remaining() / 64, 5000); - let gas_limit = interpreter.gas().remaining().saturating_sub(gas_reduce); + let gas_limit = interpreter.gas().remaining_63_of_64_parts(); gas!(interpreter, gas_limit); - // Send container for execution container is preverified. interpreter.instruction_result = InstructionResult::CallOrCreate; interpreter.next_action = InterpreterAction::EOFCreate { diff --git a/crates/interpreter/src/instructions/contract/call_helpers.rs b/crates/interpreter/src/instructions/contract/call_helpers.rs index f9acc74901..77fa16d6d3 100644 --- a/crates/interpreter/src/instructions/contract/call_helpers.rs +++ b/crates/interpreter/src/instructions/contract/call_helpers.rs @@ -55,9 +55,11 @@ pub fn calc_call_gas( // EIP-150: Gas cost changes for IO-heavy operations let gas_limit = if SPEC::enabled(TANGERINE) { - let gas = interpreter.gas().remaining(); // take l64 part of gas_limit - min(gas - gas / 64, local_gas_limit) + min( + interpreter.gas().remaining_63_of_64_parts(), + local_gas_limit, + ) } else { local_gas_limit }; diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index 200345dc77..c83d5ec14a 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -334,6 +334,14 @@ impl InnerEvmContext { 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) { + self.journaled_state.checkpoint_revert(journal_checkpoint); + interpreter_result.result = InstructionResult::OutOfGas; + return; + } + // commit changes reduces depth by -1. self.journaled_state.checkpoint_commit(); From 2f46a13679a8cf4cd8d3c405cbe25fb2a6f6b2f3 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Tue, 18 Jun 2024 21:56:59 +0200 Subject: [PATCH 82/88] chore: simplify Interpreter serde (#1544) --- crates/interpreter/src/interpreter/serde.rs | 296 ++++++-------------- 1 file changed, 90 insertions(+), 206 deletions(-) diff --git a/crates/interpreter/src/interpreter/serde.rs b/crates/interpreter/src/interpreter/serde.rs index eb4d8524fc..2cc8fd0496 100644 --- a/crates/interpreter/src/interpreter/serde.rs +++ b/crates/interpreter/src/interpreter/serde.rs @@ -1,36 +1,67 @@ +use super::Interpreter; use crate::{ Contract, FunctionStack, Gas, InstructionResult, InterpreterAction, SharedMemory, Stack, }; - -use super::Interpreter; use revm_primitives::Bytes; -use serde::de::{self, MapAccess, Visitor}; -use serde::ser::SerializeStruct; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use std::fmt; + +#[derive(Serialize)] +struct InterpreterSerde<'a> { + program_counter: usize, + + gas: &'a Gas, + contract: &'a Contract, + instruction_result: InstructionResult, + bytecode: &'a Bytes, + is_eof: bool, + is_eof_init: bool, + shared_memory: &'a SharedMemory, + stack: &'a Stack, + function_stack: &'a FunctionStack, + return_data_buffer: &'a Bytes, + is_static: bool, + next_action: &'a InterpreterAction, +} + +#[derive(Deserialize)] +struct InterpreterDe { + program_counter: usize, + + gas: Gas, + contract: Contract, + instruction_result: InstructionResult, + bytecode: Bytes, + is_eof: bool, + is_eof_init: bool, + shared_memory: SharedMemory, + stack: Stack, + function_stack: FunctionStack, + return_data_buffer: Bytes, + is_static: bool, + next_action: InterpreterAction, +} impl Serialize for Interpreter { fn serialize(&self, serializer: S) -> Result where S: Serializer, { - let mut state = serializer.serialize_struct("Interpreter", 8)?; - // Convert the instruction pointer to a usize for serialization - let program_counter = self.program_counter(); - state.serialize_field("program_counter", &program_counter)?; - state.serialize_field("gas", &self.gas)?; - state.serialize_field("contract", &self.contract)?; - state.serialize_field("instruction_result", &self.instruction_result)?; - state.serialize_field("bytecode", &self.bytecode)?; - state.serialize_field("is_eof", &self.is_eof)?; - state.serialize_field("is_eof_init", &self.is_eof_init)?; - state.serialize_field("shared_memory", &self.shared_memory)?; - state.serialize_field("stack", &self.stack)?; - state.serialize_field("function_stack", &self.function_stack)?; - state.serialize_field("return_data_buffer", &self.return_data_buffer)?; - state.serialize_field("is_static", &self.is_static)?; - state.serialize_field("next_action", &self.next_action)?; - state.end() + InterpreterSerde { + program_counter: self.program_counter(), + gas: &self.gas, + contract: &self.contract, + instruction_result: self.instruction_result, + bytecode: &self.bytecode, + is_eof: self.is_eof, + is_eof_init: self.is_eof_init, + shared_memory: &self.shared_memory, + stack: &self.stack, + function_stack: &self.function_stack, + return_data_buffer: &self.return_data_buffer, + is_static: self.is_static, + next_action: &self.next_action, + } + .serialize(serializer) } } @@ -39,192 +70,45 @@ impl<'de> Deserialize<'de> for Interpreter { where D: Deserializer<'de>, { - struct InterpreterVisitor; - - #[derive(serde::Deserialize)] - #[serde(field_identifier, rename_all = "lowercase")] - enum InterpreterFields { - ProgramCounter, - Gas, - Contract, - InstructionResult, - Bytecode, - IsEof, - IsEofInit, - SharedMemory, - Stack, - FunctionStack, - ReturnDataBuffer, - IsStatic, - NextAction, - } - - #[allow(clippy::too_many_arguments)] - fn rebuild_interp( - program_counter: isize, - gas: Gas, - contract: Contract, - instruction_result: InstructionResult, - bytecode: Bytes, - is_eof: bool, - is_eof_init: bool, - shared_memory: SharedMemory, - stack: Stack, - function_stack: FunctionStack, - return_data_buffer: Bytes, - is_static: bool, - next_action: InterpreterAction, - ) -> Result { - // Reconstruct the instruction pointer from usize - if program_counter < 0 || program_counter >= bytecode.len() as isize { - return Err("program_counter index out of range"); - } - - // SAFETY: range of program_counter checked above - let instruction_pointer = unsafe { bytecode.as_ptr().offset(program_counter) }; - - // Construct and return the Interpreter instance - Ok(Interpreter { - instruction_pointer, - gas, - contract, - instruction_result, - bytecode, - is_eof, - is_eof_init, - shared_memory, - stack, - function_stack, - return_data_buffer, - is_static, - next_action, - }) - } - - impl<'de> Visitor<'de> for InterpreterVisitor { - type Value = Interpreter; - - fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { - formatter.write_str("struct Interpreter") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: de::SeqAccess<'de>, - { - macro_rules! extract_field { - ($i:ident, $idx:expr) => { - let $i = seq - .next_element()? - .ok_or_else(|| de::Error::invalid_length($idx, &self))?; - }; - } - extract_field!(instruction_pointer, 0); - extract_field!(gas, 1); - extract_field!(contract, 2); - extract_field!(instruction_result, 3); - extract_field!(bytecode, 4); - extract_field!(is_eof, 5); - extract_field!(is_eof_init, 6); - extract_field!(shared_memory, 7); - extract_field!(stack, 8); - extract_field!(function_stack, 9); - extract_field!(return_data_buffer, 10); - extract_field!(is_static, 11); - extract_field!(next_action, 12); - rebuild_interp( - instruction_pointer, - gas, - contract, - instruction_result, - bytecode, - is_eof, - is_eof_init, - shared_memory, - stack, - function_stack, - return_data_buffer, - is_static, - next_action, - ) - .map_err(de::Error::custom) - } - - fn visit_map(self, mut map: V) -> Result - where - V: MapAccess<'de>, - { - macro_rules! parse_map { - ( $(($enum:pat, $var_name:ident)),* ) => { - $( - let mut $var_name = None; - )* - while let Some(key) = map.next_key()? { - match key { - $( - $enum => { - $var_name = Some(map.next_value()?); - } - )* - } - } - $( - let $var_name = $var_name.ok_or_else(|| de::Error::missing_field(stringify!($var_name)))?; - )* - }; - } - parse_map!( - (InterpreterFields::ProgramCounter, program_counter), - (InterpreterFields::Gas, gas), - (InterpreterFields::Contract, contract), - (InterpreterFields::InstructionResult, instruction_result), - (InterpreterFields::Bytecode, bytecode), - (InterpreterFields::IsEof, is_eof), - (InterpreterFields::IsEofInit, is_eof_init), - (InterpreterFields::SharedMemory, shared_memory), - (InterpreterFields::Stack, stack), - (InterpreterFields::FunctionStack, function_stack), - (InterpreterFields::ReturnDataBuffer, return_data_buffer), - (InterpreterFields::IsStatic, is_static), - (InterpreterFields::NextAction, next_action) - ); - - rebuild_interp( - program_counter, - gas, - contract, - instruction_result, - bytecode, - is_eof, - is_eof_init, - shared_memory, - stack, - function_stack, - return_data_buffer, - is_static, - next_action, - ) - .map_err(de::Error::custom) - } + let InterpreterDe { + program_counter, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + } = InterpreterDe::deserialize(deserializer)?; + + // Reconstruct the instruction pointer from usize + if program_counter >= bytecode.len() { + return Err(serde::de::Error::custom("program_counter out of bounds")); } - const FIELDS: &[&str] = &[ - "program_counter", - "gas", - "contract", - "instruction_result", - "bytecode", - "is_eof", - "is_eof_init", - "shared_memory", - "stack", - "function_stack", - "return_data_buffer", - "is_static", - "next_action", - ]; - - deserializer.deserialize_struct("Interpreter", FIELDS, InterpreterVisitor) + // SAFETY: range of program_counter checked above + let instruction_pointer = unsafe { bytecode.as_ptr().add(program_counter) }; + + Ok(Interpreter { + instruction_pointer, + gas, + contract, + instruction_result, + bytecode, + is_eof, + is_eof_init, + shared_memory, + stack, + function_stack, + return_data_buffer, + is_static, + next_action, + }) } } From e6b52af25d61207c2f9b728c16280c00aeee8506 Mon Sep 17 00:00:00 2001 From: DaniPopes <57450786+DaniPopes@users.noreply.github.com> Date: Wed, 19 Jun 2024 13:05:35 +0200 Subject: [PATCH 83/88] chore: remove DatabaseWithDebugError (#1545) --- crates/primitives/src/db.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/primitives/src/db.rs b/crates/primitives/src/db.rs index ca4ced987b..80c232cc99 100644 --- a/crates/primitives/src/db.rs +++ b/crates/primitives/src/db.rs @@ -67,12 +67,6 @@ impl From for WrapDatabaseRef { } } -pub trait DatabaseWithDebugError: Database -where - ::Error: std::fmt::Debug + std::fmt::Display, -{ -} - impl Database for WrapDatabaseRef { type Error = T::Error; From 7db1adcfc29480d3f0c0af134b9757aadd7f3b6b Mon Sep 17 00:00:00 2001 From: Wodann Date: Wed, 19 Jun 2024 06:07:54 -0500 Subject: [PATCH 84/88] refactor: replace TransactTo with TxKind (#1542) * refactor: replace TransactTo with TxKind * misc: apply review suggestions --- bins/revm-test/src/bin/analysis.rs | 4 +- bins/revm-test/src/bin/burntpix/main.rs | 4 +- bins/revm-test/src/bin/snailtracer.rs | 4 +- bins/revm-test/src/bin/transfer.rs | 4 +- bins/revme/src/cmd/evmrunner.rs | 4 +- bins/revme/src/cmd/statetest/runner.rs | 6 +-- .../interpreter/src/interpreter/contract.rs | 8 ++-- .../src/interpreter_action/call_inputs.rs | 4 +- .../src/interpreter_action/create_inputs.rs | 4 +- crates/primitives/src/env.rs | 41 +++---------------- crates/primitives/src/lib.rs | 2 +- crates/revm/benches/bench.rs | 8 ++-- crates/revm/src/builder.rs | 6 +-- crates/revm/src/evm.rs | 6 +-- .../revm/src/handler/mainnet/pre_execution.rs | 4 +- crates/revm/src/inspector/customprinter.rs | 2 +- crates/revm/src/inspector/gas.rs | 5 +-- crates/revm/src/inspector/handler_register.rs | 5 +-- crates/revm/src/optimism/fast_lz.rs | 5 +-- .../src/crates/primitives/environment.md | 2 +- examples/fork_ref_transact.rs | 4 +- examples/generate_block_traces.rs | 8 ++-- examples/uniswap_v2_usdc_swap.rs | 12 +++--- 23 files changed, 59 insertions(+), 93 deletions(-) diff --git a/bins/revm-test/src/bin/analysis.rs b/bins/revm-test/src/bin/analysis.rs index 40bbcf39c4..a6fa92f46d 100644 --- a/bins/revm-test/src/bin/analysis.rs +++ b/bins/revm-test/src/bin/analysis.rs @@ -1,7 +1,7 @@ use revm::{ db::BenchmarkDB, interpreter::analysis::to_analysed, - primitives::{address, bytes, Bytecode, Bytes, TransactTo}, + primitives::{address, bytes, Bytecode, Bytes, TxKind}, Evm, }; use std::time::Instant; @@ -17,7 +17,7 @@ fn main() { .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); //evm.env.tx.data = Bytes::from(hex::decode("30627b7c").unwrap()); tx.data = bytes!("8035F0CE"); }) diff --git a/bins/revm-test/src/bin/burntpix/main.rs b/bins/revm-test/src/bin/burntpix/main.rs index 8cd9eea66c..ea1ac56f70 100644 --- a/bins/revm-test/src/bin/burntpix/main.rs +++ b/bins/revm-test/src/bin/burntpix/main.rs @@ -5,7 +5,7 @@ use revm::{ db::{CacheDB, EmptyDB}, primitives::{ address, hex, keccak256, AccountInfo, Address, Bytecode, Bytes, ExecutionResult, Output, - TransactTo, B256, U256, + TxKind, B256, U256, }, Evm, }; @@ -38,7 +38,7 @@ fn main() { let mut evm = Evm::builder() .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TransactTo::Call(BURNTPIX_MAIN_ADDRESS); + tx.transact_to = TxKind::Call(BURNTPIX_MAIN_ADDRESS); tx.data = run_call_data.clone().into(); }) .with_db(db) diff --git a/bins/revm-test/src/bin/snailtracer.rs b/bins/revm-test/src/bin/snailtracer.rs index a931dc3a31..cebe950a7f 100644 --- a/bins/revm-test/src/bin/snailtracer.rs +++ b/bins/revm-test/src/bin/snailtracer.rs @@ -1,7 +1,7 @@ use revm::{ db::BenchmarkDB, interpreter::analysis::to_analysed, - primitives::{address, bytes, Bytecode, Bytes, TransactTo}, + primitives::{address, bytes, Bytecode, Bytes, TxKind}, Evm, }; @@ -14,7 +14,7 @@ pub fn simple_example() { .modify_tx_env(|tx| { // execution globals block hash/gas_limit/coinbase/timestamp.. tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.data = bytes!("30627b7c"); }) .build(); diff --git a/bins/revm-test/src/bin/transfer.rs b/bins/revm-test/src/bin/transfer.rs index 8abd0910ef..4fa1f29b09 100644 --- a/bins/revm-test/src/bin/transfer.rs +++ b/bins/revm-test/src/bin/transfer.rs @@ -1,6 +1,6 @@ use revm::{ db::BenchmarkDB, - primitives::{Bytecode, TransactTo, U256}, + primitives::{Bytecode, TxKind, U256}, Evm, }; @@ -16,7 +16,7 @@ fn main() { .parse() .unwrap(); tx.value = U256::from(10); - tx.transact_to = TransactTo::Call( + tx.transact_to = TxKind::Call( "0x0000000000000000000000000000000000000000" .parse() .unwrap(), diff --git a/bins/revme/src/cmd/evmrunner.rs b/bins/revme/src/cmd/evmrunner.rs index 8c93d3182b..50a75a8deb 100644 --- a/bins/revme/src/cmd/evmrunner.rs +++ b/bins/revme/src/cmd/evmrunner.rs @@ -2,7 +2,7 @@ use revm::{ db::BenchmarkDB, inspector_handle_register, inspectors::TracerEip3155, - primitives::{Address, Bytecode, TransactTo}, + primitives::{Address, Bytecode, TxKind}, Evm, }; use std::io::Error as IoError; @@ -86,7 +86,7 @@ impl Cmd { tx.caller = "0x0000000000000000000000000000000000000001" .parse() .unwrap(); - tx.transact_to = TransactTo::Call(Address::ZERO); + tx.transact_to = TxKind::Call(Address::ZERO); tx.data = input; }) .build(); diff --git a/bins/revme/src/cmd/statetest/runner.rs b/bins/revme/src/cmd/statetest/runner.rs index df14560a1f..06ab1d64bd 100644 --- a/bins/revme/src/cmd/statetest/runner.rs +++ b/bins/revme/src/cmd/statetest/runner.rs @@ -10,7 +10,7 @@ use revm::{ inspectors::TracerEip3155, primitives::{ calc_excess_blob_gas, keccak256, Bytecode, Bytes, EVMResultGeneric, Env, Eof, - ExecutionResult, SpecId, TransactTo, B256, EOF_MAGIC_BYTES, U256, + ExecutionResult, SpecId, TxKind, B256, EOF_MAGIC_BYTES, U256, }, Evm, State, }; @@ -364,8 +364,8 @@ pub fn execute_test_suite( .collect(); let to = match unit.transaction.to { - Some(add) => TransactTo::Call(add), - None => TransactTo::Create, + Some(add) => TxKind::Call(add), + None => TxKind::Create, }; env.tx.transact_to = to; diff --git a/crates/interpreter/src/interpreter/contract.rs b/crates/interpreter/src/interpreter/contract.rs index f8625e8533..49e511f66e 100644 --- a/crates/interpreter/src/interpreter/contract.rs +++ b/crates/interpreter/src/interpreter/contract.rs @@ -1,6 +1,8 @@ +use revm_primitives::TxKind; + use super::analysis::to_analysed; use crate::{ - primitives::{Address, Bytecode, Bytes, Env, TransactTo, B256, U256}, + primitives::{Address, Bytecode, Bytes, Env, B256, U256}, CallInputs, }; @@ -50,8 +52,8 @@ impl Contract { #[inline] pub fn new_env(env: &Env, bytecode: Bytecode, hash: Option) -> Self { let contract_address = match env.tx.transact_to { - TransactTo::Call(caller) => caller, - TransactTo::Create => Address::ZERO, + TxKind::Call(caller) => caller, + TxKind::Create => Address::ZERO, }; Self::new( env.tx.data.clone(), diff --git a/crates/interpreter/src/interpreter_action/call_inputs.rs b/crates/interpreter/src/interpreter_action/call_inputs.rs index 0e51bd5ec6..85d0c8fb71 100644 --- a/crates/interpreter/src/interpreter_action/call_inputs.rs +++ b/crates/interpreter/src/interpreter_action/call_inputs.rs @@ -1,4 +1,4 @@ -use crate::primitives::{Address, Bytes, TransactTo, TxEnv, U256}; +use crate::primitives::{Address, Bytes, TxEnv, TxKind, U256}; use core::ops::Range; use std::boxed::Box; @@ -47,7 +47,7 @@ impl CallInputs { /// /// Returns `None` if the transaction is not a call. pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { - let TransactTo::Call(target_address) = tx_env.transact_to else { + let TxKind::Call(target_address) = tx_env.transact_to else { return None; }; Some(CallInputs { diff --git a/crates/interpreter/src/interpreter_action/create_inputs.rs b/crates/interpreter/src/interpreter_action/create_inputs.rs index 6db951831a..adae96ac2d 100644 --- a/crates/interpreter/src/interpreter_action/create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/create_inputs.rs @@ -1,5 +1,5 @@ pub use crate::primitives::CreateScheme; -use crate::primitives::{Address, Bytes, TransactTo, TxEnv, U256}; +use crate::primitives::{Address, Bytes, TxEnv, TxKind, U256}; use std::boxed::Box; /// Inputs for a create call. @@ -21,7 +21,7 @@ pub struct CreateInputs { impl CreateInputs { /// Creates new create inputs. pub fn new(tx_env: &TxEnv, gas_limit: u64) -> Option { - let TransactTo::Create = tx_env.transact_to else { + let TxKind::Create = tx_env.transact_to else { return None; }; diff --git a/crates/primitives/src/env.rs b/crates/primitives/src/env.rs index 44b0736977..fde04c5734 100644 --- a/crates/primitives/src/env.rs +++ b/crates/primitives/src/env.rs @@ -1,5 +1,6 @@ pub mod handler_cfg; +use alloy_primitives::TxKind; pub use handler_cfg::{CfgEnvWithHandlerCfg, EnvWithHandlerCfg, HandlerCfg}; use crate::{ @@ -503,7 +504,7 @@ pub struct TxEnv { /// The gas price of the transaction. pub gas_price: U256, /// The destination of the transaction. - pub transact_to: TransactTo, + pub transact_to: TxKind, /// The value sent to `transact_to`. pub value: U256, /// The data of the transaction. @@ -585,7 +586,7 @@ impl Default for TxEnv { gas_limit: u64::MAX, gas_price: U256::ZERO, gas_priority_fee: None, - transact_to: TransactTo::Call(Address::ZERO), // will do nothing + transact_to: TxKind::Call(Address::ZERO), // will do nothing value: U256::ZERO, data: Bytes::new(), chain_id: None, @@ -658,40 +659,8 @@ pub struct OptimismFields { pub enveloped_tx: Option, } -/// Transaction destination. -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub enum TransactTo { - /// Simple call to an address. - Call(Address), - /// Contract creation. - Create, -} - -impl TransactTo { - /// Calls the given address. - #[inline] - pub fn call(address: Address) -> Self { - Self::Call(address) - } - - /// Creates a contract. - #[inline] - pub fn create() -> Self { - Self::Create - } - /// Returns `true` if the transaction is `Call`. - #[inline] - pub fn is_call(&self) -> bool { - matches!(self, Self::Call(_)) - } - - /// Returns `true` if the transaction is `Create` or `Create2`. - #[inline] - pub fn is_create(&self) -> bool { - matches!(self, Self::Create) - } -} +/// Transaction destination +pub type TransactTo = TxKind; /// Create scheme. #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] diff --git a/crates/primitives/src/lib.rs b/crates/primitives/src/lib.rs index c57f900b90..35019aa041 100644 --- a/crates/primitives/src/lib.rs +++ b/crates/primitives/src/lib.rs @@ -21,7 +21,7 @@ pub mod state; pub mod utilities; pub use alloy_primitives::{ self, address, b256, bytes, fixed_bytes, hex, hex_literal, ruint, uint, Address, Bytes, - FixedBytes, Log, LogData, B256, I256, U256, + FixedBytes, Log, LogData, TxKind, B256, I256, U256, }; pub use bitvec; pub use bytecode::*; diff --git a/crates/revm/benches/bench.rs b/crates/revm/benches/bench.rs index b45beefd6f..a135a367d2 100644 --- a/crates/revm/benches/bench.rs +++ b/crates/revm/benches/bench.rs @@ -4,7 +4,7 @@ use criterion::{ use revm::{ db::BenchmarkDB, interpreter::{analysis::to_analysed, Contract, DummyHost, Interpreter}, - primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, TransactTo, U256}, + primitives::{address, bytes, hex, BerlinSpec, Bytecode, Bytes, TxKind, U256}, Evm, }; use revm_interpreter::{opcode::make_instruction_table, SharedMemory, EMPTY_SHARED_MEMORY}; @@ -14,7 +14,7 @@ fn analysis(c: &mut Criterion) { let evm = Evm::builder() .modify_tx_env(|tx| { tx.caller = address!("0000000000000000000000000000000000000002"); - tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); // evm.env.tx.data = bytes!("30627b7c"); tx.data = bytes!("8035F0CE"); }) @@ -50,7 +50,7 @@ fn snailtracer(c: &mut Criterion) { .with_db(BenchmarkDB::new_bytecode(bytecode(SNAILTRACER))) .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.data = bytes!("30627b7c"); }) .build(); @@ -70,7 +70,7 @@ fn transfer(c: &mut Criterion) { .with_db(BenchmarkDB::new_bytecode(Bytecode::new())) .modify_tx_env(|tx| { tx.caller = address!("0000000000000000000000000000000000000001"); - tx.transact_to = TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.value = U256::from(10); }) .build(); diff --git a/crates/revm/src/builder.rs b/crates/revm/src/builder.rs index a09f7c0bf5..c66b61f556 100644 --- a/crates/revm/src/builder.rs +++ b/crates/revm/src/builder.rs @@ -444,7 +444,7 @@ mod test { inspector::inspector_handle_register, inspectors::NoOpInspector, primitives::{ - address, AccountInfo, Address, Bytecode, Bytes, PrecompileResult, TransactTo, U256, + address, AccountInfo, Address, Bytecode, Bytes, PrecompileResult, TxKind, U256, }, Context, ContextPrecompile, ContextStatefulPrecompile, Evm, InMemoryDB, InnerEvmContext, }; @@ -474,7 +474,7 @@ mod test { .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) - .modify_tx_env(|tx| tx.transact_to = TransactTo::Call(to_addr)) + .modify_tx_env(|tx| tx.transact_to = TxKind::Call(to_addr)) // we need to use handle register box to capture the custom context in the handle // register .append_handler_register_box(Box::new(move |handler| { @@ -523,7 +523,7 @@ mod test { .modify_db(|db| { db.insert_account_info(to_addr, AccountInfo::new(U256::ZERO, 0, code_hash, code)) }) - .modify_tx_env(|tx| tx.transact_to = TransactTo::Call(to_addr)) + .modify_tx_env(|tx| tx.transact_to = TxKind::Call(to_addr)) .append_handler_register(|handler| { handler.instruction_table.insert(0xEF, custom_instruction) }) diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index d5b853d220..5cb64af8c5 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -8,7 +8,7 @@ use crate::{ }, primitives::{ specification::SpecId, BlockEnv, Bytes, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, - ExecutionResult, HandlerCfg, ResultAndState, TransactTo, TxEnv, + ExecutionResult, HandlerCfg, ResultAndState, TxEnv, TxKind, }, Context, ContextWithHandlerCfg, Frame, FrameOrResult, FrameResult, }; @@ -344,11 +344,11 @@ impl Evm<'_, EXT, DB> { let exec = self.handler.execution(); // call inner handling of call/create let first_frame_or_result = match ctx.evm.env.tx.transact_to { - TransactTo::Call(_) => exec.call( + TxKind::Call(_) => exec.call( ctx, CallInputs::new_boxed(&ctx.evm.env.tx, gas_limit).unwrap(), )?, - TransactTo::Create => { + TxKind::Create => { // if first byte of data is magic 0xEF00, then it is EOFCreate. if spec_id.is_enabled_in(SpecId::PRAGUE) && ctx diff --git a/crates/revm/src/handler/mainnet/pre_execution.rs b/crates/revm/src/handler/mainnet/pre_execution.rs index d3b9759dcf..3cc1d89a61 100644 --- a/crates/revm/src/handler/mainnet/pre_execution.rs +++ b/crates/revm/src/handler/mainnet/pre_execution.rs @@ -8,7 +8,7 @@ use crate::{ db::Database, Account, EVMError, Env, Spec, SpecId::{CANCUN, PRAGUE, SHANGHAI}, - TransactTo, BLOCKHASH_STORAGE_ADDRESS, U256, + TxKind, BLOCKHASH_STORAGE_ADDRESS, U256, }, Context, ContextPrecompiles, }; @@ -68,7 +68,7 @@ pub fn deduct_caller_inner(caller_account: &mut Account, env: &Env) caller_account.info.balance = caller_account.info.balance.saturating_sub(gas_cost); // bump the nonce for calls. Nonce for CREATE will be bumped in `handle_create`. - if matches!(env.tx.transact_to, TransactTo::Call(_)) { + if matches!(env.tx.transact_to, TxKind::Call(_)) { // Nonce is already checked caller_account.info.nonce = caller_account.info.nonce.saturating_add(1); } diff --git a/crates/revm/src/inspector/customprinter.rs b/crates/revm/src/inspector/customprinter.rs index ac7dd26537..ed42c4f7b4 100644 --- a/crates/revm/src/inspector/customprinter.rs +++ b/crates/revm/src/inspector/customprinter.rs @@ -140,7 +140,7 @@ mod test { }) .modify_tx_env(|tx| { tx.caller = address!("5fdcca53617f4d2b9134b29090c87d01058e27e0"); - tx.transact_to = crate::primitives::TransactTo::Call(callee); + tx.transact_to = crate::primitives::TxKind::Call(callee); tx.data = crate::primitives::Bytes::new(); tx.value = crate::primitives::U256::ZERO; }) diff --git a/crates/revm/src/inspector/gas.rs b/crates/revm/src/inspector/gas.rs index 7542c3d3bf..1100bd98e4 100644 --- a/crates/revm/src/inspector/gas.rs +++ b/crates/revm/src/inspector/gas.rs @@ -162,7 +162,7 @@ mod tests { db::BenchmarkDB, inspector::inspector_handle_register, interpreter::opcode, - primitives::{address, Bytecode, Bytes, TransactTo}, + primitives::{address, Bytecode, Bytes, TxKind}, Evm, }; @@ -189,8 +189,7 @@ mod tests { .modify_tx_env(|tx| { tx.clear(); tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = - TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.gas_limit = 21100; }) .append_handler_register(inspector_handle_register) diff --git a/crates/revm/src/inspector/handler_register.rs b/crates/revm/src/inspector/handler_register.rs index 0c50058885..7c48284a03 100644 --- a/crates/revm/src/inspector/handler_register.rs +++ b/crates/revm/src/inspector/handler_register.rs @@ -334,7 +334,7 @@ mod tests { db::BenchmarkDB, inspector::inspector_handle_register, interpreter::opcode, - primitives::{address, Bytecode, Bytes, TransactTo}, + primitives::{address, Bytecode, Bytes, TxKind}, Evm, }; @@ -360,8 +360,7 @@ mod tests { .modify_tx_env(|tx| { tx.clear(); tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = - TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.gas_limit = 21100; }) .append_handler_register(inspector_handle_register) diff --git a/crates/revm/src/optimism/fast_lz.rs b/crates/revm/src/optimism/fast_lz.rs index 51ea82d493..3906bcb362 100644 --- a/crates/revm/src/optimism/fast_lz.rs +++ b/crates/revm/src/optimism/fast_lz.rs @@ -112,7 +112,7 @@ mod tests { use crate::db::BenchmarkDB; use crate::{ primitives::address, primitives::bytes, primitives::Bytecode, primitives::Bytes, - primitives::TransactTo, primitives::U256, Evm, + primitives::TxKind, primitives::U256, Evm, }; use rstest::rstest; @@ -166,8 +166,7 @@ mod tests { .with_db(BenchmarkDB::new_bytecode(contract_bytecode.clone())) .modify_tx_env(|tx| { tx.caller = address!("1000000000000000000000000000000000000000"); - tx.transact_to = - TransactTo::Call(address!("0000000000000000000000000000000000000000")); + tx.transact_to = TxKind::Call(address!("0000000000000000000000000000000000000000")); tx.data = FastLz::fastLzCall::new((input,)).abi_encode().into(); }) .build(); diff --git a/documentation/src/crates/primitives/environment.md b/documentation/src/crates/primitives/environment.md index 8e33181527..8d56024b55 100644 --- a/documentation/src/crates/primitives/environment.md +++ b/documentation/src/crates/primitives/environment.md @@ -1,5 +1,5 @@ # Environment -A significant module that manages the execution environment of the EVM. The module contains objects and methods associated with processing transactions and blocks within such a blockchain environment. It defines several structures: `Env`, `BlockEnv`, `TxEnv`, `CfgEnv`, `TransactTo`, and `CreateScheme`. These structures contain various fields representing the block data, transaction data, environmental configurations, transaction recipient details, and the method of contract creation respectively. +A significant module that manages the execution environment of the EVM. The module contains objects and methods associated with processing transactions and blocks within such a blockchain environment. It defines several structures: `Env`, `BlockEnv`, `TxEnv`, `CfgEnv`, and `CreateScheme`. These structures contain various fields representing the block data, transaction data, environmental configurations, transaction recipient details, and the method of contract creation respectively. The `Env` structure, which encapsulates the environment of the EVM, contains methods for calculating effective gas prices and for validating block and transaction data. It also checks transactions against the current state of the associated account, which is necessary to validate the transaction's nonce and the account balance. Various Ethereum Improvement Proposals (EIPs) are also considered in these validations, such as [EIP-1559](https://eips.ethereum.org/EIPS/eip-1559) for the base fee, [EIP-3607](https://eips.ethereum.org/EIPS/eip-3607) for rejecting transactions from senders with deployed code, and [EIP-3298](https://eips.ethereum.org/EIPS/eip-3298) for disabling gas refunds. The code is structured to include optional features and to allow for changes in the EVM specifications. diff --git a/examples/fork_ref_transact.rs b/examples/fork_ref_transact.rs index 6953fda2a0..33258b46f0 100644 --- a/examples/fork_ref_transact.rs +++ b/examples/fork_ref_transact.rs @@ -3,7 +3,7 @@ use alloy_sol_types::SolCall; use ethers_providers::{Http, Provider}; use revm::{ db::{CacheDB, EmptyDB, EthersDB}, - primitives::{address, ExecutionResult, Output, TransactTo, U256}, + primitives::{address, ExecutionResult, Output, TxKind, U256}, Database, Evm, }; use std::sync::Arc; @@ -70,7 +70,7 @@ async fn main() -> anyhow::Result<()> { // change that to whatever caller you want to be tx.caller = address!("0000000000000000000000000000000000000000"); // account you want to transact with - tx.transact_to = TransactTo::Call(pool_address); + tx.transact_to = TxKind::Call(pool_address); // calldata formed via abigen tx.data = encoded.into(); // transaction value in wei diff --git a/examples/generate_block_traces.rs b/examples/generate_block_traces.rs index cfd8f030c1..59d9d03680 100644 --- a/examples/generate_block_traces.rs +++ b/examples/generate_block_traces.rs @@ -6,7 +6,7 @@ use ethers_providers::{Http, Provider}; use indicatif::ProgressBar; use revm::db::{CacheDB, EthersDB, StateBuilder}; use revm::inspectors::TracerEip3155; -use revm::primitives::{Address, TransactTo, U256}; +use revm::primitives::{Address, TxKind, U256}; use revm::{inspector_handle_register, Evm}; use std::fs::OpenOptions; use std::io::BufWriter; @@ -143,10 +143,8 @@ async fn main() -> anyhow::Result<()> { } etx.transact_to = match tx.to { - Some(to_address) => { - TransactTo::Call(Address::from(to_address.as_fixed_bytes())) - } - None => TransactTo::create(), + Some(to_address) => TxKind::Call(Address::from(to_address.as_fixed_bytes())), + None => TxKind::Create, }; }) .build(); diff --git a/examples/uniswap_v2_usdc_swap.rs b/examples/uniswap_v2_usdc_swap.rs index a57a982642..3f9905bf42 100644 --- a/examples/uniswap_v2_usdc_swap.rs +++ b/examples/uniswap_v2_usdc_swap.rs @@ -7,7 +7,7 @@ use reqwest::Client; use revm::{ db::{AlloyDB, CacheDB}, primitives::{ - address, keccak256, AccountInfo, Address, Bytes, ExecutionResult, Output, TransactTo, U256, + address, keccak256, AccountInfo, Address, Bytes, ExecutionResult, Output, TxKind, U256, }, Evm, }; @@ -95,7 +95,7 @@ fn balance_of(token: Address, address: Address, cache_db: &mut AlloyCacheDB) -> .modify_tx_env(|tx| { // 0x1 because calling USDC proxy from zero address fails tx.caller = address!("0000000000000000000000000000000000000001"); - tx.transact_to = TransactTo::Call(token); + tx.transact_to = TxKind::Call(token); tx.data = encoded.into(); tx.value = U256::from(0); }) @@ -139,7 +139,7 @@ async fn get_amount_out( .with_db(cache_db) .modify_tx_env(|tx| { tx.caller = address!("0000000000000000000000000000000000000000"); - tx.transact_to = TransactTo::Call(uniswap_v2_router); + tx.transact_to = TxKind::Call(uniswap_v2_router); tx.data = encoded.into(); tx.value = U256::from(0); }) @@ -172,7 +172,7 @@ fn get_reserves(pair_address: Address, cache_db: &mut AlloyCacheDB) -> Result<(U .with_db(cache_db) .modify_tx_env(|tx| { tx.caller = address!("0000000000000000000000000000000000000000"); - tx.transact_to = TransactTo::Call(pair_address); + tx.transact_to = TxKind::Call(pair_address); tx.data = encoded.into(); tx.value = U256::from(0); }) @@ -221,7 +221,7 @@ fn swap( .with_db(cache_db) .modify_tx_env(|tx| { tx.caller = from; - tx.transact_to = TransactTo::Call(pool_address); + tx.transact_to = TxKind::Call(pool_address); tx.data = encoded.into(); tx.value = U256::from(0); }) @@ -254,7 +254,7 @@ fn transfer( .with_db(cache_db) .modify_tx_env(|tx| { tx.caller = from; - tx.transact_to = TransactTo::Call(token); + tx.transact_to = TxKind::Call(token); tx.data = encoded.into(); tx.value = U256::from(0); }) From 6e7715aa9da62a15859536a10aebc05a4f3d8968 Mon Sep 17 00:00:00 2001 From: Brian Bland Date: Thu, 20 Jun 2024 05:45:46 -0700 Subject: [PATCH 85/88] chore: Add CI build target for no-std + optimism, use matrix builds (#1551) --- .github/workflows/ci.yml | 38 ++++++++++------------------- crates/revm/src/optimism/l1block.rs | 2 +- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbea7ba5c4..9aaad96a24 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -32,45 +32,33 @@ jobs: - run: cargo test --workspace ${{ matrix.flags }} test-no-std: - name: test no_std + name: test no_std ${{ matrix.features }} runs-on: ubuntu-latest timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + features: ["", "optimism"] steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable with: targets: riscv32imac-unknown-none-elf - - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features - - check-no-default-features: - name: check no-default-features - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v4 - - run: | - cd crates/revm - cargo check --no-default-features + - run: cargo check --target riscv32imac-unknown-none-elf --no-default-features --features=${{ matrix.features }} - check-serde: - name: check serde - runs-on: ubuntu-latest - timeout-minutes: 30 - steps: - - uses: actions/checkout@v4 - - run: | - cd crates/revm - cargo check --no-default-features --features serde - - check-std: - name: check std + check: + name: check ${{ matrix.features }} runs-on: ubuntu-latest timeout-minutes: 30 + strategy: + fail-fast: false + matrix: + features: ["", "serde", "std"] steps: - uses: actions/checkout@v4 - run: | cd crates/revm - cargo check --no-default-features --features std + cargo check --no-default-features --features=${{ matrix.features }} clippy: name: clippy diff --git a/crates/revm/src/optimism/l1block.rs b/crates/revm/src/optimism/l1block.rs index 631b9a5d25..e348718db2 100644 --- a/crates/revm/src/optimism/l1block.rs +++ b/crates/revm/src/optimism/l1block.rs @@ -223,7 +223,7 @@ impl L1BlockInfo { estimated_size .saturating_mul(l1_fee_scaled) - .wrapping_div(U256::from(1000000000000u64)) + .wrapping_div(U256::from(1_000_000_000_000u64)) } // l1BaseFee*16*l1BaseFeeScalar + l1BlobBaseFee*l1BlobBaseFeeScalar From 09451cb0ed424336e077049f2b0458a6b4533145 Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 20 Jun 2024 15:12:34 +0200 Subject: [PATCH 86/88] fix(eof): fixture 2 tests (#1550) * eof fixes * fix(eof): create initcode starting with 0xff00 * Include PragueEOF * spec missing * add helper function to get address * clippy * include box * move EOF to PragueEOF --- bins/revm-test/src/bin/burntpix/main.rs | 2 +- bins/revme/src/cmd/statetest/models/spec.rs | 2 + crates/interpreter/src/instruction_result.rs | 58 +++++++--- .../interpreter/src/instructions/contract.rs | 31 ++++-- .../interpreter/src/instructions/control.rs | 2 +- crates/interpreter/src/interpreter.rs | 8 +- crates/interpreter/src/interpreter_action.rs | 4 +- .../interpreter_action/eof_create_inputs.rs | 105 +++++++++++++----- .../interpreter_action/eof_create_outcome.rs | 71 ------------ crates/interpreter/src/lib.rs | 2 +- crates/precompile/src/lib.rs | 2 +- crates/primitives/src/bytecode/eof/header.rs | 32 +++--- crates/primitives/src/result.rs | 9 +- crates/primitives/src/specification.rs | 14 +++ crates/revm/src/context/inner_evm_context.rs | 66 ++++++++--- crates/revm/src/evm.rs | 51 ++------- crates/revm/src/frame.rs | 15 +-- .../src/handler/handle_types/execution.rs | 12 +- crates/revm/src/handler/mainnet/execution.rs | 12 +- .../src/handler/mainnet/post_execution.rs | 4 +- crates/revm/src/inspector.rs | 25 ++--- 21 files changed, 284 insertions(+), 243 deletions(-) delete mode 100644 crates/interpreter/src/interpreter_action/eof_create_outcome.rs diff --git a/bins/revm-test/src/bin/burntpix/main.rs b/bins/revm-test/src/bin/burntpix/main.rs index ea1ac56f70..ef0b78ea2a 100644 --- a/bins/revm-test/src/bin/burntpix/main.rs +++ b/bins/revm-test/src/bin/burntpix/main.rs @@ -100,7 +100,7 @@ fn try_from_hex_to_u32(hex: &str) -> eyre::Result { } fn insert_account_info(cache_db: &mut CacheDB, addr: Address, code: Bytes) { - let code_hash = hex::encode(keccak256(code.clone())); + let code_hash = hex::encode(keccak256(&code)); let account_info = AccountInfo::new( U256::from(0), 0, diff --git a/bins/revme/src/cmd/statetest/models/spec.rs b/bins/revme/src/cmd/statetest/models/spec.rs index dac05f04a9..50903323a2 100644 --- a/bins/revme/src/cmd/statetest/models/spec.rs +++ b/bins/revme/src/cmd/statetest/models/spec.rs @@ -24,6 +24,7 @@ pub enum SpecName { Shanghai, Cancun, Prague, + PragueEOF, #[serde(other)] Unknown, } @@ -46,6 +47,7 @@ impl SpecName { Self::Shanghai => SpecId::SHANGHAI, Self::Cancun => SpecId::CANCUN, Self::Prague => SpecId::PRAGUE, + Self::PragueEOF => SpecId::PRAGUE_EOF, Self::ByzantiumToConstantinopleAt5 | Self::Constantinople => { panic!("Overridden with PETERSBURG") } diff --git a/crates/interpreter/src/instruction_result.rs b/crates/interpreter/src/instruction_result.rs index 121e12ead7..aed0da331e 100644 --- a/crates/interpreter/src/instruction_result.rs +++ b/crates/interpreter/src/instruction_result.rs @@ -16,6 +16,10 @@ pub enum InstructionResult { Revert = 0x10, // revert opcode CallTooDeep, OutOfFunds, + /// Revert if CREATE/CREATE2 starts with 0xEF00 + CreateInitCodeStartingEF00, + /// Invalid EOF initcode, + InvalidEOFInitCode, // Actions CallOrCreate = 0x20, @@ -29,7 +33,7 @@ pub enum InstructionResult { OpcodeNotFound, CallNotAllowedInsideStatic, StateChangeDuringStaticCall, - InvalidFEOpcode, + InvalidEFOpcode, InvalidJump, NotActivated, StackUnderflow, @@ -53,6 +57,10 @@ pub enum InstructionResult { EOFOpcodeDisabledInLegacy, /// EOF function stack overflow EOFFunctionStackOverflow, + /// Aux data overflow, new aux data is larger tha u16 max size. + EofAuxDataOverflow, + /// Aud data is smaller then already present data size. + EofAuxDataTooSmall, } impl From for InstructionResult { @@ -77,7 +85,7 @@ impl From for InstructionResult { OutOfGasError::Precompile => Self::PrecompileOOG, }, HaltReason::OpcodeNotFound => Self::OpcodeNotFound, - HaltReason::InvalidFEOpcode => Self::InvalidFEOpcode, + HaltReason::InvalidEFOpcode => Self::InvalidEFOpcode, HaltReason::InvalidJump => Self::InvalidJump, HaltReason::NotActivated => Self::NotActivated, HaltReason::StackOverflow => Self::StackOverflow, @@ -94,6 +102,9 @@ impl From for InstructionResult { HaltReason::CallNotAllowedInsideStatic => Self::CallNotAllowedInsideStatic, HaltReason::OutOfFunds => Self::OutOfFunds, HaltReason::CallTooDeep => Self::CallTooDeep, + HaltReason::EofAuxDataOverflow => Self::EofAuxDataOverflow, + HaltReason::EofAuxDataTooSmall => Self::EofAuxDataTooSmall, + HaltReason::EOFFunctionStackOverflow => Self::EOFFunctionStackOverflow, #[cfg(feature = "optimism")] HaltReason::FailedDeposit => Self::FatalExternalError, } @@ -114,7 +125,11 @@ macro_rules! return_ok { #[macro_export] macro_rules! return_revert { () => { - InstructionResult::Revert | InstructionResult::CallTooDeep | InstructionResult::OutOfFunds + InstructionResult::Revert + | InstructionResult::CallTooDeep + | InstructionResult::OutOfFunds + | InstructionResult::InvalidEOFInitCode + | InstructionResult::CreateInitCodeStartingEF00 }; } @@ -129,7 +144,7 @@ macro_rules! return_error { | InstructionResult::OpcodeNotFound | InstructionResult::CallNotAllowedInsideStatic | InstructionResult::StateChangeDuringStaticCall - | InstructionResult::InvalidFEOpcode + | InstructionResult::InvalidEFOpcode | InstructionResult::InvalidJump | InstructionResult::NotActivated | InstructionResult::StackUnderflow @@ -146,6 +161,8 @@ macro_rules! return_error { | InstructionResult::ReturnContractInNotInitEOF | InstructionResult::EOFOpcodeDisabledInLegacy | InstructionResult::EOFFunctionStackOverflow + | InstructionResult::EofAuxDataTooSmall + | InstructionResult::EofAuxDataOverflow }; } @@ -169,16 +186,24 @@ impl InstructionResult { } } +/// Internal result that are not ex +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum InternalResult { + /// Internal instruction that signals Interpreter should continue running. + InternalContinue, + /// Internal instruction that signals call or create. + InternalCallOrCreate, + /// Internal CREATE/CREATE starts with 0xEF00 + CreateInitCodeStartingEF00, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub enum SuccessOrHalt { Success(SuccessReason), Revert, Halt(HaltReason), FatalExternalError, - /// Internal instruction that signals Interpreter should continue running. - InternalContinue, - /// Internal instruction that signals call or create. - InternalCallOrCreate, + Internal(InternalResult), } impl SuccessOrHalt { @@ -222,12 +247,13 @@ impl SuccessOrHalt { impl From for SuccessOrHalt { fn from(result: InstructionResult) -> Self { match result { - InstructionResult::Continue => Self::InternalContinue, // used only in interpreter loop + InstructionResult::Continue => Self::Internal(InternalResult::InternalContinue), // used only in interpreter loop InstructionResult::Stop => Self::Success(SuccessReason::Stop), InstructionResult::Return => Self::Success(SuccessReason::Return), InstructionResult::SelfDestruct => Self::Success(SuccessReason::SelfDestruct), InstructionResult::Revert => Self::Revert, - InstructionResult::CallOrCreate => Self::InternalCallOrCreate, // used only in interpreter loop + InstructionResult::CreateInitCodeStartingEF00 => Self::Revert, + InstructionResult::CallOrCreate => Self::Internal(InternalResult::InternalCallOrCreate), // used only in interpreter loop InstructionResult::CallTooDeep => Self::Halt(HaltReason::CallTooDeep), // not gonna happen for first call InstructionResult::OutOfFunds => Self::Halt(HaltReason::OutOfFunds), // Check for first call is done separately. InstructionResult::OutOfGas => Self::Halt(HaltReason::OutOfGas(OutOfGasError::Basic)), @@ -250,7 +276,7 @@ impl From for SuccessOrHalt { InstructionResult::StateChangeDuringStaticCall => { Self::Halt(HaltReason::StateChangeDuringStaticCall) } - InstructionResult::InvalidFEOpcode => Self::Halt(HaltReason::InvalidFEOpcode), + InstructionResult::InvalidEFOpcode => Self::Halt(HaltReason::InvalidEFOpcode), InstructionResult::InvalidJump => Self::Halt(HaltReason::InvalidJump), InstructionResult::NotActivated => Self::Halt(HaltReason::NotActivated), InstructionResult::StackUnderflow => Self::Halt(HaltReason::StackUnderflow), @@ -267,10 +293,16 @@ impl From for SuccessOrHalt { InstructionResult::CreateInitCodeSizeLimit => { Self::Halt(HaltReason::CreateInitCodeSizeLimit) } + // TODO (EOF) add proper Revert subtype. + InstructionResult::InvalidEOFInitCode => Self::Revert, InstructionResult::FatalExternalError => Self::FatalExternalError, InstructionResult::EOFOpcodeDisabledInLegacy => Self::Halt(HaltReason::OpcodeNotFound), - InstructionResult::EOFFunctionStackOverflow => Self::FatalExternalError, + InstructionResult::EOFFunctionStackOverflow => { + Self::Halt(HaltReason::EOFFunctionStackOverflow) + } InstructionResult::ReturnContract => Self::Success(SuccessReason::EofReturnContract), + InstructionResult::EofAuxDataOverflow => Self::Halt(HaltReason::EofAuxDataOverflow), + InstructionResult::EofAuxDataTooSmall => Self::Halt(HaltReason::EofAuxDataTooSmall), } } } @@ -325,7 +357,7 @@ mod tests { InstructionResult::OpcodeNotFound, InstructionResult::CallNotAllowedInsideStatic, InstructionResult::StateChangeDuringStaticCall, - InstructionResult::InvalidFEOpcode, + InstructionResult::InvalidEFOpcode, InstructionResult::InvalidJump, InstructionResult::NotActivated, InstructionResult::StackUnderflow, diff --git a/crates/interpreter/src/instructions/contract.rs b/crates/interpreter/src/instructions/contract.rs index aac3d38f76..ea58ad4062 100644 --- a/crates/interpreter/src/instructions/contract.rs +++ b/crates/interpreter/src/instructions/contract.rs @@ -1,12 +1,13 @@ mod call_helpers; pub use call_helpers::{calc_call_gas, get_memory_input_and_out_ranges, resize_memory}; -use revm_primitives::{keccak256, BerlinSpec}; use crate::{ gas::{self, cost_per_word, EOF_CREATE_GAS, KECCAK256WORD}, interpreter::Interpreter, - primitives::{Address, Bytes, Eof, Spec, SpecId::*, U256}, + primitives::{ + eof::EofHeader, keccak256, Address, BerlinSpec, Bytes, Eof, Spec, SpecId::*, U256, + }, CallInputs, CallScheme, CallValue, CreateInputs, CreateScheme, EOFCreateInputs, Host, InstructionResult, InterpreterAction, InterpreterResult, LoadAccountResult, MAX_INITCODE_SIZE, }; @@ -67,7 +68,7 @@ pub fn eofcreate(interpreter: &mut Interpreter, _host: &mut H) // Send container for execution container is preverified. interpreter.instruction_result = InstructionResult::CallOrCreate; interpreter.next_action = InterpreterAction::EOFCreate { - inputs: Box::new(EOFCreateInputs::new( + inputs: Box::new(EOFCreateInputs::new_opcode( interpreter.contract.target_address, created_address, value, @@ -92,10 +93,11 @@ pub fn return_contract(interpreter: &mut Interpreter, _host: & .body .container_section .get(deploy_container_index as usize) - .expect("EOF is checked"); + .expect("EOF is checked") + .clone(); // convert to EOF so we can check data section size. - let new_eof = Eof::decode(container.clone()).expect("Container is verified"); + let (eof_header, _) = EofHeader::decode(&container).expect("valid EOF header"); let aux_slice = if aux_data_size != 0 { let aux_data_offset = as_usize_or_fail!(interpreter, aux_data_offset); @@ -108,20 +110,27 @@ pub fn return_contract(interpreter: &mut Interpreter, _host: & &[] }; - let new_data_size = new_eof.body.data_section.len() + aux_slice.len(); + let static_aux_size = eof_header.eof_size() - container.len(); + + // data_size - static_aux_size give us current data `container` size. + // and with aux_slice len we can calculate new data size. + let new_data_size = eof_header.data_size as usize - static_aux_size + aux_slice.len(); if new_data_size > 0xFFFF { // aux data is too big - interpreter.instruction_result = InstructionResult::FatalExternalError; + interpreter.instruction_result = InstructionResult::EofAuxDataOverflow; return; } - if new_data_size < new_eof.header.data_size as usize { + if new_data_size < eof_header.data_size as usize { // aux data is too small - interpreter.instruction_result = InstructionResult::FatalExternalError; + interpreter.instruction_result = InstructionResult::EofAuxDataTooSmall; return; } + let new_data_size = (new_data_size as u16).to_be_bytes(); - // append data bytes - let output = [new_eof.raw(), aux_slice].concat().into(); + let mut output = [&container, aux_slice].concat(); + // set new data size in eof bytes as we know exact index. + output[eof_header.data_size_raw_i()..][..2].clone_from_slice(&new_data_size); + let output: Bytes = output.into(); let result = InstructionResult::ReturnContract; interpreter.instruction_result = result; diff --git a/crates/interpreter/src/instructions/control.rs b/crates/interpreter/src/instructions/control.rs index 4aacffd9e4..3bf4e43514 100644 --- a/crates/interpreter/src/instructions/control.rs +++ b/crates/interpreter/src/instructions/control.rs @@ -194,7 +194,7 @@ pub fn stop(interpreter: &mut Interpreter, _host: &mut H) { /// Invalid opcode. This opcode halts the execution. pub fn invalid(interpreter: &mut Interpreter, _host: &mut H) { - interpreter.instruction_result = InstructionResult::InvalidFEOpcode; + interpreter.instruction_result = InstructionResult::InvalidEFOpcode; } /// Unknown opcode. This opcode halts the execution. diff --git a/crates/interpreter/src/interpreter.rs b/crates/interpreter/src/interpreter.rs index d74f7d08bc..4fa5816505 100644 --- a/crates/interpreter/src/interpreter.rs +++ b/crates/interpreter/src/interpreter.rs @@ -9,7 +9,6 @@ pub use contract::Contract; pub use shared_memory::{num_words, SharedMemory, EMPTY_SHARED_MEMORY}; pub use stack::{Stack, STACK_LIMIT}; -use crate::EOFCreateOutcome; use crate::{ gas, primitives::Bytes, push, push_b256, return_ok, return_revert, CallOutcome, CreateOutcome, FunctionStack, Gas, Host, InstructionResult, InterpreterAction, @@ -192,7 +191,7 @@ impl Interpreter { } } - pub fn insert_eofcreate_outcome(&mut self, create_outcome: EOFCreateOutcome) { + pub fn insert_eofcreate_outcome(&mut self, create_outcome: CreateOutcome) { self.instruction_result = InstructionResult::Continue; let instruction_result = create_outcome.instruction_result(); @@ -206,7 +205,10 @@ impl Interpreter { match instruction_result { InstructionResult::ReturnContract => { - push_b256!(self, create_outcome.address.into_word()); + push_b256!( + self, + create_outcome.address.expect("EOF Address").into_word() + ); self.gas.erase_cost(create_outcome.gas().remaining()); self.gas.record_refund(create_outcome.gas().refunded()); } diff --git a/crates/interpreter/src/interpreter_action.rs b/crates/interpreter/src/interpreter_action.rs index 1459b0226e..1d2c27d622 100644 --- a/crates/interpreter/src/interpreter_action.rs +++ b/crates/interpreter/src/interpreter_action.rs @@ -3,14 +3,12 @@ mod call_outcome; mod create_inputs; mod create_outcome; mod eof_create_inputs; -mod eof_create_outcome; pub use call_inputs::{CallInputs, CallScheme, CallValue}; pub use call_outcome::CallOutcome; pub use create_inputs::{CreateInputs, CreateScheme}; pub use create_outcome::CreateOutcome; -pub use eof_create_inputs::EOFCreateInputs; -pub use eof_create_outcome::EOFCreateOutcome; +pub use eof_create_inputs::{EOFCreateInputs, EOFCreateKind}; use crate::InterpreterResult; use std::boxed::Box; diff --git a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs index 4dc8190be5..30bc525a4e 100644 --- a/crates/interpreter/src/interpreter_action/eof_create_inputs.rs +++ b/crates/interpreter/src/interpreter_action/eof_create_inputs.rs @@ -1,5 +1,48 @@ -use crate::primitives::{eof::EofDecodeError, Address, Bytes, Eof, TxEnv, U256}; -use std::boxed::Box; +use crate::primitives::{Address, Bytes, Eof, TxEnv, U256}; + +/// EOF create can be called from two places: +/// * EOFCREATE opcode +/// * Creation transaction. +/// +/// Creation transaction uses initdata and packs EOF and initdata inside it. +/// This eof bytecode needs to be validated. +/// +/// Opcode creation uses already validated EOF bytecode, and input from Interpreter memory. +/// Address is already known and is passed as an argument. +#[derive(Debug, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub enum EOFCreateKind { + Tx { + initdata: Bytes, + }, + Opcode { + initcode: Eof, + input: Bytes, + created_address: Address, + }, +} + +impl EOFCreateKind { + /// Returns created address + pub fn created_address(&self) -> Option<&Address> { + match self { + EOFCreateKind::Opcode { + created_address, .. + } => Some(created_address), + EOFCreateKind::Tx { .. } => None, + } + } +} + +impl Default for EOFCreateKind { + fn default() -> Self { + EOFCreateKind::Opcode { + initcode: Eof::default(), + input: Bytes::default(), + created_address: Address::default(), + } + } +} /// Inputs for EOF create call. #[derive(Debug, Default, Clone, PartialEq, Eq)] @@ -7,42 +50,42 @@ use std::boxed::Box; pub struct EOFCreateInputs { /// Caller of Eof Craate pub caller: Address, - /// New contract address. - pub created_address: Address, /// Values of ether transfered pub value: U256, - /// Init eof code that is going to be executed. - pub eof_init_code: Eof, - /// Call data the input of the EOFCREATE call. - pub input: Bytes, /// Gas limit for the create call. pub gas_limit: u64, + /// EOF Create kind + pub kind: EOFCreateKind, } impl EOFCreateInputs { - /// Returns boxed EOFCreateInput or error. - /// Internally calls [`Self::new_tx`]. - pub fn new_tx_boxed(tx: &TxEnv, nonce: u64) -> Result, EofDecodeError> { - Ok(Box::new(Self::new_tx(tx, nonce)?)) - } - /// Create new EOF crate input from transaction that has concatenated eof init code and calldata. /// /// Legacy transaction still have optional nonce so we need to obtain it. - pub fn new_tx(tx: &TxEnv, nonce: u64) -> Result { - let (eof_init_code, input) = Eof::decode_dangling(tx.data.clone())?; - Ok(EOFCreateInputs { - caller: tx.caller, - created_address: tx.caller.create(nonce), - value: tx.value, - eof_init_code, - gas_limit: tx.gas_limit, - input, - }) + pub fn new(caller: Address, value: U256, gas_limit: u64, kind: EOFCreateKind) -> Self { + //let (eof_init_code, input) = Eof::decode_dangling(tx.data.clone())?; + EOFCreateInputs { + caller, + value, + gas_limit, + kind, + } + } + + /// Creates new EOFCreateInputs from transaction. + pub fn new_tx(tx: &TxEnv, gas_limit: u64) -> Self { + EOFCreateInputs::new( + tx.caller, + tx.value, + gas_limit, + EOFCreateKind::Tx { + initdata: tx.data.clone(), + }, + ) } /// Returns a new instance of EOFCreateInput. - pub fn new( + pub fn new_opcode( caller: Address, created_address: Address, value: U256, @@ -50,13 +93,15 @@ impl EOFCreateInputs { gas_limit: u64, input: Bytes, ) -> EOFCreateInputs { - EOFCreateInputs { + EOFCreateInputs::new( caller, - created_address, value, - eof_init_code, gas_limit, - input, - } + EOFCreateKind::Opcode { + initcode: eof_init_code, + input, + created_address, + }, + ) } } diff --git a/crates/interpreter/src/interpreter_action/eof_create_outcome.rs b/crates/interpreter/src/interpreter_action/eof_create_outcome.rs deleted file mode 100644 index beeda24e50..0000000000 --- a/crates/interpreter/src/interpreter_action/eof_create_outcome.rs +++ /dev/null @@ -1,71 +0,0 @@ -use crate::{Gas, InstructionResult, InterpreterResult}; -use revm_primitives::{Address, Bytes}; - -/// Represents the outcome of a create operation in an interpreter. -/// -/// This struct holds the result of the operation along with an optional address. -/// It provides methods to determine the next action based on the result of the operation. -#[derive(Debug, Clone, PartialEq, Eq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct EOFCreateOutcome { - /// The result of the interpreter operation. - pub result: InterpreterResult, - /// An optional address associated with the create operation. - pub address: Address, -} - -impl EOFCreateOutcome { - /// Constructs a new [`EOFCreateOutcome`]. - /// - /// # Arguments - /// - /// * `result` - An `InterpreterResult` representing the result of the interpreter operation. - /// * `address` - An optional `Address` associated with the create operation. - /// * `return_memory_range` - The memory range that Revert bytes are going to be written. - /// - /// # Returns - /// - /// A new [`EOFCreateOutcome`] instance. - pub fn new(result: InterpreterResult, address: Address) -> Self { - Self { result, address } - } - - /// Retrieves a reference to the [`InstructionResult`] from the [`InterpreterResult`]. - /// - /// This method provides access to the `InstructionResult` which represents the - /// outcome of the instruction execution. It encapsulates the result information - /// such as whether the instruction was executed successfully, resulted in a revert, - /// or encountered a fatal error. - /// - /// # Returns - /// - /// A reference to the `InstructionResult`. - pub fn instruction_result(&self) -> &InstructionResult { - &self.result.result - } - - /// Retrieves a reference to the output bytes from the `InterpreterResult`. - /// - /// This method returns the output of the interpreted operation. The output is - /// typically used when the operation successfully completes and returns data. - /// - /// # Returns - /// - /// A reference to the output `Bytes`. - pub fn output(&self) -> &Bytes { - &self.result.output - } - - /// Retrieves a reference to the `Gas` details from the `InterpreterResult`. - /// - /// This method provides access to the gas details of the operation, which includes - /// information about gas used, remaining, and refunded. It is essential for - /// understanding the gas consumption of the operation. - /// - /// # Returns - /// - /// A reference to the `Gas` details. - pub fn gas(&self) -> &Gas { - &self.result.gas - } -} diff --git a/crates/interpreter/src/lib.rs b/crates/interpreter/src/lib.rs index 64167dd410..da95f0895e 100644 --- a/crates/interpreter/src/lib.rs +++ b/crates/interpreter/src/lib.rs @@ -37,7 +37,7 @@ pub use interpreter::{ }; pub use interpreter_action::{ CallInputs, CallOutcome, CallScheme, CallValue, CreateInputs, CreateOutcome, CreateScheme, - EOFCreateInputs, EOFCreateOutcome, InterpreterAction, + EOFCreateInputs, EOFCreateKind, InterpreterAction, }; pub use opcode::{Instruction, OpCode, OPCODE_INFO_JUMPTABLE}; pub use primitives::{MAX_CODE_SIZE, MAX_INITCODE_SIZE}; diff --git a/crates/precompile/src/lib.rs b/crates/precompile/src/lib.rs index e930f2cdfc..1425f3421a 100644 --- a/crates/precompile/src/lib.rs +++ b/crates/precompile/src/lib.rs @@ -281,7 +281,7 @@ impl PrecompileSpecId { ISTANBUL | MUIR_GLACIER => Self::ISTANBUL, BERLIN | LONDON | ARROW_GLACIER | GRAY_GLACIER | MERGE | SHANGHAI => Self::BERLIN, CANCUN => Self::CANCUN, - PRAGUE => Self::PRAGUE, + PRAGUE | PRAGUE_EOF => Self::PRAGUE, LATEST => Self::LATEST, #[cfg(feature = "optimism")] BEDROCK | REGOLITH | CANYON => Self::BERLIN, diff --git a/crates/primitives/src/bytecode/eof/header.rs b/crates/primitives/src/bytecode/eof/header.rs index 1074f066a4..c348296872 100644 --- a/crates/primitives/src/bytecode/eof/header.rs +++ b/crates/primitives/src/bytecode/eof/header.rs @@ -62,25 +62,23 @@ fn consume_header_section_size(input: &[u8]) -> Result<(&[u8], Vec, usize), impl EofHeader { /// Length of the header in bytes. /// - /// Length is calculated as: - /// magic 2 byte + - /// version 1 byte + - /// types section 3 bytes + - /// code section 3 bytes + - /// num_code_sections * 2 + - /// if num_container_sections != 0 { container section 3 bytes} + - /// num_container_sections * 2 + - /// data section 3 bytes + - /// terminator 1 byte - /// /// It is minimum 15 bytes (there is at least one code section). pub fn size(&self) -> usize { - let optional_container_sizes = if self.container_sizes.is_empty() { - 0 - } else { - 3 + self.container_sizes.len() * 2 - }; - 13 + self.code_sizes.len() * 2 + optional_container_sizes + 2 + // magic + 1 + // version + 3 + // types section + 3 + // code section + 2 * self.code_sizes.len() + // num_code_sections + if self.container_sizes.is_empty() { 0 } else { 3 + 2 * self.container_sizes.len() } + // container + 3 + // data section. + 1 // terminator + } + + /// Return index where data size starts. + /// Data size is two bytes long. + pub fn data_size_raw_i(&self) -> usize { + // termination(1byte) + code size(2) bytes. + self.size() - 3 } /// Returns number of types. diff --git a/crates/primitives/src/result.rs b/crates/primitives/src/result.rs index 28f35ce82c..2a61883a89 100644 --- a/crates/primitives/src/result.rs +++ b/crates/primitives/src/result.rs @@ -400,7 +400,7 @@ pub enum SuccessReason { pub enum HaltReason { OutOfGas(OutOfGasError), OpcodeNotFound, - InvalidFEOpcode, + InvalidEFOpcode, InvalidJump, NotActivated, StackUnderflow, @@ -423,6 +423,13 @@ pub enum HaltReason { OutOfFunds, CallTooDeep, + /// Aux data overflow, new aux data is larger tha u16 max size. + EofAuxDataOverflow, + /// Aud data is smaller then already present data size. + EofAuxDataTooSmall, + /// EOF Subroutine stack overflow + EOFFunctionStackOverflow, + /* Optimism errors */ #[cfg(feature = "optimism")] FailedDeposit, diff --git a/crates/primitives/src/specification.rs b/crates/primitives/src/specification.rs index d7c1d3e6cf..51d18010be 100644 --- a/crates/primitives/src/specification.rs +++ b/crates/primitives/src/specification.rs @@ -29,6 +29,7 @@ pub enum SpecId { SHANGHAI = 16, // Shanghai 17034870 (Timestamp: 1681338455) CANCUN = 17, // Cancun 19426587 (Timestamp: 1710338135) PRAGUE = 18, // Praque TBD + PRAGUE_EOF = 19, // Praque+EOF TBD #[default] LATEST = u8::MAX, } @@ -65,6 +66,7 @@ pub enum SpecId { ECOTONE = 21, FJORD = 22, PRAGUE = 23, + PRAGUE_EOF = 24, #[default] LATEST = u8::MAX, } @@ -107,6 +109,7 @@ impl From<&str> for SpecId { "Shanghai" => Self::SHANGHAI, "Cancun" => Self::CANCUN, "Prague" => Self::PRAGUE, + "PragueEOF" => Self::PRAGUE_EOF, #[cfg(feature = "optimism")] "Bedrock" => SpecId::BEDROCK, #[cfg(feature = "optimism")] @@ -144,6 +147,7 @@ impl From for &'static str { SpecId::SHANGHAI => "Shanghai", SpecId::CANCUN => "Cancun", SpecId::PRAGUE => "Prague", + SpecId::PRAGUE_EOF => "PragueEOF", #[cfg(feature = "optimism")] SpecId::BEDROCK => "Bedrock", #[cfg(feature = "optimism")] @@ -200,6 +204,7 @@ spec!(MERGE, MergeSpec); spec!(SHANGHAI, ShanghaiSpec); spec!(CANCUN, CancunSpec); spec!(PRAGUE, PragueSpec); +spec!(PRAGUE_EOF, PragueEofSpec); spec!(LATEST, LatestSpec); @@ -278,6 +283,10 @@ macro_rules! spec_to_generic { use $crate::PragueSpec as SPEC; $e } + $crate::SpecId::PRAGUE_EOF => { + use $crate::PragueEofSpec as SPEC; + $e + } } }}; } @@ -345,6 +354,10 @@ macro_rules! spec_to_generic { use $crate::PragueSpec as SPEC; $e } + $crate::SpecId::PRAGUE_EOF => { + use $crate::PragueEofSpec as SPEC; + $e + } $crate::SpecId::BEDROCK => { use $crate::BedrockSpec as SPEC; $e @@ -406,6 +419,7 @@ mod tests { #[cfg(feature = "optimism")] spec_to_generic!(FJORD, assert_eq!(SPEC::SPEC_ID, FJORD)); spec_to_generic!(PRAGUE, assert_eq!(SPEC::SPEC_ID, PRAGUE)); + spec_to_generic!(PRAGUE_EOF, assert_eq!(SPEC::SPEC_ID, PRAGUE_EOF)); spec_to_generic!(LATEST, assert_eq!(SPEC::SPEC_ID, LATEST)); } } diff --git a/crates/revm/src/context/inner_evm_context.rs b/crates/revm/src/context/inner_evm_context.rs index c83d5ec14a..c166295148 100644 --- a/crates/revm/src/context/inner_evm_context.rs +++ b/crates/revm/src/context/inner_evm_context.rs @@ -1,7 +1,8 @@ use crate::{ db::Database, interpreter::{ - analysis::to_analysed, gas, return_ok, Contract, CreateInputs, EOFCreateInputs, Gas, + analysis::{to_analysed, validate_eof}, + gas, return_ok, Contract, CreateInputs, EOFCreateInputs, EOFCreateKind, Gas, InstructionResult, Interpreter, InterpreterResult, LoadAccountResult, SStoreResult, SelfDestructResult, MAX_CODE_SIZE, }, @@ -254,10 +255,41 @@ impl InnerEvmContext { gas: Gas::new(inputs.gas_limit), output: Bytes::new(), }, - inputs.created_address, + None, )) }; + let (input, initcode, created_address) = match &inputs.kind { + EOFCreateKind::Opcode { + initcode, + input, + created_address, + } => (input.clone(), initcode.clone(), *created_address), + EOFCreateKind::Tx { initdata } => { + // Use nonce from tx (if set) or from account (if not). + // Nonce for call is bumped in deduct_caller + // TODO(make this part of nonce increment code) + let nonce = self.env.tx.nonce.unwrap_or_else(|| { + let caller = self.env.tx.caller; + self.load_account(caller) + .map(|(a, _)| a.info.nonce) + .unwrap_or_default() + }); + + // decode eof and init code. + let Ok((eof, input)) = Eof::decode_dangling(initdata.clone()) else { + return return_error(InstructionResult::InvalidEOFInitCode); + }; + + if validate_eof(&eof).is_err() { + // TODO (EOF) new error type. + return return_error(InstructionResult::InvalidEOFInitCode); + } + + (input, eof, self.env.tx.caller.create(nonce)) + } + }; + // Check depth if self.journaled_state.depth() > CALL_STACK_LIMIT { return return_error(InstructionResult::CallTooDeep); @@ -279,12 +311,12 @@ impl InnerEvmContext { // Load account so it needs to be marked as warm for access list. self.journaled_state - .load_account(inputs.created_address, &mut self.db)?; + .load_account(created_address, &mut self.db)?; // create account, transfer funds and make the journal checkpoint. let checkpoint = match self.journaled_state.create_account_checkpoint( inputs.caller, - inputs.created_address, + created_address, inputs.value, spec_id, ) { @@ -295,11 +327,11 @@ impl InnerEvmContext { }; let contract = Contract::new( - inputs.input.clone(), + input.clone(), // fine to clone as it is Bytes. - Bytecode::Eof(Arc::new(inputs.eof_init_code.clone())), + Bytecode::Eof(Arc::new(initcode.clone())), None, - inputs.created_address, + created_address, inputs.caller, inputs.value, ); @@ -309,7 +341,7 @@ impl InnerEvmContext { interpreter.set_is_eof_init(); Ok(FrameOrResult::new_eofcreate_frame( - inputs.created_address, + created_address, checkpoint, interpreter, )) @@ -334,6 +366,12 @@ impl InnerEvmContext { return; } + if interpreter_result.output.len() > MAX_CODE_SIZE { + self.journaled_state.checkpoint_revert(journal_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) { @@ -361,14 +399,11 @@ impl InnerEvmContext { spec_id: SpecId, inputs: &CreateInputs, ) -> Result> { - // Prepare crate. - let gas = Gas::new(inputs.gas_limit); - let return_error = |e| { Ok(FrameOrResult::new_create_result( InterpreterResult { result: e, - gas, + gas: Gas::new(inputs.gas_limit), output: Bytes::new(), }, None, @@ -380,6 +415,11 @@ impl InnerEvmContext { return return_error(InstructionResult::CallTooDeep); } + // Prague EOF + if spec_id.is_enabled_in(PRAGUE_EOF) && inputs.init_code.get(..2) == Some(&[0xEF, 00]) { + return return_error(InstructionResult::CreateInitCodeStartingEF00); + } + // Fetch balance of caller. let (caller_balance, _) = self.balance(inputs.caller)?; @@ -437,7 +477,7 @@ impl InnerEvmContext { Ok(FrameOrResult::new_create_frame( created_address, checkpoint, - Interpreter::new(contract, gas.limit(), false), + Interpreter::new(contract, inputs.gas_limit, false), )) } diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index 5cb64af8c5..9c67a8e984 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -3,17 +3,16 @@ use crate::{ db::{Database, DatabaseCommit, EmptyDB}, handler::Handler, interpreter::{ - analysis::validate_eof, CallInputs, CreateInputs, EOFCreateInputs, EOFCreateOutcome, Gas, - Host, InstructionResult, InterpreterAction, InterpreterResult, SharedMemory, + CallInputs, CreateInputs, EOFCreateInputs, Host, InterpreterAction, SharedMemory, }, primitives::{ - specification::SpecId, BlockEnv, Bytes, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, + specification::SpecId, BlockEnv, CfgEnv, EVMError, EVMResult, EnvWithHandlerCfg, ExecutionResult, HandlerCfg, ResultAndState, TxEnv, TxKind, }, Context, ContextWithHandlerCfg, Frame, FrameOrResult, FrameResult, }; use core::fmt; -use std::vec::Vec; +use std::{boxed::Box, vec::Vec}; /// EVM call stack limit. pub const CALL_STACK_LIMIT: u64 = 1024; @@ -350,51 +349,19 @@ impl Evm<'_, EXT, DB> { )?, TxKind::Create => { // if first byte of data is magic 0xEF00, then it is EOFCreate. - if spec_id.is_enabled_in(SpecId::PRAGUE) + if spec_id.is_enabled_in(SpecId::PRAGUE_EOF) && ctx .env() .tx .data - .get(0..=1) + .get(0..2) .filter(|&t| t == [0xEF, 00]) .is_some() { - // TODO Should we just check 0xEF it seems excessive to switch to legacy only - // if it 0xEF00? - - // get nonce from tx (if set) or from account (if not). - // Nonce for call is bumped in deduct_caller while - // for CREATE it is not (it is done inside exec handlers). - let nonce = ctx.evm.env.tx.nonce.unwrap_or_else(|| { - let caller = ctx.evm.env.tx.caller; - ctx.evm - .load_account(caller) - .map(|(a, _)| a.info.nonce) - .unwrap_or_default() - }); - - // Create EOFCreateInput from transaction initdata. - let eofcreate = EOFCreateInputs::new_tx_boxed(&ctx.evm.env.tx, nonce) - .ok() - .and_then(|eofcreate| { - // validate EOF initcode - validate_eof(&eofcreate.eof_init_code).ok()?; - Some(eofcreate) - }); - - if let Some(eofcreate) = eofcreate { - exec.eofcreate(ctx, eofcreate)? - } else { - // Return result, as code is invalid. - FrameOrResult::Result(FrameResult::EOFCreate(EOFCreateOutcome::new( - InterpreterResult::new( - InstructionResult::Stop, - Bytes::new(), - Gas::new(gas_limit), - ), - ctx.env().tx.caller.create(nonce), - ))) - } + exec.eofcreate( + ctx, + Box::new(EOFCreateInputs::new_tx(&ctx.evm.env.tx, gas_limit)), + )? } else { // Safe to unwrap because we are sure that it is create tx. exec.create( diff --git a/crates/revm/src/frame.rs b/crates/revm/src/frame.rs index c36ffe0707..2ef01db561 100644 --- a/crates/revm/src/frame.rs +++ b/crates/revm/src/frame.rs @@ -4,9 +4,7 @@ use crate::{ JournalCheckpoint, }; use core::ops::Range; -use revm_interpreter::{ - CallOutcome, CreateOutcome, EOFCreateOutcome, Gas, InstructionResult, InterpreterResult, -}; +use revm_interpreter::{CallOutcome, CreateOutcome, Gas, InstructionResult, InterpreterResult}; use std::boxed::Box; /// Call CallStackFrame. @@ -59,7 +57,7 @@ pub enum Frame { pub enum FrameResult { Call(CallOutcome), Create(CreateOutcome), - EOFCreate(EOFCreateOutcome), + EOFCreate(CreateOutcome), } impl FrameResult { @@ -82,7 +80,7 @@ impl FrameResult { Output::Create(outcome.result.output.clone(), outcome.address) } FrameResult::EOFCreate(outcome) => { - Output::Create(outcome.result.output.clone(), Some(outcome.address)) + Output::Create(outcome.result.output.clone(), outcome.address) } } } @@ -277,8 +275,11 @@ impl FrameOrResult { })) } - pub fn new_eofcreate_result(interpreter_result: InterpreterResult, address: Address) -> Self { - FrameOrResult::Result(FrameResult::EOFCreate(EOFCreateOutcome { + pub fn new_eofcreate_result( + interpreter_result: InterpreterResult, + address: Option
, + ) -> Self { + FrameOrResult::Result(FrameResult::EOFCreate(CreateOutcome { result: interpreter_result, address, })) diff --git a/crates/revm/src/handler/handle_types/execution.rs b/crates/revm/src/handler/handle_types/execution.rs index 9e17def07c..27d31eb118 100644 --- a/crates/revm/src/handler/handle_types/execution.rs +++ b/crates/revm/src/handler/handle_types/execution.rs @@ -6,8 +6,8 @@ use crate::{ CallFrame, Context, CreateFrame, Frame, FrameOrResult, FrameResult, }; use revm_interpreter::{ - opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInputs, EOFCreateOutcome, - InterpreterAction, InterpreterResult, + opcode::InstructionTables, CallOutcome, CreateOutcome, EOFCreateInputs, InterpreterAction, + InterpreterResult, }; use std::{boxed::Box, sync::Arc}; @@ -102,7 +102,7 @@ pub type FrameEOFCreateReturnHandle<'a, EXT, DB> = Arc< &mut Context, Box, InterpreterResult, - ) -> Result::Error>> + ) -> Result::Error>> + 'a, >; @@ -111,7 +111,7 @@ pub type InsertEOFCreateOutcomeHandle<'a, EXT, DB> = Arc< dyn Fn( &mut Context, &mut Frame, - EOFCreateOutcome, + CreateOutcome, ) -> Result<(), EVMError<::Error>> + 'a, >; @@ -267,7 +267,7 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { context: &mut Context, frame: Box, interpreter_result: InterpreterResult, - ) -> Result> { + ) -> Result> { (self.eofcreate_return)(context, frame, interpreter_result) } @@ -277,7 +277,7 @@ impl<'a, EXT, DB: Database> ExecutionHandler<'a, EXT, DB> { &self, context: &mut Context, frame: &mut Frame, - outcome: EOFCreateOutcome, + outcome: CreateOutcome, ) -> Result<(), EVMError> { (self.insert_eofcreate_outcome)(context, frame, outcome) } diff --git a/crates/revm/src/handler/mainnet/execution.rs b/crates/revm/src/handler/mainnet/execution.rs index 4ee557f81b..928d173508 100644 --- a/crates/revm/src/handler/mainnet/execution.rs +++ b/crates/revm/src/handler/mainnet/execution.rs @@ -10,8 +10,8 @@ use crate::{ }; use core::mem; use revm_interpreter::{ - opcode::InstructionTables, CallOutcome, EOFCreateInputs, EOFCreateOutcome, InterpreterAction, - InterpreterResult, EMPTY_SHARED_MEMORY, + opcode::InstructionTables, CallOutcome, EOFCreateInputs, InterpreterAction, InterpreterResult, + EMPTY_SHARED_MEMORY, }; use std::boxed::Box; @@ -174,15 +174,15 @@ pub fn eofcreate_return( context: &mut Context, frame: Box, mut interpreter_result: InterpreterResult, -) -> Result> { +) -> Result> { context.evm.eofcreate_return::( &mut interpreter_result, frame.created_address, frame.frame_data.checkpoint, ); - Ok(EOFCreateOutcome::new( + Ok(CreateOutcome::new( interpreter_result, - frame.created_address, + Some(frame.created_address), )) } @@ -190,7 +190,7 @@ pub fn eofcreate_return( pub fn insert_eofcreate_outcome( context: &mut Context, frame: &mut Frame, - outcome: EOFCreateOutcome, + outcome: CreateOutcome, ) -> Result<(), EVMError> { core::mem::replace(&mut context.evm.error, Ok(()))?; frame diff --git a/crates/revm/src/handler/mainnet/post_execution.rs b/crates/revm/src/handler/mainnet/post_execution.rs index bf73236159..0e5cb4e187 100644 --- a/crates/revm/src/handler/mainnet/post_execution.rs +++ b/crates/revm/src/handler/mainnet/post_execution.rs @@ -111,9 +111,7 @@ pub fn output( gas_used: final_gas_used, }, // Only two internal return flags. - flag @ (SuccessOrHalt::FatalExternalError - | SuccessOrHalt::InternalContinue - | SuccessOrHalt::InternalCallOrCreate) => { + flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => { panic!( "Encountered unexpected internal return flag: {:?} with instruction result: {:?}", flag, instruction_result diff --git a/crates/revm/src/inspector.rs b/crates/revm/src/inspector.rs index 26551c8d8d..3225ed3546 100644 --- a/crates/revm/src/inspector.rs +++ b/crates/revm/src/inspector.rs @@ -1,10 +1,3 @@ -use crate::{ - interpreter::{CallInputs, CreateInputs, EOFCreateInputs, EOFCreateOutcome, Interpreter}, - primitives::{db::Database, Address, Log, U256}, - EvmContext, -}; -use auto_impl::auto_impl; - #[cfg(feature = "std")] mod customprinter; #[cfg(all(feature = "std", feature = "serde-json"))] @@ -13,10 +6,16 @@ mod gas; mod handler_register; mod noop; -// Exports. - pub use handler_register::{inspector_handle_register, GetInspector}; -use revm_interpreter::{CallOutcome, CreateOutcome}; + +use crate::{ + interpreter::{ + CallInputs, CallOutcome, CreateInputs, CreateOutcome, EOFCreateInputs, Interpreter, + }, + primitives::{db::Database, Address, Log, U256}, + EvmContext, +}; +use auto_impl::auto_impl; /// [Inspector] implementations. pub mod inspectors { @@ -142,7 +141,7 @@ pub trait Inspector { &mut self, context: &mut EvmContext, inputs: &mut EOFCreateInputs, - ) -> Option { + ) -> Option { let _ = context; let _ = inputs; None @@ -153,8 +152,8 @@ pub trait Inspector { &mut self, context: &mut EvmContext, inputs: &EOFCreateInputs, - outcome: EOFCreateOutcome, - ) -> EOFCreateOutcome { + outcome: CreateOutcome, + ) -> CreateOutcome { let _ = context; let _ = inputs; outcome From eee57298af0a42b3c67ccc89691697d04214d975 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 20 Jun 2024 19:21:46 +0200 Subject: [PATCH 87/88] chore: release (#1548) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> --- Cargo.lock | 10 ++-- bins/revm-test/CHANGELOG.md | 90 +++++++++++++++++++++++++++++++++ bins/revm-test/Cargo.toml | 2 +- bins/revme/CHANGELOG.md | 13 +++++ bins/revme/Cargo.toml | 4 +- crates/interpreter/CHANGELOG.md | 49 ++++++++++++++++++ crates/interpreter/Cargo.toml | 4 +- crates/precompile/CHANGELOG.md | 22 ++++++++ crates/precompile/Cargo.toml | 4 +- crates/primitives/CHANGELOG.md | 27 ++++++++++ crates/primitives/Cargo.toml | 2 +- crates/revm/CHANGELOG.md | 47 +++++++++++++++++ crates/revm/Cargo.toml | 6 +-- 13 files changed, 264 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5087985f71..23560d9d4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3079,7 +3079,7 @@ dependencies = [ [[package]] name = "revm" -version = "9.0.0" +version = "10.0.0" dependencies = [ "alloy-eips", "alloy-provider", @@ -3105,7 +3105,7 @@ dependencies = [ [[package]] name = "revm-interpreter" -version = "5.0.0" +version = "6.0.0" dependencies = [ "bincode", "paste", @@ -3118,7 +3118,7 @@ dependencies = [ [[package]] name = "revm-precompile" -version = "7.0.0" +version = "8.0.0" dependencies = [ "aurora-engine-modexp", "blst", @@ -3142,7 +3142,7 @@ dependencies = [ [[package]] name = "revm-primitives" -version = "4.0.0" +version = "5.0.0" dependencies = [ "alloy-primitives", "auto_impl", @@ -3175,7 +3175,7 @@ dependencies = [ [[package]] name = "revme" -version = "0.5.0" +version = "0.6.0" dependencies = [ "alloy-rlp", "hash-db", diff --git a/bins/revm-test/CHANGELOG.md b/bins/revm-test/CHANGELOG.md index 4821d7ec54..63053a3463 100644 --- a/bins/revm-test/CHANGELOG.md +++ b/bins/revm-test/CHANGELOG.md @@ -6,6 +6,96 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.1.0](https://github.com/bluealloy/revm/releases/tag/revm-test-v0.1.0) - 2024-06-20 + +### Added +- EOF (Ethereum Object Format) ([#1143](https://github.com/bluealloy/revm/pull/1143)) +- add tests for shift instructions ([#1254](https://github.com/bluealloy/revm/pull/1254)) +- EvmBuilder and External Contexts ([#888](https://github.com/bluealloy/revm/pull/888)) +- separate initial checks ([#486](https://github.com/bluealloy/revm/pull/486)) +- revm-interpreter created ([#320](https://github.com/bluealloy/revm/pull/320)) +- *(interpreter)* Unify instruction fn signature ([#283](https://github.com/bluealloy/revm/pull/283)) +- Migrate `primitive_types::U256` to `ruint::Uint<256, 4>` ([#239](https://github.com/bluealloy/revm/pull/239)) +- Introduce ByteCode format, Update Readme ([#156](https://github.com/bluealloy/revm/pull/156)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) +- *(clippy)* fix some clippy lints + +### Other +- replace TransactTo with TxKind ([#1542](https://github.com/bluealloy/revm/pull/1542)) +- *(deps)* bump regex from 1.10.4 to 1.10.5 ([#1502](https://github.com/bluealloy/revm/pull/1502)) +- release ([#1261](https://github.com/bluealloy/revm/pull/1261)) +- *(interpreter)* rewrite gas accounting for memory expansion ([#1361](https://github.com/bluealloy/revm/pull/1361)) +- revert snailtracer without microbench ([#1259](https://github.com/bluealloy/revm/pull/1259)) +- release ([#1231](https://github.com/bluealloy/revm/pull/1231)) +- *(deps)* bump other alloy deps 0.7.0 ([#1252](https://github.com/bluealloy/revm/pull/1252)) +- *(deps)* bump regex from 1.10.3 to 1.10.4 ([#1223](https://github.com/bluealloy/revm/pull/1223)) +- *(deps)* bump bytes from 1.5.0 to 1.6.0 ([#1224](https://github.com/bluealloy/revm/pull/1224)) +- release ([#1175](https://github.com/bluealloy/revm/pull/1175)) +- tag v32 revm v7.1.0 ([#1176](https://github.com/bluealloy/revm/pull/1176)) +- release ([#1125](https://github.com/bluealloy/revm/pull/1125)) +- *(deps)* bump alloy-sol-types from 0.6.3 to 0.6.4 ([#1148](https://github.com/bluealloy/revm/pull/1148)) +- *(deps)* bump alloy-sol-macro from 0.6.3 to 0.6.4 ([#1136](https://github.com/bluealloy/revm/pull/1136)) +- release tag v30 revm v6.1.0 ([#1100](https://github.com/bluealloy/revm/pull/1100)) +- clippy cleanup ([#1112](https://github.com/bluealloy/revm/pull/1112)) +- *(deps)* bump alloy-sol-types from 0.6.2 to 0.6.3 ([#1103](https://github.com/bluealloy/revm/pull/1103)) +- release ([#1082](https://github.com/bluealloy/revm/pull/1082)) +- *(deps)* bump alloy-sol-macro from 0.6.2 to 0.6.3 ([#1094](https://github.com/bluealloy/revm/pull/1094)) +- license date and revm docs ([#1080](https://github.com/bluealloy/revm/pull/1080)) +- release ([#1067](https://github.com/bluealloy/revm/pull/1067)) +- tag v27, revm v4.0.0 release ([#1061](https://github.com/bluealloy/revm/pull/1061)) +- *(deps)* bump eyre from 0.6.11 to 0.6.12 ([#1051](https://github.com/bluealloy/revm/pull/1051)) +- *(deps)* bump alloy-sol-types from 0.6.0 to 0.6.2 ([#1035](https://github.com/bluealloy/revm/pull/1035)) +- *(deps)* bump alloy-sol-macro from 0.6.0 to 0.6.2 ([#1013](https://github.com/bluealloy/revm/pull/1013)) +- chore(Test) : const to static ([#1016](https://github.com/bluealloy/revm/pull/1016)) +- Burntpix criterion bench ([#1004](https://github.com/bluealloy/revm/pull/1004)) +- Instruction table ([#759](https://github.com/bluealloy/revm/pull/759)) +- rewrite revm-test as a criterion bench ([#579](https://github.com/bluealloy/revm/pull/579)) +- optimize stack usage for recursive `call` and `create` programs ([#522](https://github.com/bluealloy/revm/pull/522)) +- Bump v24, revm v3.3.0 ([#476](https://github.com/bluealloy/revm/pull/476)) +- Release v23, revm v3.2.0 ([#464](https://github.com/bluealloy/revm/pull/464)) +- Release v22, revm v3.1.1 ([#460](https://github.com/bluealloy/revm/pull/460)) +- v21, revm v3.1.0 ([#444](https://github.com/bluealloy/revm/pull/444)) +- remove gas blocks ([#391](https://github.com/bluealloy/revm/pull/391)) +- *(deps)* bump bytes from 1.3.0 to 1.4.0 ([#355](https://github.com/bluealloy/revm/pull/355)) +- Bump v20, changelog ([#350](https://github.com/bluealloy/revm/pull/350)) +- includes to libs ([#338](https://github.com/bluealloy/revm/pull/338)) +- Creating revm-primitives, revm better errors and db components ([#334](https://github.com/bluealloy/revm/pull/334)) +- Cleanup, move hot fields toggether in Interpreter ([#321](https://github.com/bluealloy/revm/pull/321)) +- native bits ([#278](https://github.com/bluealloy/revm/pull/278)) +- *(release)* Bump revm and precompiles versions +- Bump primitive_types. Add statetest spec +- Bump revm v2.1.0 ([#224](https://github.com/bluealloy/revm/pull/224)) +- revm bump v2.0.0, precompile bump v1.1.1 ([#212](https://github.com/bluealloy/revm/pull/212)) +- Cfg choose create analysis, option on bytecode size limit ([#210](https://github.com/bluealloy/revm/pull/210)) +- Cargo sort. Bump lib versions ([#208](https://github.com/bluealloy/revm/pull/208)) +- Return `ExecutionResult`, which includes `gas_refunded` ([#169](https://github.com/bluealloy/revm/pull/169)) +- Bytecode hash, remove override_spec, ([#165](https://github.com/bluealloy/revm/pull/165)) +- revm bump 1.8. update libs. snailtracer rename ([#159](https://github.com/bluealloy/revm/pull/159)) +- v6 changelog, bump versions +- Big Refactor. Machine to Interpreter. refactor instructions. call/create struct ([#52](https://github.com/bluealloy/revm/pull/52)) +- [revm] pop_top and unsafe comments ([#51](https://github.com/bluealloy/revm/pull/51)) +- [precompiles] remove unused borsh +- [recompl] Bump precompile deps, cargo sort on workspace +- [revm] output log. Stetetest test log output. fmt +- Bump versions, Changelogs, fmt, revm readme, clippy. +- [revm] Run test multiple times. fmt, BenchmarkDB +- Multiple changes: web3 db, debugger initial commit, precompile load +- Memory to usize, clippy,fmt +- wip optimize i256 +- TEMP switch stacks H256 with U256 +- [revm] some perfs +- [revm] Perfs stack pop. Benchmark snailtracer. +- [revm] cleanup +- fmt +- EVM Interface changed. Inspector called separately +- Bump revm v0.3.0. README updated +- DB ref mut polished +- And now we debug +- [revm] Interface. Inspector added, Env cleanup. revm-test passes +- Rename bin to bins + ## [0.1.0](https://github.com/bluealloy/revm/releases/tag/revm-test-v0.1.0) - 2024-02-07 ### Added diff --git a/bins/revm-test/Cargo.toml b/bins/revm-test/Cargo.toml index 01a5ab9ab8..c18da1135e 100644 --- a/bins/revm-test/Cargo.toml +++ b/bins/revm-test/Cargo.toml @@ -7,7 +7,7 @@ edition = "2021" [dependencies] bytes = "1.6" hex = "0.4" -revm = { path = "../../crates/revm", version = "9.0.0", default-features=false } +revm = { path = "../../crates/revm", version = "10.0.0", default-features=false } microbench = "0.5" alloy-sol-macro = "0.7.0" alloy-sol-types = "0.7.0" diff --git a/bins/revme/CHANGELOG.md b/bins/revme/CHANGELOG.md index 41e895456c..fdd6500108 100644 --- a/bins/revme/CHANGELOG.md +++ b/bins/revme/CHANGELOG.md @@ -6,6 +6,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.6.0](https://github.com/bluealloy/revm/compare/revme-v0.5.0...revme-v0.6.0) - 2024-06-20 + +### Added +- *(EOF)* Put EOF bytecode behind an Arc ([#1517](https://github.com/bluealloy/revm/pull/1517)) +- *(revme)* add prague spec ([#1506](https://github.com/bluealloy/revm/pull/1506)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) + +### Other +- replace TransactTo with TxKind ([#1542](https://github.com/bluealloy/revm/pull/1542)) +- skip tests with storage check and return status ([#1452](https://github.com/bluealloy/revm/pull/1452)) + ## [0.5.0](https://github.com/bluealloy/revm/compare/revme-v0.4.0...revme-v0.5.0) - 2024-05-12 ### Added diff --git a/bins/revme/Cargo.toml b/bins/revme/Cargo.toml index 71d9d6543d..04f9b26442 100644 --- a/bins/revme/Cargo.toml +++ b/bins/revme/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["ethereum", "evm"] license = "MIT" repository = "https://github.com/bluealloy/revm" description = "Rust Ethereum Virtual Machine Executable" -version = "0.5.0" +version = "0.6.0" [dependencies] hash-db = "0.15" @@ -15,7 +15,7 @@ hashbrown = "0.14" indicatif = "0.17" microbench = "0.5" plain_hasher = "0.2" -revm = { path = "../../crates/revm", version = "9.0.0", default-features = false, features = [ +revm = { path = "../../crates/revm", version = "10.0.0", default-features = false, features = [ "ethersdb", "std", "serde-json", diff --git a/crates/interpreter/CHANGELOG.md b/crates/interpreter/CHANGELOG.md index be64279f7d..2ae9a3cab3 100644 --- a/crates/interpreter/CHANGELOG.md +++ b/crates/interpreter/CHANGELOG.md @@ -6,6 +6,55 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [6.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v5.0.0...revm-interpreter-v6.0.0) - 2024-06-20 + +### Added +- *(EOF)* Put EOF bytecode behind an Arc ([#1517](https://github.com/bluealloy/revm/pull/1517)) +- *(EOF)* EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support ([#1504](https://github.com/bluealloy/revm/pull/1504)) +- add helpers for working with instruction tables ([#1493](https://github.com/bluealloy/revm/pull/1493)) +- *(EOF)* change oob behavior of RETURNDATALOAD and RETURNDATACOPY ([#1476](https://github.com/bluealloy/revm/pull/1476)) +- *(EOF)* EIP-7698 eof creation transaction ([#1467](https://github.com/bluealloy/revm/pull/1467)) +- adjust gas-costs for EIP-2935 BLOCKHASH ([#1422](https://github.com/bluealloy/revm/pull/1422)) +- add Opcode::modifies_memory back ([#1421](https://github.com/bluealloy/revm/pull/1421)) +- *(EOF)* Add CALLF/JUMPF stack checks ([#1417](https://github.com/bluealloy/revm/pull/1417)) +- *(EOF)* remove TXCREATE ([#1415](https://github.com/bluealloy/revm/pull/1415)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) +- *(eof)* output gas for eofcreate ([#1540](https://github.com/bluealloy/revm/pull/1540)) +- *(EOF)* set CallOrCreate result in EOFCREATE ([#1535](https://github.com/bluealloy/revm/pull/1535)) +- *(EOF)* target needed for EOFCREATE created address ([#1536](https://github.com/bluealloy/revm/pull/1536)) +- *(EOF)* ext*call return values ([#1515](https://github.com/bluealloy/revm/pull/1515)) +- *(EOF)* Remove redundunt ext call gas cost ([#1513](https://github.com/bluealloy/revm/pull/1513)) +- *(EOF)* add DATACOPY copy gas ([#1510](https://github.com/bluealloy/revm/pull/1510)) +- *(EOF)* extstaticcall make static ([#1508](https://github.com/bluealloy/revm/pull/1508)) +- *(EOF)* jumpf gas was changes ([#1507](https://github.com/bluealloy/revm/pull/1507)) +- *(EOF)* panic on empty input range, and continue exec after eofcreate ([#1477](https://github.com/bluealloy/revm/pull/1477)) +- *(eof)* EOFCREATE spend gas and apply 63/64 rule ([#1471](https://github.com/bluealloy/revm/pull/1471)) +- *(stack)* pop with five items was not correct ([#1472](https://github.com/bluealloy/revm/pull/1472)) +- *(EOF)* returncontract immediate is one byte ([#1468](https://github.com/bluealloy/revm/pull/1468)) +- *(Interpreter)* wrong block number used ([#1458](https://github.com/bluealloy/revm/pull/1458)) +- *(interpreter)* avoid overflow when checking if mem limit reached ([#1429](https://github.com/bluealloy/revm/pull/1429)) +- blockchash for devnet-0 ([#1427](https://github.com/bluealloy/revm/pull/1427)) + +### Other +- replace TransactTo with TxKind ([#1542](https://github.com/bluealloy/revm/pull/1542)) +- simplify Interpreter serde ([#1544](https://github.com/bluealloy/revm/pull/1544)) +- *(interpreter)* use U256::arithmetic_shr in SAR ([#1525](https://github.com/bluealloy/revm/pull/1525)) +- pluralize EOFCreateInput ([#1523](https://github.com/bluealloy/revm/pull/1523)) +- added simular to used-by ([#1521](https://github.com/bluealloy/revm/pull/1521)) +- Removed .clone() in ExecutionHandler::call, and reusing output buffer in Interpreter ([#1512](https://github.com/bluealloy/revm/pull/1512)) +- *(revme)* add new line in revme EOF printer ([#1503](https://github.com/bluealloy/revm/pull/1503)) +- remove old deprecated items ([#1489](https://github.com/bluealloy/revm/pull/1489)) +- *(interpreter)* use max gas limit in `impl Default for Interpreter` ([#1478](https://github.com/bluealloy/revm/pull/1478)) +- *(interpreter)* optimisation for BYTE, SHL, SHR and SAR ([#1418](https://github.com/bluealloy/revm/pull/1418)) +- Revert "Revert "feat: implement EIP-2935 ([#1354](https://github.com/bluealloy/revm/pull/1354))" ([#1424](https://github.com/bluealloy/revm/pull/1424))" ([#1426](https://github.com/bluealloy/revm/pull/1426)) +- Revert "feat: implement EIP-2935 ([#1354](https://github.com/bluealloy/revm/pull/1354))" ([#1424](https://github.com/bluealloy/revm/pull/1424)) +- *(EOF)* rename extcall opcode/names ([#1416](https://github.com/bluealloy/revm/pull/1416)) +- point to gas! in Gas::record_cost ([#1413](https://github.com/bluealloy/revm/pull/1413)) +- pop_address should use crate scope ([#1410](https://github.com/bluealloy/revm/pull/1410)) +- Remove Host constrain from calc_call_gas ([#1409](https://github.com/bluealloy/revm/pull/1409)) + ## [5.0.0](https://github.com/bluealloy/revm/compare/revm-interpreter-v4.0.0...revm-interpreter-v5.0.0) - 2024-05-12 ### Added diff --git a/crates/interpreter/Cargo.toml b/crates/interpreter/Cargo.toml index cd6b3d9668..91777aa638 100644 --- a/crates/interpreter/Cargo.toml +++ b/crates/interpreter/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm", "interpreter"] license = "MIT" name = "revm-interpreter" repository = "https://github.com/bluealloy/revm" -version = "5.0.0" +version = "6.0.0" readme = "../../README.md" [package.metadata.docs.rs] @@ -22,7 +22,7 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] -revm-primitives = { path = "../primitives", version = "4.0.0", default-features = false } +revm-primitives = { path = "../primitives", version = "5.0.0", default-features = false } paste = { version = "1.0", optional = true } phf = { version = "0.11", default-features = false, optional = true, features = [ diff --git a/crates/precompile/CHANGELOG.md b/crates/precompile/CHANGELOG.md index ac868f2e44..9edb307ac4 100644 --- a/crates/precompile/CHANGELOG.md +++ b/crates/precompile/CHANGELOG.md @@ -6,6 +6,28 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [8.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v7.0.0...revm-precompile-v8.0.0) - 2024-06-20 + +### Added +- *(precompiles)* fatal error for precompiles ([#1499](https://github.com/bluealloy/revm/pull/1499)) +- add ecAdd to precompile bench ([#1496](https://github.com/bluealloy/revm/pull/1496)) +- *(optimism)* Add secp256r1 precompile for Fjord ([#1436](https://github.com/bluealloy/revm/pull/1436)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) +- check canonical Fp elements ([#1434](https://github.com/bluealloy/revm/pull/1434)) +- *(precompile)* ignore infinity points in G1 MSM ([#1432](https://github.com/bluealloy/revm/pull/1432)) +- *(precompile)* BLS G2 MSM ([#1428](https://github.com/bluealloy/revm/pull/1428)) + +### Other +- avoid cloning precompiles ([#1486](https://github.com/bluealloy/revm/pull/1486)) +- *(precompiles)* Fix some nits in bls12_381 ([#1495](https://github.com/bluealloy/revm/pull/1495)) +- *(deps)* allow multiple versions of secp256k1 ([#1490](https://github.com/bluealloy/revm/pull/1490)) +- *(deps)* bump rstest from 0.19.0 to 0.21.0 ([#1482](https://github.com/bluealloy/revm/pull/1482)) +- *(deps)* bump blst from 0.3.11 to 0.3.12 ([#1481](https://github.com/bluealloy/revm/pull/1481)) +- add test for map_fp_to_g1 precompile ([#1465](https://github.com/bluealloy/revm/pull/1465)) +- add docs for BLS scalar input decoding ([#1446](https://github.com/bluealloy/revm/pull/1446)) + ## [7.0.0](https://github.com/bluealloy/revm/compare/revm-precompile-v6.0.0...revm-precompile-v7.0.0) - 2024-05-12 ### Added diff --git a/crates/precompile/Cargo.toml b/crates/precompile/Cargo.toml index 097985edca..b27ef6f3be 100644 --- a/crates/precompile/Cargo.toml +++ b/crates/precompile/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm", "precompiles"] license = "MIT" name = "revm-precompile" repository = "https://github.com/bluealloy/revm" -version = "7.0.0" +version = "8.0.0" [package.metadata.docs.rs] all-features = true @@ -21,7 +21,7 @@ rust_2018_idioms = "deny" all = "warn" [dependencies] -revm-primitives = { path = "../primitives", version = "4.0.0", default-features = false } +revm-primitives = { path = "../primitives", version = "5.0.0", default-features = false } once_cell = { version = "1.19", default-features = false, features = ["alloc"] } # ecRecover diff --git a/crates/primitives/CHANGELOG.md b/crates/primitives/CHANGELOG.md index ad68b29b62..3aebb96619 100644 --- a/crates/primitives/CHANGELOG.md +++ b/crates/primitives/CHANGELOG.md @@ -6,6 +6,33 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [5.0.0](https://github.com/bluealloy/revm/compare/revm-primitives-v4.0.0...revm-primitives-v5.0.0) - 2024-06-20 + +### Added +- *(EOF)* Put EOF bytecode behind an Arc ([#1517](https://github.com/bluealloy/revm/pull/1517)) +- *(EOF)* EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support ([#1504](https://github.com/bluealloy/revm/pull/1504)) +- *(precompiles)* fatal error for precompiles ([#1499](https://github.com/bluealloy/revm/pull/1499)) +- Persist reverted account and storage slot lookups in `JournaledState` ([#1437](https://github.com/bluealloy/revm/pull/1437)) +- *(EOF)* EIP-7698 eof creation transaction ([#1467](https://github.com/bluealloy/revm/pull/1467)) +- *(optimism)* Add secp256r1 precompile for Fjord ([#1436](https://github.com/bluealloy/revm/pull/1436)) +- *(EOF)* Add CALLF/JUMPF stack checks ([#1417](https://github.com/bluealloy/revm/pull/1417)) +- *(EOF)* remove TXCREATE ([#1415](https://github.com/bluealloy/revm/pull/1415)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) +- *(primitives)* specify the optimism cfg on spec_to_generic ([#1412](https://github.com/bluealloy/revm/pull/1412)) + +### Other +- replace TransactTo with TxKind ([#1542](https://github.com/bluealloy/revm/pull/1542)) +- remove DatabaseWithDebugError ([#1545](https://github.com/bluealloy/revm/pull/1545)) +- avoid cloning precompiles ([#1486](https://github.com/bluealloy/revm/pull/1486)) +- added simular to used-by ([#1521](https://github.com/bluealloy/revm/pull/1521)) +- derive PartialEq and Hash on EnvKzgSettings ([#1494](https://github.com/bluealloy/revm/pull/1494)) +- remove old deprecated items ([#1489](https://github.com/bluealloy/revm/pull/1489)) +- *(primitives)* rename State/Storage to EvmState/EvmStorage ([#1459](https://github.com/bluealloy/revm/pull/1459)) +- Revert "Revert "feat: implement EIP-2935 ([#1354](https://github.com/bluealloy/revm/pull/1354))" ([#1424](https://github.com/bluealloy/revm/pull/1424))" ([#1426](https://github.com/bluealloy/revm/pull/1426)) +- Revert "feat: implement EIP-2935 ([#1354](https://github.com/bluealloy/revm/pull/1354))" ([#1424](https://github.com/bluealloy/revm/pull/1424)) + ## [4.0.0](https://github.com/bluealloy/revm/compare/revm-primitives-v3.1.1...revm-primitives-v4.0.0) - 2024-05-12 ### Added diff --git a/crates/primitives/Cargo.toml b/crates/primitives/Cargo.toml index a9d009d2e4..eeb36da112 100644 --- a/crates/primitives/Cargo.toml +++ b/crates/primitives/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm", "types"] license = "MIT" name = "revm-primitives" repository = "https://github.com/bluealloy/revm" -version = "4.0.0" +version = "5.0.0" readme = "../../README.md" [package.metadata.docs.rs] diff --git a/crates/revm/CHANGELOG.md b/crates/revm/CHANGELOG.md index fc2408cb5c..0822ca7334 100644 --- a/crates/revm/CHANGELOG.md +++ b/crates/revm/CHANGELOG.md @@ -6,6 +6,53 @@ 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-v9.0.0...revm-v10.0.0) - 2024-06-20 + +### Added +- *(revm)* derive serde for `BundleState` ([#1539](https://github.com/bluealloy/revm/pull/1539)) +- bump alloy, re-enable alloydb ([#1533](https://github.com/bluealloy/revm/pull/1533)) +- mutable access for all fields in BundleBuilder ([#1524](https://github.com/bluealloy/revm/pull/1524)) +- *(EOF)* Put EOF bytecode behind an Arc ([#1517](https://github.com/bluealloy/revm/pull/1517)) +- *(EOF)* EXTCODECOPY,EXTCODESIZE,EXTCODEHASH eof support ([#1504](https://github.com/bluealloy/revm/pull/1504)) +- add helpers for working with instruction tables ([#1493](https://github.com/bluealloy/revm/pull/1493)) +- *(precompiles)* fatal error for precompiles ([#1499](https://github.com/bluealloy/revm/pull/1499)) +- Persist reverted account and storage slot lookups in `JournaledState` ([#1437](https://github.com/bluealloy/revm/pull/1437)) +- *(EOF)* EIP-7698 eof creation transaction ([#1467](https://github.com/bluealloy/revm/pull/1467)) +- *(EOF)* Add EOF to inspector handle register ([#1469](https://github.com/bluealloy/revm/pull/1469)) +- *(optimism)* Implement new L1 cost function for Fjord ([#1420](https://github.com/bluealloy/revm/pull/1420)) +- *(optimism)* Add secp256r1 precompile for Fjord ([#1436](https://github.com/bluealloy/revm/pull/1436)) +- *(revm)* revert EIP-2935 BLOCKHASH opcode changes ([#1450](https://github.com/bluealloy/revm/pull/1450)) +- load account should return db error ([#1447](https://github.com/bluealloy/revm/pull/1447)) +- *(EOF)* remove TXCREATE ([#1415](https://github.com/bluealloy/revm/pull/1415)) + +### Fixed +- *(eof)* fixture 2 tests ([#1550](https://github.com/bluealloy/revm/pull/1550)) +- *(eof)* output gas for eofcreate ([#1540](https://github.com/bluealloy/revm/pull/1540)) +- *(revm)* remove storage reset that clears is_cold flag ([#1518](https://github.com/bluealloy/revm/pull/1518)) +- *(op)* Remove `U256::from()` ([#1498](https://github.com/bluealloy/revm/pull/1498)) +- *(EOF)* panic on empty input range, and continue exec after eofcreate ([#1477](https://github.com/bluealloy/revm/pull/1477)) +- *(Interpreter)* wrong block number used ([#1458](https://github.com/bluealloy/revm/pull/1458)) +- blockchash for devnet-0 ([#1427](https://github.com/bluealloy/revm/pull/1427)) + +### Other +- Add CI build target for no-std + optimism, use matrix builds ([#1551](https://github.com/bluealloy/revm/pull/1551)) +- replace TransactTo with TxKind ([#1542](https://github.com/bluealloy/revm/pull/1542)) +- avoid cloning precompiles ([#1486](https://github.com/bluealloy/revm/pull/1486)) +- add setters to `BundleBuilder` with `&mut self` ([#1527](https://github.com/bluealloy/revm/pull/1527)) +- pluralize EOFCreateInput ([#1523](https://github.com/bluealloy/revm/pull/1523)) +- added simular to used-by ([#1521](https://github.com/bluealloy/revm/pull/1521)) +- Removed .clone() in ExecutionHandler::call, and reusing output buffer in Interpreter ([#1512](https://github.com/bluealloy/revm/pull/1512)) +- remove old deprecated items ([#1489](https://github.com/bluealloy/revm/pull/1489)) +- *(deps)* bump rstest from 0.19.0 to 0.21.0 ([#1482](https://github.com/bluealloy/revm/pull/1482)) +- *(deps)* bump tokio from 1.37.0 to 1.38.0 ([#1480](https://github.com/bluealloy/revm/pull/1480)) +- *(primitives)* rename State/Storage to EvmState/EvmStorage ([#1459](https://github.com/bluealloy/revm/pull/1459)) +- remove 'checked' bytecode bench causing benchmarks to crash due to name ([#1461](https://github.com/bluealloy/revm/pull/1461)) +- cargo update ([#1451](https://github.com/bluealloy/revm/pull/1451)) +- cleanup host blockhash fn ([#1430](https://github.com/bluealloy/revm/pull/1430)) +- Revert "Revert "feat: implement EIP-2935 ([#1354](https://github.com/bluealloy/revm/pull/1354))" ([#1424](https://github.com/bluealloy/revm/pull/1424))" ([#1426](https://github.com/bluealloy/revm/pull/1426)) +- Revert "feat: implement EIP-2935 ([#1354](https://github.com/bluealloy/revm/pull/1354))" ([#1424](https://github.com/bluealloy/revm/pull/1424)) +- *(deps)* bump anyhow from 1.0.82 to 1.0.83 ([#1404](https://github.com/bluealloy/revm/pull/1404)) + ## [9.0.0](https://github.com/bluealloy/revm/compare/revm-v8.0.0...revm-v9.0.0) - 2024-05-12 ### Added diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 7ca55cd73b..bae8199148 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -6,7 +6,7 @@ keywords = ["no_std", "ethereum", "evm", "revm"] license = "MIT" name = "revm" repository = "https://github.com/bluealloy/revm" -version = "9.0.0" +version = "10.0.0" readme = "../../README.md" [package.metadata.docs.rs] @@ -23,8 +23,8 @@ all = "warn" [dependencies] # revm -revm-interpreter = { path = "../interpreter", version = "5.0.0", default-features = false } -revm-precompile = { path = "../precompile", version = "7.0.0", default-features = false } +revm-interpreter = { path = "../interpreter", version = "6.0.0", default-features = false } +revm-precompile = { path = "../precompile", version = "8.0.0", default-features = false } # misc auto_impl = { version = "1.2", default-features = false } From 99367b1db2c436359c0155ed8965c19fc5503a1b Mon Sep 17 00:00:00 2001 From: rakita Date: Thu, 20 Jun 2024 19:54:29 +0200 Subject: [PATCH 88/88] release: main Readme (#1555) --- CHANGELOG.md | 53 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd62fd2c56..cd0cee8198 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ Because this is workspace with multi libraries, tags will be simplified, and with this document you can match version of project with git tag. +# v37 tag +date: 20.06.2024 + +Audit of the codebase announced: https://hackmd.io/G7zazTX4TtekCnj6xlgctQ +secp256r1 precompile added. + +Prague changes: +* EOF bugs squashed. +* Introducing PragueEOF hardfork. +* EIP-2935 (blockhashes) modified for devnet-1. +* Fixed for BLS12-381 curve. + +Versions: +* revme: 0.5.0 -> 0.6.0 +* revm: 9.0.0 -> 10.0.0 +* revm-interpreter: 5.0.0 -> 6.0.0 +* revm-primitives: 4.0.0 -> 5.0.0 +* revm-precompile: 7.0.0 -> 8.0.0 + # v36 tag date: 12.05.2024 @@ -10,35 +29,35 @@ Support for prague EIPs. EOF removed BytecodeLocked, OpCode table got changed, and CallInputs got refactored. -revme: 0.4.0 -> 0.5.0 (⚠️ API breaking changes) -revm: 8.0.0 -> 9.0.0 (⚠️ API breaking changes) -revm-interpreter: 4.0.0 -> 5.0.0 (⚠️ API breaking changes) -revm-primitives: 3.1.1 -> 4.0.0 (⚠️ API breaking changes) -revm-precompile: 6.0.0 -> 7.0.0 (⚠️ API breaking changes) -revm-test: 0.1.0 +* revme: 0.4.0 -> 0.5.0 (⚠️ API breaking changes) +* revm: 8.0.0 -> 9.0.0 (⚠️ API breaking changes) +* revm-interpreter: 4.0.0 -> 5.0.0 (⚠️ API breaking changes) +* revm-primitives: 3.1.1 -> 4.0.0 (⚠️ API breaking changes) +* revm-precompile: 6.0.0 -> 7.0.0 (⚠️ API breaking changes) +* revm-test: 0.1.0 # v35 tag date: 02.04.2024 Small release. Alloy bump. Small refactors and deprecated functions removed. -revme: 0.3.1 -> 0.4.0 (✓ API compatible changes) -revm: 7.2.0 -> 8.0.0 (⚠️ API breaking changes) -revm-interpreter: 3.4.0 -> 4.0.0 (⚠️ API breaking changes) -revm-primitives: 3.1.0 -> 3.1.1 (✓ API compatible changes) -revm-precompile: 5.1.0 -> 6.0.0 (⚠️ API breaking changes) -revm-test: 0.1.0 +* revme: 0.3.1 -> 0.4.0 (✓ API compatible changes) +* revm: 7.2.0 -> 8.0.0 (⚠️ API breaking changes) +* revm-interpreter: 3.4.0 -> 4.0.0 (⚠️ API breaking changes) +* revm-primitives: 3.1.0 -> 3.1.1 (✓ API compatible changes) +* revm-precompile: 5.1.0 -> 6.0.0 (⚠️ API breaking changes) +* revm-test: 0.1.0 # v34 tag date: 20.03.2024 Small release, few utilities and refactoring, precompiles fn and Interpreter helper macros are made public. -revme: 0.3.0 -> 0.3.1 (✓ API compatible changes) -revm: 7.1.0 -> 7.2.0 (✓ API compatible changes) -revm-interpreter: 3.3.0 -> 3.4.0 (✓ API compatible changes) -revm-primitives: 3.0.0 -> 3.1.0 (✓ API compatible changes) -revm-precompile: 5.0.0 -> 5.1.0 (✓ API compatible changes) +* revme: 0.3.0 -> 0.3.1 (✓ API compatible changes) +* revm: 7.1.0 -> 7.2.0 (✓ API compatible changes) +* revm-interpreter: 3.3.0 -> 3.4.0 (✓ API compatible changes) +* revm-primitives: 3.0.0 -> 3.1.0 (✓ API compatible changes) +* revm-precompile: 5.0.0 -> 5.1.0 (✓ API compatible changes) # v33 tag TODO