Port to reth 1.6.0-dev

This commit is contained in:
sprites0
2025-08-21 05:55:48 -04:00
parent 239ee5f8e8
commit 4be1aa83de
24 changed files with 1721 additions and 1749 deletions

View File

@ -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
View 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
}
}