mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
Port to reth 1.6.0-dev
This commit is contained in:
@ -1,4 +1,5 @@
|
||||
use revm::{
|
||||
bytecode::opcode::BLOCKHASH,
|
||||
context::{ContextSetters, Evm, FrameStack},
|
||||
context_interface::ContextTr,
|
||||
handler::{
|
||||
@ -7,13 +8,14 @@ use revm::{
|
||||
EthFrame, EthPrecompiles, EvmTr, FrameInitOrResult, FrameTr, PrecompileProvider,
|
||||
},
|
||||
inspector::{InspectorEvmTr, JournalExt},
|
||||
interpreter::{interpreter::EthInterpreter, InterpreterResult},
|
||||
interpreter::{interpreter::EthInterpreter, Instruction, InterpreterResult},
|
||||
Inspector,
|
||||
};
|
||||
|
||||
pub mod builder;
|
||||
pub mod ctx;
|
||||
mod exec;
|
||||
mod patch;
|
||||
|
||||
pub struct HlEvmInner<
|
||||
CTX: ContextTr,
|
||||
@ -26,10 +28,20 @@ impl<CTX: ContextTr, INSP>
|
||||
HlEvmInner<CTX, INSP, EthInstructions<EthInterpreter, CTX>, EthPrecompiles>
|
||||
{
|
||||
pub fn new(ctx: CTX, inspector: INSP) -> Self {
|
||||
let mut instruction = EthInstructions::new_mainnet();
|
||||
|
||||
const NON_PLACEHOLDER_BLOCK_HASH_HEIGHT: u64 = 243_538;
|
||||
if ctx.chain_id() == 999 && ctx.block_number() < NON_PLACEHOLDER_BLOCK_HASH_HEIGHT {
|
||||
instruction.insert_instruction(
|
||||
BLOCKHASH,
|
||||
Instruction::new(patch::blockhash_returning_placeholder, 20),
|
||||
);
|
||||
}
|
||||
|
||||
Self(Evm {
|
||||
ctx,
|
||||
inspector,
|
||||
instruction: EthInstructions::new_mainnet(),
|
||||
instruction,
|
||||
precompiles: EthPrecompiles::default(),
|
||||
frame_stack: FrameStack::new(),
|
||||
})
|
||||
@ -125,23 +137,3 @@ where
|
||||
self.0.frame_return_result(result)
|
||||
}
|
||||
}
|
||||
|
||||
// #[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();
|
||||
// }
|
||||
// }
|
||||
|
||||
71
src/evm/api/patch.rs
Normal file
71
src/evm/api/patch.rs
Normal file
@ -0,0 +1,71 @@
|
||||
//! Modified version of `blockhash` instruction before block `243538`.
|
||||
//!
|
||||
//! This is a mainnet-specific fix for the `blockhash` instruction,
|
||||
//! copied and modified from revm-interpreter-25.0.1/src/instructions/host.rs.
|
||||
|
||||
use alloy_primitives::keccak256;
|
||||
use revm::{
|
||||
context::Host,
|
||||
interpreter::{
|
||||
as_u64_saturated, interpreter_types::StackTr, popn_top, InstructionContext,
|
||||
InterpreterTypes,
|
||||
},
|
||||
primitives::{BLOCK_HASH_HISTORY, U256},
|
||||
};
|
||||
|
||||
#[doc(hidden)]
|
||||
#[macro_export]
|
||||
#[collapse_debuginfo(yes)]
|
||||
macro_rules! _count {
|
||||
(@count) => { 0 };
|
||||
(@count $head:tt $($tail:tt)*) => { 1 + _count!(@count $($tail)*) };
|
||||
($($arg:tt)*) => { _count!(@count $($arg)*) };
|
||||
}
|
||||
|
||||
/// Pops n values from the stack and returns the top value. Fails the instruction if n values can't be popped.
|
||||
#[macro_export]
|
||||
#[collapse_debuginfo(yes)]
|
||||
macro_rules! popn_top {
|
||||
([ $($x:ident),* ], $top:ident, $interpreter:expr $(,$ret:expr)? ) => {
|
||||
// Workaround for https://github.com/rust-lang/rust/issues/144329.
|
||||
if $interpreter.stack.len() < (1 + $crate::_count!($($x)*)) {
|
||||
$interpreter.halt_underflow();
|
||||
return $($ret)?;
|
||||
}
|
||||
let ([$( $x ),*], $top) = unsafe { $interpreter.stack.popn_top().unwrap_unchecked() };
|
||||
};
|
||||
}
|
||||
|
||||
/// Implements the BLOCKHASH instruction.
|
||||
///
|
||||
/// Gets the hash of one of the 256 most recent complete blocks.
|
||||
pub fn blockhash_returning_placeholder<WIRE: InterpreterTypes, H: Host + ?Sized>(
|
||||
context: InstructionContext<'_, H, WIRE>,
|
||||
) {
|
||||
//gas!(context.interpreter, gas::BLOCKHASH);
|
||||
popn_top!([], number, context.interpreter);
|
||||
|
||||
let requested_number = *number;
|
||||
let block_number = context.host.block_number();
|
||||
|
||||
let Some(diff) = block_number.checked_sub(requested_number) else {
|
||||
*number = U256::ZERO;
|
||||
return;
|
||||
};
|
||||
|
||||
let diff = as_u64_saturated!(diff);
|
||||
|
||||
// blockhash should push zero if number is same as current block number.
|
||||
if diff == 0 {
|
||||
*number = U256::ZERO;
|
||||
return;
|
||||
}
|
||||
|
||||
*number = if diff <= BLOCK_HASH_HISTORY {
|
||||
// NOTE: This is HL-specific modifcation that returns the placeholder hash before specific block.
|
||||
let hash = keccak256(as_u64_saturated!(requested_number).to_string().as_bytes());
|
||||
U256::from_be_bytes(hash.0)
|
||||
} else {
|
||||
U256::ZERO
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user