mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Make it compilable (still bunch to fix!)
This commit is contained in:
39
src/evm/api/builder.rs
Normal file
39
src/evm/api/builder.rs
Normal file
@ -0,0 +1,39 @@
|
||||
use super::HlEvmInner;
|
||||
use crate::evm::{spec::HlSpecId, transaction::HlTxTr};
|
||||
use revm::{
|
||||
context::{Cfg, JournalOutput},
|
||||
context_interface::{Block, JournalTr},
|
||||
handler::instructions::EthInstructions,
|
||||
interpreter::interpreter::EthInterpreter,
|
||||
Context, Database,
|
||||
};
|
||||
|
||||
/// Trait that allows for hl HlEvm to be built.
|
||||
pub trait HlBuilder: Sized {
|
||||
/// Type of the context.
|
||||
type Context;
|
||||
|
||||
/// Build the hl with an inspector.
|
||||
fn build_hl_with_inspector<INSP>(
|
||||
self,
|
||||
inspector: INSP,
|
||||
) -> HlEvmInner<Self::Context, INSP, EthInstructions<EthInterpreter, Self::Context>>;
|
||||
}
|
||||
|
||||
impl<BLOCK, TX, CFG, DB, JOURNAL> HlBuilder for Context<BLOCK, TX, CFG, DB, JOURNAL>
|
||||
where
|
||||
BLOCK: Block,
|
||||
TX: HlTxTr,
|
||||
CFG: Cfg<Spec = HlSpecId>,
|
||||
DB: Database,
|
||||
JOURNAL: JournalTr<Database = DB, FinalOutput = JournalOutput>,
|
||||
{
|
||||
type Context = Self;
|
||||
|
||||
fn build_hl_with_inspector<INSP>(
|
||||
self,
|
||||
inspector: INSP,
|
||||
) -> HlEvmInner<Self::Context, INSP, EthInstructions<EthInterpreter, Self::Context>> {
|
||||
HlEvmInner::new(self, inspector)
|
||||
}
|
||||
}
|
||||
23
src/evm/api/ctx.rs
Normal file
23
src/evm/api/ctx.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::evm::{spec::HlSpecId, transaction::HlTxEnv};
|
||||
use revm::{
|
||||
context::{BlockEnv, CfgEnv, TxEnv},
|
||||
database_interface::EmptyDB,
|
||||
Context, Journal, MainContext,
|
||||
};
|
||||
|
||||
/// Type alias for the default context type of the HlEvm.
|
||||
pub type HlContext<DB> = Context<BlockEnv, HlTxEnv<TxEnv>, CfgEnv<HlSpecId>, DB, Journal<DB>>;
|
||||
|
||||
/// Trait that allows for a default context to be created.
|
||||
pub trait DefaultHl {
|
||||
/// Create a default context.
|
||||
fn hl() -> HlContext<EmptyDB>;
|
||||
}
|
||||
|
||||
impl DefaultHl for HlContext<EmptyDB> {
|
||||
fn hl() -> Self {
|
||||
Context::mainnet()
|
||||
.with_tx(HlTxEnv::default())
|
||||
.with_cfg(CfgEnv::new_with_spec(HlSpecId::default()))
|
||||
}
|
||||
}
|
||||
107
src/evm/api/exec.rs
Normal file
107
src/evm/api/exec.rs
Normal file
@ -0,0 +1,107 @@
|
||||
use super::HlEvmInner;
|
||||
use crate::evm::{handler::HlHandler, spec::HlSpecId, transaction::HlTxTr};
|
||||
use revm::{
|
||||
context::{ContextSetters, JournalOutput},
|
||||
context_interface::{
|
||||
result::{EVMError, ExecutionResult, ResultAndState},
|
||||
Cfg, ContextTr, Database, JournalTr,
|
||||
},
|
||||
handler::{instructions::EthInstructions, EthFrame, EvmTr, Handler, PrecompileProvider},
|
||||
inspector::{InspectCommitEvm, InspectEvm, Inspector, InspectorHandler, JournalExt},
|
||||
interpreter::{interpreter::EthInterpreter, InterpreterResult},
|
||||
DatabaseCommit, ExecuteCommitEvm, ExecuteEvm,
|
||||
};
|
||||
|
||||
// Type alias for HL context
|
||||
pub trait HlContextTr:
|
||||
ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Tx: HlTxTr, Cfg: Cfg<Spec = HlSpecId>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> HlContextTr for T where
|
||||
T: ContextTr<
|
||||
Journal: JournalTr<FinalOutput = JournalOutput>,
|
||||
Tx: HlTxTr,
|
||||
Cfg: Cfg<Spec = HlSpecId>,
|
||||
>
|
||||
{
|
||||
}
|
||||
|
||||
/// Type alias for the error type of the HlEvm.
|
||||
type HlError<CTX> = EVMError<<<CTX as ContextTr>::Db as Database>::Error>;
|
||||
|
||||
impl<CTX, INSP, PRECOMPILE> ExecuteEvm
|
||||
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
|
||||
where
|
||||
CTX: HlContextTr + ContextSetters,
|
||||
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
|
||||
{
|
||||
type Output = Result<ResultAndState, HlError<CTX>>;
|
||||
|
||||
type Tx = <CTX as ContextTr>::Tx;
|
||||
|
||||
type Block = <CTX as ContextTr>::Block;
|
||||
|
||||
fn set_tx(&mut self, tx: Self::Tx) {
|
||||
self.0.ctx.set_tx(tx);
|
||||
}
|
||||
|
||||
fn set_block(&mut self, block: Self::Block) {
|
||||
self.0.ctx.set_block(block);
|
||||
}
|
||||
|
||||
fn replay(&mut self) -> Self::Output {
|
||||
let mut h = HlHandler::<_, _, EthFrame<_, _, _>>::new();
|
||||
h.run(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX, INSP, PRECOMPILE> ExecuteCommitEvm
|
||||
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
|
||||
where
|
||||
CTX: HlContextTr<Db: DatabaseCommit> + ContextSetters,
|
||||
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
|
||||
{
|
||||
type CommitOutput = Result<ExecutionResult, HlError<CTX>>;
|
||||
|
||||
fn replay_commit(&mut self) -> Self::CommitOutput {
|
||||
self.replay().map(|r| {
|
||||
self.ctx().db().commit(r.state);
|
||||
r.result
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX, INSP, PRECOMPILE> InspectEvm
|
||||
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
|
||||
where
|
||||
CTX: HlContextTr<Journal: JournalExt> + ContextSetters,
|
||||
INSP: Inspector<CTX, EthInterpreter>,
|
||||
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
|
||||
{
|
||||
type Inspector = INSP;
|
||||
|
||||
fn set_inspector(&mut self, inspector: Self::Inspector) {
|
||||
self.0.inspector = inspector;
|
||||
}
|
||||
|
||||
fn inspect_replay(&mut self) -> Self::Output {
|
||||
let mut h = HlHandler::<_, _, EthFrame<_, _, _>>::new();
|
||||
h.inspect_run(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX, INSP, PRECOMPILE> InspectCommitEvm
|
||||
for HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, PRECOMPILE>
|
||||
where
|
||||
CTX: HlContextTr<Journal: JournalExt, Db: DatabaseCommit> + ContextSetters,
|
||||
INSP: Inspector<CTX, EthInterpreter>,
|
||||
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
|
||||
{
|
||||
fn inspect_replay_commit(&mut self) -> Self::CommitOutput {
|
||||
self.inspect_replay().map(|r| {
|
||||
self.ctx().db().commit(r.state);
|
||||
r.result
|
||||
})
|
||||
}
|
||||
}
|
||||
134
src/evm/api/mod.rs
Normal file
134
src/evm/api/mod.rs
Normal file
@ -0,0 +1,134 @@
|
||||
use super::precompiles::HlPrecompiles;
|
||||
use revm::{
|
||||
context::{ContextSetters, Evm as EvmCtx},
|
||||
context_interface::ContextTr,
|
||||
handler::{
|
||||
instructions::{EthInstructions, InstructionProvider},
|
||||
EvmTr, PrecompileProvider,
|
||||
},
|
||||
inspector::{InspectorEvmTr, JournalExt},
|
||||
interpreter::{interpreter::EthInterpreter, Interpreter, InterpreterAction, InterpreterTypes},
|
||||
Inspector,
|
||||
};
|
||||
|
||||
pub mod builder;
|
||||
pub mod ctx;
|
||||
mod exec;
|
||||
|
||||
pub struct HlEvmInner<CTX, INSP, I = EthInstructions<EthInterpreter, CTX>, P = HlPrecompiles>(
|
||||
pub EvmCtx<CTX, INSP, I, P>,
|
||||
);
|
||||
|
||||
impl<CTX: ContextTr, INSP>
|
||||
HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, HlPrecompiles>
|
||||
{
|
||||
pub fn new(ctx: CTX, inspector: INSP) -> Self {
|
||||
Self(EvmCtx {
|
||||
ctx,
|
||||
inspector,
|
||||
instruction: EthInstructions::new_mainnet(),
|
||||
precompiles: HlPrecompiles::default(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Consumes self and returns a new Evm type with given Precompiles.
|
||||
pub fn with_precompiles<OP>(
|
||||
self,
|
||||
precompiles: OP,
|
||||
) -> HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, OP> {
|
||||
HlEvmInner(self.0.with_precompiles(precompiles))
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX, INSP, I, P> InspectorEvmTr for HlEvmInner<CTX, INSP, I, P>
|
||||
where
|
||||
CTX: ContextTr<Journal: JournalExt> + ContextSetters,
|
||||
I: InstructionProvider<
|
||||
Context = CTX,
|
||||
InterpreterTypes: InterpreterTypes<Output = InterpreterAction>,
|
||||
>,
|
||||
INSP: Inspector<CTX, I::InterpreterTypes>,
|
||||
P: PrecompileProvider<CTX>,
|
||||
{
|
||||
type Inspector = INSP;
|
||||
|
||||
fn inspector(&mut self) -> &mut Self::Inspector {
|
||||
&mut self.0.inspector
|
||||
}
|
||||
|
||||
fn ctx_inspector(&mut self) -> (&mut Self::Context, &mut Self::Inspector) {
|
||||
(&mut self.0.ctx, &mut self.0.inspector)
|
||||
}
|
||||
|
||||
fn run_inspect_interpreter(
|
||||
&mut self,
|
||||
interpreter: &mut Interpreter<
|
||||
<Self::Instructions as InstructionProvider>::InterpreterTypes,
|
||||
>,
|
||||
) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output
|
||||
{
|
||||
self.0.run_inspect_interpreter(interpreter)
|
||||
}
|
||||
}
|
||||
|
||||
impl<CTX, INSP, I, P> EvmTr for HlEvmInner<CTX, INSP, I, P>
|
||||
where
|
||||
CTX: ContextTr,
|
||||
I: InstructionProvider<
|
||||
Context = CTX,
|
||||
InterpreterTypes: InterpreterTypes<Output = InterpreterAction>,
|
||||
>,
|
||||
P: PrecompileProvider<CTX>,
|
||||
{
|
||||
type Context = CTX;
|
||||
type Instructions = I;
|
||||
type Precompiles = P;
|
||||
|
||||
fn run_interpreter(
|
||||
&mut self,
|
||||
interpreter: &mut Interpreter<
|
||||
<Self::Instructions as InstructionProvider>::InterpreterTypes,
|
||||
>,
|
||||
) -> <<Self::Instructions as InstructionProvider>::InterpreterTypes as InterpreterTypes>::Output
|
||||
{
|
||||
let context = &mut self.0.ctx;
|
||||
let instructions = &mut self.0.instruction;
|
||||
interpreter.run_plain(instructions.instruction_table(), context)
|
||||
}
|
||||
|
||||
fn ctx(&mut self) -> &mut Self::Context {
|
||||
&mut self.0.ctx
|
||||
}
|
||||
|
||||
fn ctx_ref(&self) -> &Self::Context {
|
||||
&self.0.ctx
|
||||
}
|
||||
|
||||
fn ctx_instructions(&mut self) -> (&mut Self::Context, &mut Self::Instructions) {
|
||||
(&mut self.0.ctx, &mut self.0.instruction)
|
||||
}
|
||||
|
||||
fn ctx_precompiles(&mut self) -> (&mut Self::Context, &mut Self::Precompiles) {
|
||||
(&mut self.0.ctx, &mut self.0.precompiles)
|
||||
}
|
||||
}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod test {
|
||||
// use super::{builder::HlBuilder, ctx::DefaultHl};
|
||||
// use revm::{
|
||||
// inspector::{InspectEvm, NoOpInspector},
|
||||
// Context, ExecuteEvm,
|
||||
// };
|
||||
|
||||
// #[test]
|
||||
// fn default_run_bsc() {
|
||||
// let ctx = Context::bsc();
|
||||
// let mut evm = ctx.build_bsc_with_inspector(NoOpInspector {});
|
||||
|
||||
// // execute
|
||||
// let _ = evm.replay();
|
||||
// // inspect
|
||||
// let _ = evm.inspect_replay();
|
||||
// }
|
||||
// }
|
||||
148
src/evm/handler.rs
Normal file
148
src/evm/handler.rs
Normal file
@ -0,0 +1,148 @@
|
||||
//! EVM Handler related to Hl chain
|
||||
|
||||
use super::{spec::HlSpecId, transaction::HlTxTr};
|
||||
use revm::{
|
||||
context::{
|
||||
result::{ExecutionResult, HaltReason},
|
||||
Cfg, ContextTr, JournalOutput, LocalContextTr,
|
||||
},
|
||||
context_interface::{result::ResultAndState, JournalTr},
|
||||
handler::{handler::EvmTrError, EvmTr, Frame, FrameResult, Handler, MainnetHandler},
|
||||
inspector::{Inspector, InspectorEvmTr, InspectorFrame, InspectorHandler},
|
||||
interpreter::{interpreter::EthInterpreter, FrameInput, InitialAndFloorGas, SuccessOrHalt},
|
||||
};
|
||||
|
||||
pub struct HlHandler<EVM, ERROR, FRAME> {
|
||||
pub mainnet: MainnetHandler<EVM, ERROR, FRAME>,
|
||||
}
|
||||
|
||||
impl<EVM, ERROR, FRAME> HlHandler<EVM, ERROR, FRAME> {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
mainnet: MainnetHandler::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<EVM, ERROR, FRAME> Default for HlHandler<EVM, ERROR, FRAME> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
pub trait HlContextTr:
|
||||
ContextTr<Journal: JournalTr<FinalOutput = JournalOutput>, Tx: HlTxTr, Cfg: Cfg<Spec = HlSpecId>>
|
||||
{
|
||||
}
|
||||
|
||||
impl<T> HlContextTr for T where
|
||||
T: ContextTr<
|
||||
Journal: JournalTr<FinalOutput = JournalOutput>,
|
||||
Tx: HlTxTr,
|
||||
Cfg: Cfg<Spec = HlSpecId>,
|
||||
>
|
||||
{
|
||||
}
|
||||
|
||||
impl<EVM, ERROR, FRAME> Handler for HlHandler<EVM, ERROR, FRAME>
|
||||
where
|
||||
EVM: EvmTr<Context: HlContextTr>,
|
||||
ERROR: EvmTrError<EVM>,
|
||||
FRAME: Frame<Evm = EVM, Error = ERROR, FrameResult = FrameResult, FrameInit = FrameInput>,
|
||||
{
|
||||
type Evm = EVM;
|
||||
type Error = ERROR;
|
||||
type Frame = FRAME;
|
||||
type HaltReason = HaltReason;
|
||||
|
||||
fn validate_initial_tx_gas(
|
||||
&self,
|
||||
evm: &Self::Evm,
|
||||
) -> Result<revm::interpreter::InitialAndFloorGas, Self::Error> {
|
||||
let ctx = evm.ctx_ref();
|
||||
let tx = ctx.tx();
|
||||
|
||||
if tx.is_system_transaction() {
|
||||
return Ok(InitialAndFloorGas {
|
||||
initial_gas: 0,
|
||||
floor_gas: 0,
|
||||
});
|
||||
}
|
||||
|
||||
self.mainnet.validate_initial_tx_gas(evm)
|
||||
}
|
||||
|
||||
fn reward_beneficiary(
|
||||
&self,
|
||||
evm: &mut Self::Evm,
|
||||
exec_result: &mut <Self::Frame as Frame>::FrameResult,
|
||||
) -> Result<(), Self::Error> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn output(
|
||||
&self,
|
||||
evm: &mut Self::Evm,
|
||||
result: <Self::Frame as Frame>::FrameResult,
|
||||
) -> Result<ResultAndState<Self::HaltReason>, Self::Error> {
|
||||
let ctx = evm.ctx();
|
||||
ctx.error();
|
||||
let tx = ctx.tx();
|
||||
// used gas with refund calculated.
|
||||
let gas_refunded = if tx.is_system_transaction() {
|
||||
0
|
||||
} else {
|
||||
result.gas().refunded() as u64
|
||||
};
|
||||
let final_gas_used = result.gas().spent() - gas_refunded;
|
||||
let output = result.output();
|
||||
let instruction_result = result.into_interpreter_result();
|
||||
|
||||
// Reset journal and return present state.
|
||||
let JournalOutput { state, logs } = evm.ctx().journal().finalize();
|
||||
|
||||
let result = match SuccessOrHalt::from(instruction_result.result) {
|
||||
SuccessOrHalt::Success(reason) => ExecutionResult::Success {
|
||||
reason,
|
||||
gas_used: final_gas_used,
|
||||
gas_refunded,
|
||||
logs,
|
||||
output,
|
||||
},
|
||||
SuccessOrHalt::Revert => ExecutionResult::Revert {
|
||||
gas_used: final_gas_used,
|
||||
output: output.into_data(),
|
||||
},
|
||||
SuccessOrHalt::Halt(reason) => ExecutionResult::Halt {
|
||||
reason,
|
||||
gas_used: final_gas_used,
|
||||
},
|
||||
// Only two internal return flags.
|
||||
flag @ (SuccessOrHalt::FatalExternalError | SuccessOrHalt::Internal(_)) => {
|
||||
panic!(
|
||||
"Encountered unexpected internal return flag: {flag:?} with instruction result: {instruction_result:?}"
|
||||
)
|
||||
}
|
||||
};
|
||||
|
||||
// Clear local context
|
||||
evm.ctx().local().clear();
|
||||
// Clear journal
|
||||
evm.ctx().journal().clear();
|
||||
|
||||
Ok(ResultAndState { result, state })
|
||||
}
|
||||
}
|
||||
|
||||
impl<EVM, ERROR, FRAME> InspectorHandler for HlHandler<EVM, ERROR, FRAME>
|
||||
where
|
||||
EVM: InspectorEvmTr<
|
||||
Context: HlContextTr,
|
||||
Inspector: Inspector<<<Self as Handler>::Evm as EvmTr>::Context, EthInterpreter>,
|
||||
>,
|
||||
ERROR: EvmTrError<EVM>,
|
||||
FRAME: Frame<Evm = EVM, Error = ERROR, FrameResult = FrameResult, FrameInit = FrameInput>
|
||||
+ InspectorFrame<IT = EthInterpreter>,
|
||||
{
|
||||
type IT = EthInterpreter;
|
||||
}
|
||||
5
src/evm/mod.rs
Normal file
5
src/evm/mod.rs
Normal file
@ -0,0 +1,5 @@
|
||||
pub mod api;
|
||||
mod handler;
|
||||
pub mod precompiles;
|
||||
pub mod spec;
|
||||
pub mod transaction;
|
||||
87
src/evm/precompiles.rs
Normal file
87
src/evm/precompiles.rs
Normal file
@ -0,0 +1,87 @@
|
||||
#![allow(unused)]
|
||||
|
||||
use super::spec::HlSpecId;
|
||||
use cfg_if::cfg_if;
|
||||
use once_cell::{race::OnceBox, sync::Lazy};
|
||||
use revm::{
|
||||
context::Cfg,
|
||||
context_interface::ContextTr,
|
||||
handler::{EthPrecompiles, PrecompileProvider},
|
||||
interpreter::{InputsImpl, InterpreterResult},
|
||||
precompile::{bls12_381, kzg_point_evaluation, modexp, secp256r1, Precompiles},
|
||||
primitives::{hardfork::SpecId, Address},
|
||||
};
|
||||
use std::boxed::Box;
|
||||
|
||||
// HL precompile provider
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct HlPrecompiles {
|
||||
/// Inner precompile provider is same as Ethereums.
|
||||
inner: EthPrecompiles,
|
||||
}
|
||||
|
||||
impl HlPrecompiles {
|
||||
/// Create a new precompile provider with the given hl spec.
|
||||
#[inline]
|
||||
pub fn new(spec: HlSpecId) -> Self {
|
||||
let precompiles = cancun();
|
||||
|
||||
Self { inner: EthPrecompiles { precompiles, spec: spec.into_eth_spec() } }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn precompiles(&self) -> &'static Precompiles {
|
||||
self.inner.precompiles
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns precompiles for Istanbul spec.
|
||||
pub fn cancun() -> &'static Precompiles {
|
||||
static INSTANCE: OnceBox<Precompiles> = OnceBox::new();
|
||||
INSTANCE.get_or_init(|| {
|
||||
let mut precompiles = Precompiles::cancun().clone();
|
||||
// precompiles.extend([tendermint::TENDERMINT_HEADER_VALIDATION, iavl::IAVL_PROOF_VALIDATION]);
|
||||
Box::new(precompiles)
|
||||
})
|
||||
}
|
||||
|
||||
impl<CTX> PrecompileProvider<CTX> for HlPrecompiles
|
||||
where
|
||||
CTX: ContextTr<Cfg: Cfg<Spec = HlSpecId>>,
|
||||
{
|
||||
type Output = InterpreterResult;
|
||||
|
||||
#[inline]
|
||||
fn set_spec(&mut self, spec: <CTX::Cfg as Cfg>::Spec) -> bool {
|
||||
*self = Self::new(spec);
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn run(
|
||||
&mut self,
|
||||
context: &mut CTX,
|
||||
address: &Address,
|
||||
inputs: &InputsImpl,
|
||||
is_static: bool,
|
||||
gas_limit: u64,
|
||||
) -> Result<Option<Self::Output>, String> {
|
||||
self.inner.run(context, address, inputs, is_static, gas_limit)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn warm_addresses(&self) -> Box<impl Iterator<Item = Address>> {
|
||||
self.inner.warm_addresses()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn contains(&self, address: &Address) -> bool {
|
||||
self.inner.contains(address)
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HlPrecompiles {
|
||||
fn default() -> Self {
|
||||
Self::new(HlSpecId::default())
|
||||
}
|
||||
}
|
||||
55
src/evm/spec.rs
Normal file
55
src/evm/spec.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use revm::primitives::hardfork::SpecId;
|
||||
use std::str::FromStr;
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[allow(non_camel_case_types)]
|
||||
#[allow(clippy::upper_case_acronyms)]
|
||||
pub enum HlSpecId {
|
||||
#[default]
|
||||
V1, // V1
|
||||
}
|
||||
|
||||
impl HlSpecId {
|
||||
pub const fn is_enabled_in(self, other: HlSpecId) -> bool {
|
||||
other as u8 <= self as u8
|
||||
}
|
||||
|
||||
/// Converts the [`HlSpecId`] into a [`SpecId`].
|
||||
pub const fn into_eth_spec(self) -> SpecId {
|
||||
match self {
|
||||
Self::V1 => SpecId::CANCUN,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HlSpecId> for SpecId {
|
||||
fn from(spec: HlSpecId) -> Self {
|
||||
spec.into_eth_spec()
|
||||
}
|
||||
}
|
||||
|
||||
/// String identifiers for HL hardforks
|
||||
pub mod name {
|
||||
pub const V1: &str = "V1";
|
||||
}
|
||||
|
||||
impl FromStr for HlSpecId {
|
||||
type Err = String;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Ok(match s {
|
||||
name::V1 => Self::V1,
|
||||
_ => return Err(format!("Unknown HL spec: {s}")),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HlSpecId> for &'static str {
|
||||
fn from(spec_id: HlSpecId) -> Self {
|
||||
match spec_id {
|
||||
HlSpecId::V1 => name::V1,
|
||||
}
|
||||
}
|
||||
}
|
||||
203
src/evm/transaction.rs
Normal file
203
src/evm/transaction.rs
Normal file
@ -0,0 +1,203 @@
|
||||
use alloy_consensus::Transaction as AlloyTransaction;
|
||||
use alloy_rpc_types::AccessList;
|
||||
use auto_impl::auto_impl;
|
||||
use reth_evm::{FromRecoveredTx, FromTxWithEncoded, IntoTxEnv, TransactionEnv};
|
||||
use reth_primitives::TransactionSigned;
|
||||
use revm::{
|
||||
context::TxEnv,
|
||||
context_interface::transaction::Transaction,
|
||||
primitives::{Address, Bytes, TxKind, B256, U256},
|
||||
};
|
||||
|
||||
#[auto_impl(&, &mut, Box, Arc)]
|
||||
pub trait HlTxTr: Transaction {
|
||||
/// Whether the transaction is a system transaction
|
||||
fn is_system_transaction(&self) -> bool;
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct HlTxEnv<T: Transaction> {
|
||||
pub base: T,
|
||||
pub is_system_transaction: bool,
|
||||
}
|
||||
|
||||
impl<T: Transaction> HlTxEnv<T> {
|
||||
pub fn new(base: T) -> Self {
|
||||
Self {
|
||||
base,
|
||||
is_system_transaction: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for HlTxEnv<TxEnv> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
base: TxEnv::default(),
|
||||
is_system_transaction: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transaction> Transaction for HlTxEnv<T> {
|
||||
type AccessListItem<'a>
|
||||
= T::AccessListItem<'a>
|
||||
where
|
||||
T: 'a;
|
||||
type Authorization<'a>
|
||||
= T::Authorization<'a>
|
||||
where
|
||||
T: 'a;
|
||||
|
||||
fn tx_type(&self) -> u8 {
|
||||
self.base.tx_type()
|
||||
}
|
||||
|
||||
fn caller(&self) -> Address {
|
||||
self.base.caller()
|
||||
}
|
||||
|
||||
fn gas_limit(&self) -> u64 {
|
||||
self.base.gas_limit()
|
||||
}
|
||||
|
||||
fn value(&self) -> U256 {
|
||||
self.base.value()
|
||||
}
|
||||
|
||||
fn input(&self) -> &Bytes {
|
||||
self.base.input()
|
||||
}
|
||||
|
||||
fn nonce(&self) -> u64 {
|
||||
self.base.nonce()
|
||||
}
|
||||
|
||||
fn kind(&self) -> TxKind {
|
||||
self.base.kind()
|
||||
}
|
||||
|
||||
fn chain_id(&self) -> Option<u64> {
|
||||
self.base.chain_id()
|
||||
}
|
||||
|
||||
fn gas_price(&self) -> u128 {
|
||||
self.base.gas_price()
|
||||
}
|
||||
|
||||
fn access_list(&self) -> Option<impl Iterator<Item = Self::AccessListItem<'_>>> {
|
||||
self.base.access_list()
|
||||
}
|
||||
|
||||
fn blob_versioned_hashes(&self) -> &[B256] {
|
||||
self.base.blob_versioned_hashes()
|
||||
}
|
||||
|
||||
fn max_fee_per_blob_gas(&self) -> u128 {
|
||||
self.base.max_fee_per_blob_gas()
|
||||
}
|
||||
|
||||
fn authorization_list_len(&self) -> usize {
|
||||
self.base.authorization_list_len()
|
||||
}
|
||||
|
||||
fn authorization_list(&self) -> impl Iterator<Item = Self::Authorization<'_>> {
|
||||
self.base.authorization_list()
|
||||
}
|
||||
|
||||
fn max_fee_per_gas(&self) -> u128 {
|
||||
self.base.max_fee_per_gas()
|
||||
}
|
||||
|
||||
fn max_priority_fee_per_gas(&self) -> Option<u128> {
|
||||
self.base.max_priority_fee_per_gas()
|
||||
}
|
||||
|
||||
fn effective_gas_price(&self, base_fee: u128) -> u128 {
|
||||
self.base.effective_gas_price(base_fee)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Transaction> HlTxTr for HlTxEnv<T> {
|
||||
fn is_system_transaction(&self) -> bool {
|
||||
self.is_system_transaction
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: revm::context::Transaction> IntoTxEnv<Self> for HlTxEnv<T> {
|
||||
fn into_tx_env(self) -> Self {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRecoveredTx<TransactionSigned> for HlTxEnv<TxEnv> {
|
||||
fn from_recovered_tx(tx: &TransactionSigned, sender: Address) -> Self {
|
||||
Self::new(TxEnv::from_recovered_tx(tx, sender))
|
||||
}
|
||||
}
|
||||
|
||||
impl FromTxWithEncoded<TransactionSigned> for HlTxEnv<TxEnv> {
|
||||
fn from_encoded_tx(tx: &TransactionSigned, sender: Address, _encoded: Bytes) -> Self {
|
||||
let base = match tx.clone().into_typed_transaction() {
|
||||
reth_primitives::Transaction::Legacy(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||
reth_primitives::Transaction::Eip2930(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||
reth_primitives::Transaction::Eip1559(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||
reth_primitives::Transaction::Eip4844(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||
reth_primitives::Transaction::Eip7702(tx) => TxEnv::from_recovered_tx(&tx, sender),
|
||||
};
|
||||
|
||||
let is_system_transaction = match tx.gas_price() {
|
||||
Some(x) => x == 0u128,
|
||||
None => false,
|
||||
};
|
||||
|
||||
Self {
|
||||
base,
|
||||
is_system_transaction
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: TransactionEnv> TransactionEnv for HlTxEnv<T> {
|
||||
fn set_gas_limit(&mut self, gas_limit: u64) {
|
||||
self.base.set_gas_limit(gas_limit);
|
||||
}
|
||||
|
||||
fn nonce(&self) -> u64 {
|
||||
TransactionEnv::nonce(&self.base)
|
||||
}
|
||||
|
||||
fn set_nonce(&mut self, nonce: u64) {
|
||||
self.base.set_nonce(nonce);
|
||||
}
|
||||
|
||||
fn set_access_list(&mut self, access_list: AccessList) {
|
||||
self.base.set_access_list(access_list);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use revm::primitives::Address;
|
||||
|
||||
#[test]
|
||||
fn test_hl_transaction_fields() {
|
||||
let hl_tx = HlTxEnv {
|
||||
base: TxEnv {
|
||||
tx_type: 0,
|
||||
gas_limit: 10,
|
||||
gas_price: 100,
|
||||
gas_priority_fee: Some(5),
|
||||
..Default::default()
|
||||
},
|
||||
is_system_transaction: false,
|
||||
};
|
||||
|
||||
assert_eq!(hl_tx.tx_type(), 0);
|
||||
assert_eq!(hl_tx.gas_limit(), 10);
|
||||
assert_eq!(hl_tx.kind(), revm::primitives::TxKind::Call(Address::ZERO));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user