mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 02:49:55 +00:00
remove: use default implementations, remove HlEvmHandler (this might be added later)
This commit is contained in:
@ -98,10 +98,4 @@ where
|
|||||||
INSP: Inspector<CTX, EthInterpreter>,
|
INSP: Inspector<CTX, EthInterpreter>,
|
||||||
PRECOMPILE: PrecompileProvider<CTX, Output = InterpreterResult>,
|
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
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,122 +1 @@
|
|||||||
//! 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, 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> {
|
|
||||||
self.mainnet.validate_initial_tx_gas(evm)
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
// used gas with refund calculated.
|
|
||||||
let gas_refunded = 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;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -56,107 +56,4 @@ where
|
|||||||
fn max_simulate_blocks(&self) -> u64 {
|
fn max_simulate_blocks(&self) -> u64 {
|
||||||
self.inner.eth_api.max_simulate_blocks()
|
self.inner.eth_api.max_simulate_blocks()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_txn_env(
|
|
||||||
&self,
|
|
||||||
evm_env: &EvmEnv<SpecFor<Self::Evm>>,
|
|
||||||
request: TransactionRequest,
|
|
||||||
mut db: impl Database<Error: Into<EthApiError>>,
|
|
||||||
) -> Result<HlTxEnv<TxEnv>, Self::Error> {
|
|
||||||
// Ensure that if versioned hashes are set, they're not empty
|
|
||||||
if request.blob_versioned_hashes.as_ref().is_some_and(|hashes| hashes.is_empty()) {
|
|
||||||
return Err(RpcInvalidTransactionError::BlobTransactionMissingBlobHashes.into_eth_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
let tx_type = if request.authorization_list.is_some() {
|
|
||||||
TxType::Eip7702
|
|
||||||
} else if request.sidecar.is_some() || request.max_fee_per_blob_gas.is_some() {
|
|
||||||
TxType::Eip4844
|
|
||||||
} else if request.max_fee_per_gas.is_some() || request.max_priority_fee_per_gas.is_some() {
|
|
||||||
TxType::Eip1559
|
|
||||||
} else if request.access_list.is_some() {
|
|
||||||
TxType::Eip2930
|
|
||||||
} else {
|
|
||||||
TxType::Legacy
|
|
||||||
} as u8;
|
|
||||||
|
|
||||||
let TransactionRequest {
|
|
||||||
from,
|
|
||||||
to,
|
|
||||||
gas_price,
|
|
||||||
max_fee_per_gas,
|
|
||||||
max_priority_fee_per_gas,
|
|
||||||
gas,
|
|
||||||
value,
|
|
||||||
input,
|
|
||||||
nonce,
|
|
||||||
access_list,
|
|
||||||
chain_id,
|
|
||||||
blob_versioned_hashes,
|
|
||||||
max_fee_per_blob_gas,
|
|
||||||
authorization_list,
|
|
||||||
transaction_type: _,
|
|
||||||
sidecar: _,
|
|
||||||
} = request;
|
|
||||||
|
|
||||||
let CallFees { max_priority_fee_per_gas, gas_price, max_fee_per_blob_gas } =
|
|
||||||
CallFees::ensure_fees(
|
|
||||||
gas_price.map(U256::from),
|
|
||||||
max_fee_per_gas.map(U256::from),
|
|
||||||
max_priority_fee_per_gas.map(U256::from),
|
|
||||||
U256::from(evm_env.block_env.basefee),
|
|
||||||
blob_versioned_hashes.as_deref(),
|
|
||||||
max_fee_per_blob_gas.map(U256::from),
|
|
||||||
evm_env.block_env.blob_gasprice().map(U256::from),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let gas_limit = gas.unwrap_or(
|
|
||||||
// Use maximum allowed gas limit. The reason for this
|
|
||||||
// is that both Erigon and Geth use pre-configured gas cap even if
|
|
||||||
// it's possible to derive the gas limit from the block:
|
|
||||||
// <https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/cmd/rpcdaemon/commands/trace_adhoc.go#L956
|
|
||||||
// https://github.com/ledgerwatch/erigon/blob/eae2d9a79cb70dbe30b3a6b79c436872e4605458/eth/ethconfig/config.go#L94>
|
|
||||||
evm_env.block_env.gas_limit,
|
|
||||||
);
|
|
||||||
|
|
||||||
let chain_id = chain_id.unwrap_or(evm_env.cfg_env.chain_id);
|
|
||||||
|
|
||||||
let caller = from.unwrap_or_default();
|
|
||||||
|
|
||||||
let nonce = if let Some(nonce) = nonce {
|
|
||||||
nonce
|
|
||||||
} else {
|
|
||||||
db.basic(caller).map_err(Into::into)?.map(|acc| acc.nonce).unwrap_or_default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let env = TxEnv {
|
|
||||||
tx_type,
|
|
||||||
gas_limit,
|
|
||||||
nonce,
|
|
||||||
caller,
|
|
||||||
gas_price: gas_price.saturating_to(),
|
|
||||||
gas_priority_fee: max_priority_fee_per_gas.map(|v| v.saturating_to()),
|
|
||||||
kind: to.unwrap_or(TxKind::Create),
|
|
||||||
value: value.unwrap_or_default(),
|
|
||||||
data: input
|
|
||||||
.try_into_unique_input()
|
|
||||||
.map_err(Self::Error::from_eth_err)?
|
|
||||||
.unwrap_or_default(),
|
|
||||||
chain_id: Some(chain_id),
|
|
||||||
access_list: access_list.unwrap_or_default(),
|
|
||||||
// EIP-4844 fields
|
|
||||||
blob_hashes: blob_versioned_hashes.unwrap_or_default(),
|
|
||||||
max_fee_per_blob_gas: max_fee_per_blob_gas
|
|
||||||
.map(|v| v.saturating_to())
|
|
||||||
.unwrap_or_default(),
|
|
||||||
// EIP-7702 fields
|
|
||||||
authorization_list: authorization_list
|
|
||||||
.unwrap_or_default()
|
|
||||||
.into_iter()
|
|
||||||
.map(Either::Left)
|
|
||||||
.collect(),
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(HlTxEnv::new(env))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user