From 389be74aaca78ec2ebb5eca5c46a4d3204aa9d82 Mon Sep 17 00:00:00 2001 From: rakita Date: Fri, 7 Mar 2025 20:04:01 +0100 Subject: [PATCH] chore: op-revm cleanup and few docs (#2156) --- crates/handler/src/mainnet_builder.rs | 4 +- crates/optimism/src/api/builder.rs | 13 +- crates/optimism/src/api/default_ctx.rs | 26 +-- crates/optimism/src/api/exec.rs | 122 +++++------- crates/optimism/src/bn128.rs | 80 -------- crates/optimism/src/evm.rs | 3 +- crates/optimism/src/handler.rs | 23 +-- crates/optimism/src/handler/precompiles.rs | 126 ------------- crates/optimism/src/lib.rs | 6 +- crates/optimism/src/precompiles.rs | 209 +++++++++++++++++++++ crates/optimism/src/transaction/deposit.rs | 4 + 11 files changed, 285 insertions(+), 331 deletions(-) delete mode 100644 crates/optimism/src/bn128.rs delete mode 100644 crates/optimism/src/handler/precompiles.rs create mode 100644 crates/optimism/src/precompiles.rs diff --git a/crates/handler/src/mainnet_builder.rs b/crates/handler/src/mainnet_builder.rs index 8e712518e4..dc6c66f938 100644 --- a/crates/handler/src/mainnet_builder.rs +++ b/crates/handler/src/mainnet_builder.rs @@ -1,5 +1,5 @@ use crate::{instructions::EthInstructions, EthPrecompiles}; -use context::{BlockEnv, Cfg, CfgEnv, Context, Evm, EvmData, Journal, JournalOutput, TxEnv}; +use context::{BlockEnv, Cfg, CfgEnv, Context, Evm, EvmData, Journal, TxEnv}; use context_interface::{Block, Database, JournalTr, Transaction}; use database_interface::EmptyDB; use interpreter::interpreter::EthInterpreter; @@ -23,7 +23,7 @@ where TX: Transaction, CFG: Cfg, DB: Database, - JOURNAL: JournalTr, + JOURNAL: JournalTr, { type Context = Self; diff --git a/crates/optimism/src/api/builder.rs b/crates/optimism/src/api/builder.rs index 74ce1e3cb0..20c980ee08 100644 --- a/crates/optimism/src/api/builder.rs +++ b/crates/optimism/src/api/builder.rs @@ -1,17 +1,21 @@ -use crate::{evm::OpEvm, transaction::OpTxTr, L1BlockInfo, OpSpecId, OpTransaction}; +use crate::{evm::OpEvm, transaction::OpTxTr, L1BlockInfo, OpSpecId}; use revm::{ - context::{BlockEnv, Cfg, CfgEnv, JournalOutput, TxEnv}, + context::{Cfg, JournalOutput}, context_interface::{Block, JournalTr}, handler::instructions::EthInstructions, interpreter::interpreter::EthInterpreter, - Context, Database, Journal, + Context, Database, }; +/// Trait that allows for optimism OpEvm to be built. pub trait OpBuilder: Sized { + /// Type of the context. type Context; + /// Build the op. fn build_op(self) -> OpEvm>; + /// Build the op with an inspector. fn build_op_with_inspector( self, inspector: INSP, @@ -39,6 +43,3 @@ where OpEvm::new(self, inspector) } } - -pub type OpContext = - Context, CfgEnv, DB, Journal, L1BlockInfo>; diff --git a/crates/optimism/src/api/default_ctx.rs b/crates/optimism/src/api/default_ctx.rs index 024d160e99..b3690f0a82 100644 --- a/crates/optimism/src/api/default_ctx.rs +++ b/crates/optimism/src/api/default_ctx.rs @@ -5,27 +5,17 @@ use revm::{ Context, Journal, MainContext, }; +/// Type alias for the default context type of the OpEvm. +pub type OpContext = + Context, CfgEnv, DB, Journal, L1BlockInfo>; + +/// Trait that allows for a default context to be created. pub trait DefaultOp { - fn op() -> Context< - BlockEnv, - OpTransaction, - CfgEnv, - EmptyDB, - Journal, - L1BlockInfo, - >; + /// Create a default context. + fn op() -> OpContext; } -impl DefaultOp - for Context< - BlockEnv, - OpTransaction, - CfgEnv, - EmptyDB, - Journal, - L1BlockInfo, - > -{ +impl DefaultOp for OpContext { fn op() -> Self { Context::mainnet() .with_tx(OpTransaction::default()) diff --git a/crates/optimism/src/api/exec.rs b/crates/optimism/src/api/exec.rs index 0782f12345..7ae0d340f1 100644 --- a/crates/optimism/src/api/exec.rs +++ b/crates/optimism/src/api/exec.rs @@ -3,37 +3,48 @@ use crate::{ OpTransactionError, }; use revm::{ - context::JournalOutput, + context::{setters::ContextSetters, JournalOutput}, context_interface::{ result::{EVMError, ExecutionResult, ResultAndState}, - Block, Cfg, ContextTr, Database, JournalTr, + Cfg, ContextTr, Database, JournalTr, }, handler::{instructions::EthInstructions, EthFrame, EvmTr, Handler, PrecompileProvider}, inspector::{InspectCommitEvm, InspectEvm, Inspector, JournalExt}, interpreter::{interpreter::EthInterpreter, InterpreterResult}, - Context, DatabaseCommit, ExecuteCommitEvm, ExecuteEvm, + DatabaseCommit, ExecuteCommitEvm, ExecuteEvm, }; -impl ExecuteEvm - for OpEvm< - Context, - INSP, - EthInstructions>, - PRECOMPILE, - > +// Type alias for Optimism context +pub trait OpContextTr: + ContextTr< + Journal: JournalTr, + Tx: OpTxTr, + Cfg: Cfg, + Chain = L1BlockInfo, + > + ContextSetters +{ +} + +impl OpContextTr for T where + T: ContextTr< + Journal: JournalTr, + Tx: OpTxTr, + Cfg: Cfg, + Chain = L1BlockInfo, + > + ContextSetters +{ +} + +/// Type alias for the error type of the OpEvm. +type OpError = EVMError<<::Db as Database>::Error, OpTransactionError>; + +impl ExecuteEvm + for OpEvm, PRECOMPILE> where - BLOCK: Block, - TX: OpTxTr, - CFG: Cfg, - DB: Database, - JOURNAL: JournalTr, - PRECOMPILE: PrecompileProvider< - Context = Context, - Output = InterpreterResult, - >, + CTX: OpContextTr, + PRECOMPILE: PrecompileProvider, { - type Output = - Result, EVMError<::Error, OpTransactionError>>; + type Output = Result, OpError>; fn replay(&mut self) -> Self::Output { let mut h = OpHandler::<_, _, EthFrame<_, _, _>>::new(); @@ -41,28 +52,13 @@ where } } -impl ExecuteCommitEvm - for OpEvm< - Context, - INSP, - EthInstructions>, - PRECOMPILE, - > +impl ExecuteCommitEvm + for OpEvm, PRECOMPILE> where - BLOCK: Block, - TX: OpTxTr, - CFG: Cfg, - DB: Database + DatabaseCommit, - JOURNAL: JournalTr + JournalExt, - PRECOMPILE: PrecompileProvider< - Context = Context, - Output = InterpreterResult, - >, + CTX: OpContextTr, + PRECOMPILE: PrecompileProvider, { - type CommitOutput = Result< - ExecutionResult, - EVMError<::Error, OpTransactionError>, - >; + type CommitOutput = Result, OpError>; fn replay_commit(&mut self) -> Self::CommitOutput { self.replay().map(|r| { @@ -72,24 +68,12 @@ where } } -impl InspectEvm - for OpEvm< - Context, - INSP, - EthInstructions>, - PRECOMPILE, - > +impl InspectEvm + for OpEvm, PRECOMPILE> where - BLOCK: Block, - TX: OpTxTr, - CFG: Cfg, - DB: Database, - JOURNAL: JournalTr + JournalExt, - INSP: Inspector, EthInterpreter>, - PRECOMPILE: PrecompileProvider< - Context = Context, - Output = InterpreterResult, - >, + CTX: OpContextTr, + INSP: Inspector, + PRECOMPILE: PrecompileProvider, { type Inspector = INSP; @@ -103,24 +87,12 @@ where } } -impl InspectCommitEvm - for OpEvm< - Context, - INSP, - EthInstructions>, - PRECOMPILE, - > +impl InspectCommitEvm + for OpEvm, PRECOMPILE> where - BLOCK: Block, - TX: OpTxTr, - CFG: Cfg, - DB: Database + DatabaseCommit, - JOURNAL: JournalTr + JournalExt, - INSP: Inspector, EthInterpreter>, - PRECOMPILE: PrecompileProvider< - Context = Context, - Output = InterpreterResult, - >, + CTX: OpContextTr, + INSP: Inspector, + PRECOMPILE: PrecompileProvider, { fn inspect_commit_previous(&mut self) -> Self::CommitOutput { self.inspect_previous().map(|r| { diff --git a/crates/optimism/src/bn128.rs b/crates/optimism/src/bn128.rs deleted file mode 100644 index 8bdd40f139..0000000000 --- a/crates/optimism/src/bn128.rs +++ /dev/null @@ -1,80 +0,0 @@ -use revm::precompile::{ - bn128, {PrecompileError, PrecompileResult, PrecompileWithAddress}, -}; - -pub mod pair { - use super::*; - - pub const GRANITE_MAX_INPUT_SIZE: usize = 112687; - pub const GRANITE: PrecompileWithAddress = - PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit| { - run_pair(input, gas_limit) - }); - - pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { - if input.len() > GRANITE_MAX_INPUT_SIZE { - return Err(PrecompileError::Bn128PairLength); - } - bn128::run_pair( - input, - bn128::pair::ISTANBUL_PAIR_PER_POINT, - bn128::pair::ISTANBUL_PAIR_BASE, - gas_limit, - ) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use revm::{precompile::PrecompileError, primitives::hex}; - use std::vec; - - #[test] - fn test_bn128_pair() { - let input = hex::decode( - "\ - 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ - 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ - 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ - 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ - 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ - 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ - 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ - 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ - 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ - 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ - 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ - 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", - ) - .unwrap(); - let expected = - hex::decode("0000000000000000000000000000000000000000000000000000000000000001") - .unwrap(); - let outcome = pair::run_pair(&input, 260_000).unwrap(); - assert_eq!(outcome.bytes, expected); - - // Invalid input length - let input = hex::decode( - "\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 1111111111111111111111111111111111111111111111111111111111111111\ - 111111111111111111111111111111\ - ", - ) - .unwrap(); - - let res = pair::run_pair(&input, 260_000); - assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); - - // Valid input length shorter than 112687 - let input = vec![1u8; 586 * bn128::PAIR_ELEMENT_LEN]; - let res = pair::run_pair(&input, 260_000); - assert!(matches!(res, Err(PrecompileError::OutOfGas))); - - // Input length longer than 112687 - let input = vec![1u8; 587 * bn128::PAIR_ELEMENT_LEN]; - let res = pair::run_pair(&input, 260_000); - assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); - } -} diff --git a/crates/optimism/src/evm.rs b/crates/optimism/src/evm.rs index 3d0f014f95..a08fcfa1d1 100644 --- a/crates/optimism/src/evm.rs +++ b/crates/optimism/src/evm.rs @@ -1,3 +1,4 @@ +use crate::precompiles::OpPrecompileProvider; use revm::{ context::{setters::ContextSetters, Evm, EvmData}, context_interface::ContextTr, @@ -10,8 +11,6 @@ use revm::{ }, }; -use crate::handler::precompiles::OpPrecompileProvider; - pub struct OpEvm, P = OpPrecompileProvider>( pub Evm, ); diff --git a/crates/optimism/src/handler.rs b/crates/optimism/src/handler.rs index 77b93af7f1..8f5e1d2d28 100644 --- a/crates/optimism/src/handler.rs +++ b/crates/optimism/src/handler.rs @@ -1,8 +1,6 @@ //!Handler related to Optimism chain - -pub mod precompiles; - use crate::{ + api::exec::OpContextTr, constants::{BASE_FEE_RECIPIENT, L1_FEE_RECIPIENT, OPERATOR_FEE_RECIPIENT}, transaction::{ deposit::{DepositTransaction, DEPOSIT_TRANSACTION_TYPE}, @@ -11,7 +9,6 @@ use crate::{ L1BlockInfo, OpHaltReason, OpSpecId, }; use revm::{ - context::JournalOutput, context_interface::{ result::{EVMError, ExecutionResult, FromStringError, ResultAndState}, Block, Cfg, ContextTr, JournalTr, Transaction, @@ -60,14 +57,7 @@ impl IsTxError for EVMError { impl Handler for OpHandler where - EVM: EvmTr< - Context: ContextTr< - Journal: JournalTr, - Tx: OpTxTr, - Cfg: Cfg, - Chain = L1BlockInfo, - >, - >, + EVM: EvmTr, ERROR: EvmTrError + From + FromStringError + IsTxError, // TODO `FrameResult` should be a generic trait. // TODO `FrameInit` should be a generic. @@ -461,12 +451,7 @@ where impl InspectorHandler for OpHandler where EVM: InspectorEvmTr< - Context: ContextTr< - Journal: JournalTr, - Tx: OpTxTr, - Cfg: Cfg, - Chain = L1BlockInfo, - >, + Context: OpContextTr, Inspector: Inspector<<::Evm as EvmTr>::Context, EthInterpreter>, >, ERROR: EvmTrError + From + FromStringError + IsTxError, @@ -486,7 +471,7 @@ where #[cfg(test)] mod tests { use super::*; - use crate::{DefaultOp, OpBuilder, OpContext}; + use crate::{api::default_ctx::OpContext, DefaultOp, OpBuilder}; use revm::{ context::Context, context_interface::result::InvalidTransaction, diff --git a/crates/optimism/src/handler/precompiles.rs b/crates/optimism/src/handler/precompiles.rs deleted file mode 100644 index a872810795..0000000000 --- a/crates/optimism/src/handler/precompiles.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::OpSpecId; -use once_cell::race::OnceBox; -use revm::{ - context::Cfg, - context_interface::ContextTr, - handler::{EthPrecompiles, PrecompileProvider}, - interpreter::InterpreterResult, - precompile::{self, secp256r1, PrecompileError, Precompiles}, -}; -use std::boxed::Box; - -pub struct OpPrecompileProvider { - precompile_provider: EthPrecompiles, -} - -impl Clone for OpPrecompileProvider { - fn clone(&self) -> Self { - Self { - precompile_provider: self.precompile_provider.clone(), - } - } -} - -impl OpPrecompileProvider { - pub fn new(precompiles: &'static Precompiles) -> Self { - Self { - precompile_provider: EthPrecompiles { - precompiles, - _phantom: core::marker::PhantomData, - }, - } - } - - #[inline] - pub fn new_with_spec(spec: OpSpecId) -> Self { - match spec { - spec @ (OpSpecId::BEDROCK - | OpSpecId::REGOLITH - | OpSpecId::CANYON - | OpSpecId::ECOTONE) => Self::new(Precompiles::new(spec.into_eth_spec().into())), - OpSpecId::FJORD => Self::new(fjord()), - OpSpecId::GRANITE | OpSpecId::HOLOCENE => Self::new(granite()), - OpSpecId::ISTHMUS | OpSpecId::INTEROP | OpSpecId::OSAKA => Self::new(isthumus()), - } - } -} - -/// Returns precompiles for Fjor spec. -pub fn fjord() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); - INSTANCE.get_or_init(|| { - let mut precompiles = Precompiles::cancun().clone(); - // EIP-7212: secp256r1 P256verify - precompiles.extend([crate::bn128::pair::GRANITE]); - Box::new(precompiles) - }) -} - -/// Returns precompiles for Granite spec. -pub fn granite() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); - INSTANCE.get_or_init(|| { - let mut precompiles = Precompiles::cancun().clone(); - // Restrict bn256Pairing input size - precompiles.extend([secp256r1::P256VERIFY]); - Box::new(precompiles) - }) -} - -/// Returns precompiles for isthumus spec. -pub fn isthumus() -> &'static Precompiles { - static INSTANCE: OnceBox = OnceBox::new(); - INSTANCE.get_or_init(|| { - let precompiles = granite().clone(); - // Prague bls12 precompiles - // Don't include BLS12-381 precompiles in no_std builds. - #[cfg(feature = "blst")] - let precompiles = { - let mut precompiles = precompiles; - precompiles.extend(precompile::bls12_381::precompiles()); - precompiles - }; - Box::new(precompiles) - }) -} - -impl PrecompileProvider for OpPrecompileProvider -where - CTX: ContextTr>, -{ - type Context = CTX; - type Output = InterpreterResult; - - #[inline] - fn set_spec(&mut self, spec: <::Cfg as Cfg>::Spec) { - *self = Self::new_with_spec(spec); - } - - #[inline] - fn run( - &mut self, - context: &mut Self::Context, - address: &precompile::Address, - bytes: &precompile::Bytes, - gas_limit: u64, - ) -> Result, PrecompileError> { - self.precompile_provider - .run(context, address, bytes, gas_limit) - } - - #[inline] - fn warm_addresses(&self) -> Box + '_> { - self.precompile_provider.warm_addresses() - } - - #[inline] - fn contains(&self, address: &precompile::Address) -> bool { - self.precompile_provider.contains(address) - } -} - -impl Default for OpPrecompileProvider { - fn default() -> Self { - Self::new_with_spec(OpSpecId::ISTHMUS) - } -} diff --git a/crates/optimism/src/lib.rs b/crates/optimism/src/lib.rs index ec5209c116..485d5adc17 100644 --- a/crates/optimism/src/lib.rs +++ b/crates/optimism/src/lib.rs @@ -6,19 +6,19 @@ extern crate alloc as std; pub mod api; -pub mod bn128; pub mod constants; pub mod evm; pub mod fast_lz; pub mod handler; pub mod l1block; +pub mod precompiles; pub mod result; pub mod spec; pub mod transaction; pub use api::{ - builder::{OpBuilder, OpContext}, - default_ctx::DefaultOp, + builder::OpBuilder, + default_ctx::{DefaultOp, OpContext}, }; pub use evm::OpEvm; pub use l1block::L1BlockInfo; diff --git a/crates/optimism/src/precompiles.rs b/crates/optimism/src/precompiles.rs new file mode 100644 index 0000000000..8dd9913f52 --- /dev/null +++ b/crates/optimism/src/precompiles.rs @@ -0,0 +1,209 @@ +use crate::OpSpecId; +use once_cell::race::OnceBox; +use revm::{ + context::Cfg, + context_interface::ContextTr, + handler::{EthPrecompiles, PrecompileProvider}, + interpreter::InterpreterResult, + precompile::{ + self, bn128, secp256r1, PrecompileError, Precompiles, + {PrecompileResult, PrecompileWithAddress}, + }, +}; +use std::boxed::Box; + +// Optimism precompile provider +pub struct OpPrecompileProvider { + /// Inner precompile provider is same as Ethereums. + inner: EthPrecompiles, +} + +impl Clone for OpPrecompileProvider { + fn clone(&self) -> Self { + Self { + inner: self.inner.clone(), + } + } +} + +impl OpPrecompileProvider { + /// Create a new [`OpPrecompileProvider`] with the given precompiles. + pub fn new(precompiles: &'static Precompiles) -> Self { + Self { + inner: EthPrecompiles { + precompiles, + _phantom: core::marker::PhantomData, + }, + } + } + + /// Create a new precompile provider with the given optimismispec. + #[inline] + pub fn new_with_spec(spec: OpSpecId) -> Self { + match spec { + spec @ (OpSpecId::BEDROCK + | OpSpecId::REGOLITH + | OpSpecId::CANYON + | OpSpecId::ECOTONE) => Self::new(Precompiles::new(spec.into_eth_spec().into())), + OpSpecId::FJORD => Self::new(fjord()), + OpSpecId::GRANITE | OpSpecId::HOLOCENE => Self::new(granite()), + OpSpecId::ISTHMUS | OpSpecId::INTEROP | OpSpecId::OSAKA => Self::new(isthumus()), + } + } +} + +/// Returns precompiles for Fjor spec. +pub fn fjord() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::cancun().clone(); + // EIP-7212: secp256r1 P256verify + precompiles.extend([bn128_pair::GRANITE]); + Box::new(precompiles) + }) +} + +/// Returns precompiles for Granite spec. +pub fn granite() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let mut precompiles = Precompiles::cancun().clone(); + // Restrict bn256Pairing input size + precompiles.extend([secp256r1::P256VERIFY]); + Box::new(precompiles) + }) +} + +/// Returns precompiles for isthumus spec. +pub fn isthumus() -> &'static Precompiles { + static INSTANCE: OnceBox = OnceBox::new(); + INSTANCE.get_or_init(|| { + let precompiles = granite().clone(); + // Prague bls12 precompiles + // Don't include BLS12-381 precompiles in no_std builds. + #[cfg(feature = "blst")] + let precompiles = { + let mut precompiles = precompiles; + precompiles.extend(precompile::bls12_381::precompiles()); + precompiles + }; + Box::new(precompiles) + }) +} + +impl PrecompileProvider for OpPrecompileProvider +where + CTX: ContextTr>, +{ + type Context = CTX; + type Output = InterpreterResult; + + #[inline] + fn set_spec(&mut self, spec: <::Cfg as Cfg>::Spec) { + *self = Self::new_with_spec(spec); + } + + #[inline] + fn run( + &mut self, + context: &mut Self::Context, + address: &precompile::Address, + bytes: &precompile::Bytes, + gas_limit: u64, + ) -> Result, PrecompileError> { + self.inner.run(context, address, bytes, gas_limit) + } + + #[inline] + fn warm_addresses(&self) -> Box + '_> { + self.inner.warm_addresses() + } + + #[inline] + fn contains(&self, address: &precompile::Address) -> bool { + self.inner.contains(address) + } +} + +impl Default for OpPrecompileProvider { + fn default() -> Self { + Self::new_with_spec(OpSpecId::ISTHMUS) + } +} + +pub mod bn128_pair { + use super::*; + + pub const GRANITE_MAX_INPUT_SIZE: usize = 112687; + pub const GRANITE: PrecompileWithAddress = + PrecompileWithAddress(bn128::pair::ADDRESS, |input, gas_limit| { + run_pair(input, gas_limit) + }); + + pub fn run_pair(input: &[u8], gas_limit: u64) -> PrecompileResult { + if input.len() > GRANITE_MAX_INPUT_SIZE { + return Err(PrecompileError::Bn128PairLength); + } + bn128::run_pair( + input, + bn128::pair::ISTANBUL_PAIR_PER_POINT, + bn128::pair::ISTANBUL_PAIR_BASE, + gas_limit, + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use revm::{precompile::PrecompileError, primitives::hex}; + use std::vec; + + #[test] + fn test_bn128_pair() { + let input = hex::decode( + "\ + 1c76476f4def4bb94541d57ebba1193381ffa7aa76ada664dd31c16024c43f59\ + 3034dd2920f673e204fee2811c678745fc819b55d3e9d294e45c9b03a76aef41\ + 209dd15ebff5d46c4bd888e51a93cf99a7329636c63514396b4a452003a35bf7\ + 04bf11ca01483bfa8b34b43561848d28905960114c8ac04049af4b6315a41678\ + 2bb8324af6cfc93537a2ad1a445cfd0ca2a71acd7ac41fadbf933c2a51be344d\ + 120a2a4cf30c1bf9845f20c6fe39e07ea2cce61f0c9bb048165fe5e4de877550\ + 111e129f1cf1097710d41c4ac70fcdfa5ba2023c6ff1cbeac322de49d1b6df7c\ + 2032c61a830e3c17286de9462bf242fca2883585b93870a73853face6a6bf411\ + 198e9393920d483a7260bfb731fb5d25f1aa493335a9e71297e485b7aef312c2\ + 1800deef121f1e76426a00665e5c4479674322d4f75edadd46debd5cd992f6ed\ + 090689d0585ff075ec9e99ad690c3395bc4b313370b38ef355acdadcd122975b\ + 12c85ea5db8c6deb4aab71808dcb408fe3d1e7690c43d37b4ce6cc0166fa7daa", + ) + .unwrap(); + let expected = + hex::decode("0000000000000000000000000000000000000000000000000000000000000001") + .unwrap(); + let outcome = bn128_pair::run_pair(&input, 260_000).unwrap(); + assert_eq!(outcome.bytes, expected); + + // Invalid input length + let input = hex::decode( + "\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 1111111111111111111111111111111111111111111111111111111111111111\ + 111111111111111111111111111111\ + ", + ) + .unwrap(); + + let res = bn128_pair::run_pair(&input, 260_000); + assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); + + // Valid input length shorter than 112687 + let input = vec![1u8; 586 * bn128::PAIR_ELEMENT_LEN]; + let res = bn128_pair::run_pair(&input, 260_000); + assert!(matches!(res, Err(PrecompileError::OutOfGas))); + + // Input length longer than 112687 + let input = vec![1u8; 587 * bn128::PAIR_ELEMENT_LEN]; + let res = bn128_pair::run_pair(&input, 260_000); + assert!(matches!(res, Err(PrecompileError::Bn128PairLength))); + } +} diff --git a/crates/optimism/src/transaction/deposit.rs b/crates/optimism/src/transaction/deposit.rs index 0e0cff3547..b1b38de3af 100644 --- a/crates/optimism/src/transaction/deposit.rs +++ b/crates/optimism/src/transaction/deposit.rs @@ -2,11 +2,15 @@ use revm::primitives::B256; pub const DEPOSIT_TRANSACTION_TYPE: u8 = 0x7E; +/// Deposit transaction trait pub trait DepositTransaction { + /// Source hash of the deposit transaction fn source_hash(&self) -> B256; + /// Mint of the deposit transaction fn mint(&self) -> Option; + /// Whether the transaction is a system transaction fn is_system_transaction(&self) -> bool; }