1use self::state::trie_storage;
4use crate::{
5 config::PruneStateHistoryConfig,
6 eth::{
7 backend::{
8 cheats::CheatsManager,
9 db::{Db, MaybeFullDatabase, SerializableState},
10 env::Env,
11 executor::{ExecutedTransactions, TransactionExecutor},
12 fork::ClientFork,
13 genesis::GenesisConfig,
14 mem::{
15 state::{storage_root, trie_accounts},
16 storage::MinedTransactionReceipt,
17 },
18 notifications::{NewBlockNotification, NewBlockNotifications},
19 time::{utc_from_secs, TimeManager},
20 validate::TransactionValidator,
21 },
22 error::{BlockchainError, ErrDetail, InvalidTransactionError},
23 fees::{FeeDetails, FeeManager, MIN_SUGGESTED_PRIORITY_FEE},
24 macros::node_info,
25 pool::transactions::PoolTransaction,
26 sign::build_typed_transaction,
27 util::get_precompiles_for,
28 },
29 inject_precompiles,
30 mem::{
31 inspector::AnvilInspector,
32 storage::{BlockchainStorage, InMemoryBlockStates, MinedBlockOutcome},
33 },
34 ForkChoice, NodeConfig, PrecompileFactory,
35};
36use alloy_chains::NamedChain;
37use alloy_consensus::{
38 proofs::{calculate_receipt_root, calculate_transaction_root},
39 transaction::Recovered,
40 Account, BlockHeader, EnvKzgSettings, Header, Receipt, ReceiptWithBloom, Signed,
41 Transaction as TransactionTrait, TxEnvelope,
42};
43use alloy_eips::{
44 eip1559::BaseFeeParams,
45 eip2718::{
46 EIP1559_TX_TYPE_ID, EIP2930_TX_TYPE_ID, EIP4844_TX_TYPE_ID, EIP7702_TX_TYPE_ID,
47 LEGACY_TX_TYPE_ID,
48 },
49 eip7840::BlobParams,
50};
51use alloy_evm::{eth::EthEvmContext, precompiles::PrecompilesMap, Database, Evm};
52use alloy_network::{
53 AnyHeader, AnyRpcBlock, AnyRpcHeader, AnyRpcTransaction, AnyTxEnvelope, AnyTxType,
54 EthereumWallet, UnknownTxEnvelope, UnknownTypedTransaction,
55};
56use alloy_primitives::{
57 address, hex, keccak256, logs_bloom, map::HashMap, utils::Unit, Address, Bytes, TxHash, TxKind,
58 B256, U256, U64,
59};
60use alloy_rpc_types::{
61 anvil::Forking,
62 request::TransactionRequest,
63 serde_helpers::JsonStorageKey,
64 simulate::{SimBlock, SimCallResult, SimulatePayload, SimulatedBlock},
65 state::EvmOverrides,
66 trace::{
67 filter::TraceFilter,
68 geth::{
69 GethDebugBuiltInTracerType, GethDebugTracerType, GethDebugTracingCallOptions,
70 GethDebugTracingOptions, GethTrace, NoopFrame,
71 },
72 parity::LocalizedTransactionTrace,
73 },
74 AccessList, Block as AlloyBlock, BlockId, BlockNumberOrTag as BlockNumber, BlockTransactions,
75 EIP1186AccountProofResponse as AccountProof, EIP1186StorageProof as StorageProof, Filter,
76 Header as AlloyHeader, Index, Log, Transaction, TransactionReceipt,
77};
78use alloy_serde::{OtherFields, WithOtherFields};
79use alloy_signer::Signature;
80use alloy_signer_local::PrivateKeySigner;
81use alloy_trie::{proof::ProofRetainer, HashBuilder, Nibbles};
82use anvil_core::eth::{
83 block::{Block, BlockInfo},
84 transaction::{
85 has_optimism_fields, transaction_request_to_typed, DepositReceipt,
86 MaybeImpersonatedTransaction, PendingTransaction, ReceiptResponse, TransactionInfo,
87 TypedReceipt, TypedTransaction,
88 },
89 wallet::{Capabilities, DelegationCapability, WalletCapabilities},
90};
91use anvil_rpc::error::RpcError;
92use chrono::Datelike;
93use eyre::{Context, Result};
94use flate2::{read::GzDecoder, write::GzEncoder, Compression};
95use foundry_evm::{
96 backend::{DatabaseError, DatabaseResult, RevertStateSnapshotAction},
97 constants::DEFAULT_CREATE2_DEPLOYER_RUNTIME_CODE,
98 decode::RevertDecoder,
99 inspectors::AccessListInspector,
100 traces::TracingInspectorConfig,
101};
102use foundry_evm_core::either_evm::EitherEvm;
103use futures::channel::mpsc::{unbounded, UnboundedSender};
104use op_alloy_consensus::DEPOSIT_TX_TYPE_ID;
105use op_revm::{
106 transaction::deposit::DepositTransactionParts, OpContext, OpHaltReason, OpTransaction,
107};
108use parking_lot::{Mutex, RwLock};
109use revm::{
110 context::{Block as RevmBlock, BlockEnv, TxEnv},
111 context_interface::{
112 block::BlobExcessGasAndPrice,
113 result::{ExecutionResult, Output, ResultAndState},
114 },
115 database::{CacheDB, DatabaseRef, WrapDatabaseRef},
116 interpreter::InstructionResult,
117 precompile::secp256r1::P256VERIFY,
118 primitives::{hardfork::SpecId, KECCAK_EMPTY},
119 state::AccountInfo,
120 DatabaseCommit, Inspector,
121};
122use revm_inspectors::transfer::TransferInspector;
123use std::{
124 collections::BTreeMap,
125 io::{Read, Write},
126 ops::Not,
127 path::PathBuf,
128 sync::Arc,
129 time::Duration,
130};
131use storage::{Blockchain, MinedTransaction, DEFAULT_HISTORY_LIMIT};
132use tokio::sync::RwLock as AsyncRwLock;
133
134use super::executor::new_evm_with_inspector_ref;
135
136pub mod cache;
137pub mod fork_db;
138pub mod in_memory_db;
139pub mod inspector;
140pub mod state;
141pub mod storage;
142
143pub const MIN_TRANSACTION_GAS: u128 = 21000;
145pub const MIN_CREATE_GAS: u128 = 53000;
147pub const EXECUTOR: Address = address!("0x6634F723546eCc92277e8a2F93d4f248bf1189ea");
149pub const EXECUTOR_PK: &str = "0x502d47e1421cb9abef497096728e69f07543232b93ef24de4998e18b5fd9ba0f";
150pub const P256_DELEGATION_CONTRACT: Address =
152 address!("0x35202a6e6317f3cc3a177eeee562d3bcda4a6fcc");
153pub const P256_DELEGATION_RUNTIME_CODE: &[u8] = &hex!("60806040526004361015610018575b361561001657005b005b5f3560e01c806309c5eabe146100c75780630cb6aaf1146100c257806330f6a8e5146100bd5780635fce1927146100b8578063641cdfe2146100b357806376ba882d146100ae5780638d80ff0a146100a9578063972ce4bc146100a4578063a78fc2441461009f578063a82e44e01461009a5763b34893910361000e576108e1565b6108b5565b610786565b610646565b6105ba565b610529565b6103f8565b6103a2565b61034c565b6102c0565b61020b565b634e487b7160e01b5f52604160045260245ffd5b6040810190811067ffffffffffffffff8211176100fc57604052565b6100cc565b6080810190811067ffffffffffffffff8211176100fc57604052565b60a0810190811067ffffffffffffffff8211176100fc57604052565b90601f8019910116810190811067ffffffffffffffff8211176100fc57604052565b6040519061016a608083610139565b565b67ffffffffffffffff81116100fc57601f01601f191660200190565b9291926101948261016c565b916101a26040519384610139565b8294818452818301116101be578281602093845f960137010152565b5f80fd5b9080601f830112156101be578160206101dd93359101610188565b90565b60206003198201126101be576004359067ffffffffffffffff82116101be576101dd916004016101c2565b346101be57610219366101e0565b3033036102295761001690610ae6565b636f6a1b8760e11b5f5260045ffd5b634e487b7160e01b5f52603260045260245ffd5b5f54811015610284575f8080526005919091027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5630191565b610238565b8054821015610284575f52600560205f20910201905f90565b906040516102af816100e0565b602060018294805484520154910152565b346101be5760203660031901126101be576004355f548110156101be576102e69061024c565b5060ff815416600182015491610306600360ff60028401541692016102a2565b926040519215158352602083015260028110156103385760a09260209160408401528051606084015201516080820152f35b634e487b7160e01b5f52602160045260245ffd5b346101be575f3660031901126101be576020600254604051908152f35b6004359063ffffffff821682036101be57565b6064359063ffffffff821682036101be57565b6084359063ffffffff821682036101be57565b346101be5760203660031901126101be576103bb610369565b303303610229576103cb9061024c565b50805460ff19169055005b60609060231901126101be57602490565b60609060831901126101be57608490565b346101be5760803660031901126101be57610411610369565b60205f61041d366103d6565b60015461043161042c82610a0b565b600155565b60405184810191825260e086901b6001600160e01b031916602083015261046581602484015b03601f198101835282610139565b51902060ff61047660408401610a19565b161583146104fe576104b2601b925b85813591013590604051948594859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156104f9575f51306001600160a01b03909116036104ea576104df6100169161024c565b50805460ff19169055565b638baa579f60e01b5f5260045ffd5b610a27565b6104b2601c92610485565b60409060031901126101be57600490565b6044359060028210156101be57565b346101be5760803660031901126101be5761054336610509565b61054b61051a565b606435903033036102295761059192610580610587926040519461056e86610101565b60018652602086015260408501610a32565b36906105f3565b6060820152610a3e565b5f545f1981019081116105b55760405163ffffffff919091168152602090f35b0390f35b6109f7565b6100166105c6366101e0565b610ae6565b60409060231901126101be57604051906105e4826100e0565b60243582526044356020830152565b91908260409103126101be5760405161060b816100e0565b6020808294803584520135910152565b6084359081151582036101be57565b60a4359081151582036101be57565b359081151582036101be57565b346101be5760a03660031901126101be5760043567ffffffffffffffff81116101be576106779036906004016101c2565b610680366105cb565b61068861037c565b61069061061b565b906002546106a56106a082610a0b565b600255565b6040516106bb8161045788602083019586610b6a565b51902091610747575b6106d06106d69161024c565b50610b7b565b906106e86106e48351151590565b1590565b610738576020820151801515908161072e575b5061071f576107129260606106e493015191610ce3565b6104ea5761001690610ae6565b632572e3a960e01b5f5260045ffd5b905042115f6106fb565b637dd286d760e11b5f5260045ffd5b905f61077361045761076760209460405192839187830160209181520190565b60405191828092610b58565b039060025afa156104f9575f51906106c4565b346101be5760e03660031901126101be576107a036610509565b6107a861051a565b6064359060205f6107b8366103e7565b6001546107c761042c82610a0b565b60408051808601928352883560208401528589013591830191909152606082018790526107f78160808401610457565b51902060ff61080860408401610a19565b161583146108aa5760408051918252601b602083015282359082015290830135606082015280608081015b838052039060015afa156104f9575f51306001600160a01b03909116036104ea5761087a926105806105879261086761015b565b6001815294602086015260408501610a32565b6105b161089361088a5f54610ad8565b63ffffffff1690565b60405163ffffffff90911681529081906020820190565b610833601c92610485565b346101be575f3660031901126101be576020600154604051908152f35b359061ffff821682036101be57565b346101be5760c03660031901126101be5760043567ffffffffffffffff81116101be576109129036906004016101c2565b61091b366105cb565b906064359167ffffffffffffffff83116101be5760a060031984360301126101be576040516109498161011d565b836004013567ffffffffffffffff81116101be5761096d90600436918701016101c2565b8152602484013567ffffffffffffffff81116101be57840193366023860112156101be5760846109db916109ae610016973690602460048201359101610188565b60208501526109bf604482016108d2565b60408501526109d0606482016108d2565b606085015201610639565b60808201526109e861038f565b916109f161062a565b93610bc3565b634e487b7160e01b5f52601160045260245ffd5b5f1981146105b55760010190565b3560ff811681036101be5790565b6040513d5f823e3d90fd5b60028210156103385752565b5f54680100000000000000008110156100fc57806001610a6192015f555f610289565b610ac557610a7e82511515829060ff801983541691151516179055565b6020820151600182015560028101604083015160028110156103385761016a9360039260609260ff8019835416911617905501519101906020600191805184550151910155565b634e487b7160e01b5f525f60045260245ffd5b5f198101919082116105b557565b80519060205b828110610af857505050565b808201805160f81c600182015160601c91601581015160358201519384915f9493845f14610b4257505050506001146101be575b15610b3a5701605501610aec565b3d5f803e3d5ffd5b5f95508594506055019130811502175af1610b2c565b805191908290602001825e015f815290565b6020906101dd939281520190610b58565b90604051610b8881610101565b6060610bbe6003839560ff8154161515855260018101546020860152610bb860ff60028301541660408701610a32565b016102a2565b910152565b93909192600254610bd66106a082610a0b565b604051610bec8161045789602083019586610b6a565b51902091610c50575b6106d0610c019161024c565b91610c0f6106e48451151590565b6107385760208301518015159081610c46575b5061071f57610c399360606106e494015192610e0d565b6104ea5761016a90610ae6565b905042115f610c22565b905f610c7061045761076760209460405192839187830160209181520190565b039060025afa156104f9575f5190610bf5565b3d15610cad573d90610c948261016c565b91610ca26040519384610139565b82523d5f602084013e565b606090565b8051601f101561028457603f0190565b8051602010156102845760400190565b908151811015610284570160200190565b5f9291839260208251920151906020815191015191604051936020850195865260408501526060840152608083015260a082015260a08152610d2660c082610139565b519060145afa610d34610c83565b81610d74575b81610d43575090565b600160f81b91506001600160f81b031990610d6f90610d6190610cb2565b516001600160f81b03191690565b161490565b80516020149150610d3a565b60405190610d8f604083610139565b6015825274113a3cb832911d113bb2b130baba34371733b2ba1160591b6020830152565b9061016a6001610de3936040519485916c1131b430b63632b733b2911d1160991b6020840152602d830190610b58565b601160f91b815203601e19810185520183610139565b610e069060209392610b58565b9081520190565b92919281516025815110908115610f0a575b50610ef957610e2c610d80565b90610e596106e460208501938451610e53610e4c606089015161ffff1690565b61ffff1690565b91610f9b565b610f01576106e4610e8d610e88610457610e83610ea1956040519283916020830160209181520190565b611012565b610db3565b8351610e53610e4c604088015161ffff1690565b610ef9575f610eb96020925160405191828092610b58565b039060025afa156104f9575f610ee360209261076783519151610457604051938492888401610df9565b039060025afa156104f9576101dd915f51610ce3565b505050505f90565b50505050505f90565b610f2b9150610f1e610d616106e492610cc2565b6080850151151590610f31565b5f610e1f565b906001600160f81b0319600160f81b831601610f955780610f85575b610f8057601f60fb1b600160fb1b821601610f69575b50600190565b600160fc1b90811614610f7c575f610f63565b5f90565b505f90565b50600160fa1b8181161415610f4d565b50505f90565b80519282515f5b858110610fb457505050505050600190565b8083018084116105b5578281101561100757610fe56001600160f81b0319610fdc8488610cd2565b51169187610cd2565b516001600160f81b03191603610ffd57600101610fa2565b5050505050505f90565b505050505050505f90565b80516060929181611021575050565b9092506003600284010460021b604051937f4142434445464748494a4b4c4d4e4f505152535455565758595a616263646566601f527f6768696a6b6c6d6e6f707172737475767778797a303132333435363738392d5f603f52602085019282860191602083019460208284010190600460038351955f85525b0191603f8351818160121c16515f538181600c1c1651600153818160061c165160025316516003535f5181520190878210156110db5760049060039061109a565b5095505f93600393604092520160405206600204809303613d3d60f01b81525203825256fea26469706673582212200ba93b78f286a25ece47e9403c47be9862f9b8b70ba1a95098667b90c47308b064736f6c634300081a0033");
155pub const EXP_ERC20_CONTRACT: Address = address!("0x238c8CD93ee9F8c7Edf395548eF60c0d2e46665E");
157pub const EXP_ERC20_RUNTIME_CODE: &[u8] = &hex!("60806040526004361015610010575b005b5f3560e01c806306fdde03146106f7578063095ea7b31461068c57806318160ddd1461066757806323b872dd146105a15780632bb7c5951461050e578063313ce567146104f35780633644e5151461045557806340c10f191461043057806370a08231146103fe5780637ecebe00146103cc57806395d89b4114610366578063a9059cbb146102ea578063ad0c8fdd146102ad578063d505accf146100fb5763dd62ed3e0361000e57346100f75760403660031901126100f7576100d261075c565b6100da610772565b602052637f5e9f20600c525f5260206034600c2054604051908152f35b5f80fd5b346100f75760e03660031901126100f75761011461075c565b61011c610772565b6084359160643560443560ff851685036100f757610138610788565b60208101906e04578706572696d656e74455243323608c1b8252519020908242116102a0576040519360018060a01b03169460018060a01b03169565383775081901600e52855f5260c06020600c20958654957f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8252602082019586528660408301967fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc688528b6060850198468a528c608087019330855260a08820602e527f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9885252528688525260a082015220604e526042602c205f5260ff1660205260a43560405260c43560605260208060805f60015afa93853d5103610293577f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92594602094019055856303faf4f960a51b176040526034602c2055a3005b63ddafbaef5f526004601cfd5b631a15a3cc5f526004601cfd5b5f3660031901126100f7576103e834023481046103e814341517156102d65761000e90336107ac565b634e487b7160e01b5f52601160045260245ffd5b346100f75760403660031901126100f75761030361075c565b602435906387a211a2600c52335f526020600c2080548084116103595783900390555f526020600c20818154019055602052600c5160601c335f51602061080d5f395f51905f52602080a3602060405160018152f35b63f4d678b85f526004601cfd5b346100f7575f3660031901126100f757604051604081019080821067ffffffffffffffff8311176103b8576103b491604052600381526204558560ec1b602082015260405191829182610732565b0390f35b634e487b7160e01b5f52604160045260245ffd5b346100f75760203660031901126100f7576103e561075c565b6338377508600c525f52602080600c2054604051908152f35b346100f75760203660031901126100f75761041761075c565b6387a211a2600c525f52602080600c2054604051908152f35b346100f75760403660031901126100f75761000e61044c61075c565b602435906107ac565b346100f7575f3660031901126100f757602060a0610471610788565b828101906e04578706572696d656e74455243323608c1b8252519020604051907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8252838201527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6604082015246606082015230608082015220604051908152f35b346100f7575f3660031901126100f757602060405160128152f35b346100f75760203660031901126100f7576004356387a211a2600c52335f526020600c2090815490818111610359575f80806103e88487839688039055806805345cdf77eb68f44c54036805345cdf77eb68f44c5580835282335f51602061080d5f395f51905f52602083a304818115610598575b3390f11561058d57005b6040513d5f823e3d90fd5b506108fc610583565b346100f75760603660031901126100f7576105ba61075c565b6105c2610772565b604435908260601b33602052637f5e9f208117600c526034600c20908154918219610643575b506387a211a2915017600c526020600c2080548084116103595783900390555f526020600c20818154019055602052600c5160601c9060018060a01b03165f51602061080d5f395f51905f52602080a3602060405160018152f35b82851161065a57846387a211a293039055856105e8565b6313be252b5f526004601cfd5b346100f7575f3660031901126100f75760206805345cdf77eb68f44c54604051908152f35b346100f75760403660031901126100f7576106a561075c565b60243590602052637f5e9f20600c52335f52806034600c20555f52602c5160601c337f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560205fa3602060405160018152f35b346100f7575f3660031901126100f7576103b4610712610788565b6e04578706572696d656e74455243323608c1b6020820152604051918291825b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b03821682036100f757565b602435906001600160a01b03821682036100f757565b604051906040820182811067ffffffffffffffff8211176103b857604052600f8252565b6805345cdf77eb68f44c548281019081106107ff576805345cdf77eb68f44c556387a211a2600c525f526020600c20818154019055602052600c5160601c5f5f51602061080d5f395f51905f52602080a3565b63e5cfe9575f526004601cfdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220fbe302881d9891005ba1448ba48547cc1cb17dea1a5c4011dfcb035de325bb1d64736f6c634300081b0033");
159
160pub type State = foundry_evm::utils::StateChangeset;
161
162#[derive(Debug)]
164pub enum BlockRequest {
165 Pending(Vec<Arc<PoolTransaction>>),
166 Number(u64),
167}
168
169impl BlockRequest {
170 pub fn block_number(&self) -> BlockNumber {
171 match *self {
172 Self::Pending(_) => BlockNumber::Pending,
173 Self::Number(n) => BlockNumber::Number(n),
174 }
175 }
176}
177
178#[derive(Clone)]
180pub struct Backend {
181 db: Arc<AsyncRwLock<Box<dyn Db>>>,
201 blockchain: Blockchain,
203 states: Arc<RwLock<InMemoryBlockStates>>,
205 env: Arc<RwLock<Env>>,
207 fork: Arc<RwLock<Option<ClientFork>>>,
209 time: TimeManager,
211 cheats: CheatsManager,
213 fees: FeeManager,
215 genesis: GenesisConfig,
217 new_block_listeners: Arc<Mutex<Vec<UnboundedSender<NewBlockNotification>>>>,
219 active_state_snapshots: Arc<Mutex<HashMap<U256, (u64, B256)>>>,
221 enable_steps_tracing: bool,
222 print_logs: bool,
223 print_traces: bool,
224 odyssey: bool,
225 prune_state_history_config: PruneStateHistoryConfig,
227 transaction_block_keeper: Option<usize>,
229 node_config: Arc<AsyncRwLock<NodeConfig>>,
230 slots_in_an_epoch: u64,
232 precompile_factory: Option<Arc<dyn PrecompileFactory>>,
234 mining: Arc<tokio::sync::Mutex<()>>,
236 capabilities: Arc<RwLock<WalletCapabilities>>,
238 executor_wallet: Arc<RwLock<Option<EthereumWallet>>>,
239}
240
241impl Backend {
242 #[expect(clippy::too_many_arguments)]
244 pub async fn with_genesis(
245 db: Arc<AsyncRwLock<Box<dyn Db>>>,
246 env: Arc<RwLock<Env>>,
247 genesis: GenesisConfig,
248 fees: FeeManager,
249 fork: Arc<RwLock<Option<ClientFork>>>,
250 enable_steps_tracing: bool,
251 print_logs: bool,
252 print_traces: bool,
253 odyssey: bool,
254 prune_state_history_config: PruneStateHistoryConfig,
255 max_persisted_states: Option<usize>,
256 transaction_block_keeper: Option<usize>,
257 automine_block_time: Option<Duration>,
258 cache_path: Option<PathBuf>,
259 node_config: Arc<AsyncRwLock<NodeConfig>>,
260 ) -> Result<Self> {
261 let blockchain = if let Some(fork) = fork.read().as_ref() {
263 trace!(target: "backend", "using forked blockchain at {}", fork.block_number());
264 Blockchain::forked(fork.block_number(), fork.block_hash(), fork.total_difficulty())
265 } else {
266 let env = env.read();
267 Blockchain::new(
268 &env,
269 env.evm_env.cfg_env.spec,
270 fees.is_eip1559().then(|| fees.base_fee()),
271 genesis.timestamp,
272 genesis.number,
273 )
274 };
275
276 let start_timestamp = if let Some(fork) = fork.read().as_ref() {
277 fork.timestamp()
278 } else {
279 genesis.timestamp
280 };
281
282 let mut states = if prune_state_history_config.is_config_enabled() {
283 prune_state_history_config
285 .max_memory_history
286 .map(|limit| InMemoryBlockStates::new(limit, 0))
287 .unwrap_or_default()
288 .memory_only()
289 } else if max_persisted_states.is_some() {
290 max_persisted_states
291 .map(|limit| InMemoryBlockStates::new(DEFAULT_HISTORY_LIMIT, limit))
292 .unwrap_or_default()
293 } else {
294 Default::default()
295 };
296
297 if let Some(cache_path) = cache_path {
298 states = states.disk_path(cache_path);
299 }
300
301 let (slots_in_an_epoch, precompile_factory) = {
302 let cfg = node_config.read().await;
303 (cfg.slots_in_an_epoch, cfg.precompile_factory.clone())
304 };
305
306 let (capabilities, executor_wallet) = if odyssey {
307 let mut db = db.write().await;
309
310 let _ = db.set_code(
311 P256_DELEGATION_CONTRACT,
312 Bytes::from_static(P256_DELEGATION_RUNTIME_CODE),
313 );
314
315 let _ = db.set_code(EXP_ERC20_CONTRACT, Bytes::from_static(EXP_ERC20_RUNTIME_CODE));
317
318 let init_balance = Unit::ETHER.wei().saturating_mul(U256::from(10_000)); let _ = db.set_balance(EXP_ERC20_CONTRACT, init_balance);
322 let _ = db.set_balance(EXECUTOR, init_balance);
323
324 let mut capabilities = WalletCapabilities::default();
325
326 let chain_id = env.read().evm_env.cfg_env.chain_id;
327 capabilities.insert(
328 chain_id,
329 Capabilities {
330 delegation: DelegationCapability { addresses: vec![P256_DELEGATION_CONTRACT] },
331 },
332 );
333
334 let signer: PrivateKeySigner = EXECUTOR_PK.parse().unwrap();
335
336 let executor_wallet = EthereumWallet::new(signer);
337
338 (capabilities, Some(executor_wallet))
339 } else {
340 (WalletCapabilities::default(), None)
341 };
342
343 let backend = Self {
344 db,
345 blockchain,
346 states: Arc::new(RwLock::new(states)),
347 env,
348 fork,
349 time: TimeManager::new(start_timestamp),
350 cheats: Default::default(),
351 new_block_listeners: Default::default(),
352 fees,
353 genesis,
354 active_state_snapshots: Arc::new(Mutex::new(Default::default())),
355 enable_steps_tracing,
356 print_logs,
357 print_traces,
358 odyssey,
359 prune_state_history_config,
360 transaction_block_keeper,
361 node_config,
362 slots_in_an_epoch,
363 precompile_factory,
364 mining: Arc::new(tokio::sync::Mutex::new(())),
365 capabilities: Arc::new(RwLock::new(capabilities)),
366 executor_wallet: Arc::new(RwLock::new(executor_wallet)),
367 };
368
369 if let Some(interval_block_time) = automine_block_time {
370 backend.update_interval_mine_block_time(interval_block_time);
371 }
372
373 backend.apply_genesis().await.wrap_err("failed to create genesis")?;
375 Ok(backend)
376 }
377
378 pub async fn set_create2_deployer(&self, address: Address) -> DatabaseResult<()> {
380 self.set_code(address, Bytes::from_static(DEFAULT_CREATE2_DEPLOYER_RUNTIME_CODE)).await?;
381
382 Ok(())
383 }
384
385 pub(crate) fn get_capabilities(&self) -> WalletCapabilities {
391 self.capabilities.read().clone()
392 }
393
394 pub(crate) fn update_interval_mine_block_time(&self, block_time: Duration) {
396 self.states.write().update_interval_mine_block_time(block_time)
397 }
398
399 pub(crate) fn executor_wallet(&self) -> Option<EthereumWallet> {
400 self.executor_wallet.read().clone()
401 }
402
403 pub(crate) fn add_capability(&self, address: Address) {
405 let chain_id = self.env.read().evm_env.cfg_env.chain_id;
406 let mut capabilities = self.capabilities.write();
407 let mut capability = capabilities.get(chain_id).cloned().unwrap_or_default();
408 capability.delegation.addresses.push(address);
409 capabilities.insert(chain_id, capability);
410 }
411
412 pub(crate) fn set_executor(&self, executor_pk: String) -> Result<Address, BlockchainError> {
413 let signer: PrivateKeySigner =
414 executor_pk.parse().map_err(|_| RpcError::invalid_params("Invalid private key"))?;
415
416 let executor = signer.address();
417 let wallet = EthereumWallet::new(signer);
418
419 *self.executor_wallet.write() = Some(wallet);
420
421 Ok(executor)
422 }
423
424 async fn apply_genesis(&self) -> Result<(), DatabaseError> {
428 trace!(target: "backend", "setting genesis balances");
429
430 if self.fork.read().is_some() {
431 let mut genesis_accounts_futures = Vec::with_capacity(self.genesis.accounts.len());
433 for address in self.genesis.accounts.iter().copied() {
434 let db = Arc::clone(&self.db);
435
436 genesis_accounts_futures.push(tokio::task::spawn(async move {
439 let db = db.read().await;
440 let info = db.basic_ref(address)?.unwrap_or_default();
441 Ok::<_, DatabaseError>((address, info))
442 }));
443 }
444
445 let genesis_accounts = futures::future::join_all(genesis_accounts_futures).await;
446
447 let mut db = self.db.write().await;
448
449 for res in genesis_accounts {
450 let (address, mut info) = res.unwrap()?;
451 info.balance = self.genesis.balance;
452 db.insert_account(address, info.clone());
453 }
454 } else {
455 let mut db = self.db.write().await;
456 for (account, info) in self.genesis.account_infos() {
457 db.insert_account(account, info);
458 }
459
460 db.insert_block_hash(U256::from(self.best_number()), self.best_hash());
463 }
464
465 let db = self.db.write().await;
466 self.genesis.apply_genesis_json_alloc(db)?;
468
469 trace!(target: "backend", "set genesis balances");
470
471 Ok(())
472 }
473
474 pub fn impersonate(&self, addr: Address) -> bool {
478 if self.cheats.impersonated_accounts().contains(&addr) {
479 return true
480 }
481 let mut env = self.env.write();
483 env.evm_env.cfg_env.disable_eip3607 = true;
484 self.cheats.impersonate(addr)
485 }
486
487 pub fn stop_impersonating(&self, addr: Address) {
491 self.cheats.stop_impersonating(&addr);
492 }
493
494 pub fn auto_impersonate_account(&self, enabled: bool) {
496 self.cheats.set_auto_impersonate_account(enabled);
497 }
498
499 pub fn get_fork(&self) -> Option<ClientFork> {
501 self.fork.read().clone()
502 }
503
504 pub fn get_db(&self) -> &Arc<AsyncRwLock<Box<dyn Db>>> {
506 &self.db
507 }
508
509 pub async fn get_account(&self, address: Address) -> DatabaseResult<AccountInfo> {
511 Ok(self.db.read().await.basic_ref(address)?.unwrap_or_default())
512 }
513
514 pub fn is_fork(&self) -> bool {
516 self.fork.read().is_some()
517 }
518
519 pub fn precompiles(&self) -> Vec<Address> {
520 get_precompiles_for(self.env.read().evm_env.cfg_env.spec)
521 }
522
523 pub async fn reset_fork(&self, forking: Forking) -> Result<(), BlockchainError> {
525 if !self.is_fork() {
526 if let Some(eth_rpc_url) = forking.clone().json_rpc_url {
527 let mut env = self.env.read().clone();
528
529 let (db, config) = {
530 let mut node_config = self.node_config.write().await;
531
532 node_config.base_fee.take();
535
536 node_config.setup_fork_db_config(eth_rpc_url, &mut env, &self.fees).await?
537 };
538
539 *self.db.write().await = Box::new(db);
540
541 let fork = ClientFork::new(config, Arc::clone(&self.db));
542
543 *self.env.write() = env;
544 *self.fork.write() = Some(fork);
545 } else {
546 return Err(RpcError::invalid_params(
547 "Forking not enabled and RPC URL not provided to start forking",
548 )
549 .into());
550 }
551 }
552
553 if let Some(fork) = self.get_fork() {
554 let block_number =
555 forking.block_number.map(BlockNumber::from).unwrap_or(BlockNumber::Latest);
556 fork.reset(forking.json_rpc_url.clone(), block_number).await?;
558 let fork_block_number = fork.block_number();
559 let fork_block = fork
560 .block_by_number(fork_block_number)
561 .await?
562 .ok_or(BlockchainError::BlockNotFound)?;
563 {
565 if let Some(fork_url) = forking.json_rpc_url {
566 self.reset_block_number(fork_url, fork_block_number).await?;
567 } else {
568 {
571 let maybe_fork_url = { self.node_config.read().await.eth_rpc_url.clone() };
572 if let Some(fork_url) = maybe_fork_url {
573 self.reset_block_number(fork_url, fork_block_number).await?;
574 }
575 }
576
577 let gas_limit = self.node_config.read().await.fork_gas_limit(&fork_block);
578 let mut env = self.env.write();
579
580 env.evm_env.cfg_env.chain_id = fork.chain_id();
581 env.evm_env.block_env = BlockEnv {
582 number: fork_block_number,
583 timestamp: fork_block.header.timestamp,
584 gas_limit,
585 difficulty: fork_block.header.difficulty,
586 prevrandao: Some(fork_block.header.mix_hash.unwrap_or_default()),
587 beneficiary: env.evm_env.block_env.beneficiary,
589 basefee: env.evm_env.block_env.basefee,
590 ..env.evm_env.block_env.clone()
591 };
592
593 let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
596 fork_block.header.gas_used,
597 gas_limit,
598 fork_block.header.base_fee_per_gas.unwrap_or_default(),
599 );
600
601 self.fees.set_base_fee(next_block_base_fee);
602 }
603
604 self.time.reset(fork_block.header.timestamp);
606
607 self.blockchain.storage.write().total_difficulty = fork.total_difficulty();
609 }
610 *self.blockchain.storage.write() = BlockchainStorage::forked(
612 fork.block_number(),
613 fork.block_hash(),
614 fork.total_difficulty(),
615 );
616 self.states.write().clear();
617 self.db.write().await.clear();
618
619 self.apply_genesis().await?;
620
621 trace!(target: "backend", "reset fork");
622
623 Ok(())
624 } else {
625 Err(RpcError::invalid_params("Forking not enabled").into())
626 }
627 }
628
629 async fn reset_block_number(
630 &self,
631 fork_url: String,
632 fork_block_number: u64,
633 ) -> Result<(), BlockchainError> {
634 let mut node_config = self.node_config.write().await;
635 node_config.fork_choice = Some(ForkChoice::Block(fork_block_number as i128));
636
637 let mut env = self.env.read().clone();
638 let (forked_db, client_fork_config) =
639 node_config.setup_fork_db_config(fork_url, &mut env, &self.fees).await?;
640
641 *self.db.write().await = Box::new(forked_db);
642 let fork = ClientFork::new(client_fork_config, Arc::clone(&self.db));
643 *self.fork.write() = Some(fork);
644 *self.env.write() = env;
645
646 Ok(())
647 }
648
649 pub fn time(&self) -> &TimeManager {
651 &self.time
652 }
653
654 pub fn cheats(&self) -> &CheatsManager {
656 &self.cheats
657 }
658
659 pub fn skip_blob_validation(&self, impersonator: Option<Address>) -> bool {
661 self.cheats().auto_impersonate_accounts() ||
662 impersonator
663 .is_some_and(|addr| self.cheats().impersonated_accounts().contains(&addr))
664 }
665
666 pub fn fees(&self) -> &FeeManager {
668 &self.fees
669 }
670
671 pub fn env(&self) -> &Arc<RwLock<Env>> {
673 &self.env
674 }
675
676 pub fn best_hash(&self) -> B256 {
678 self.blockchain.storage.read().best_hash
679 }
680
681 pub fn best_number(&self) -> u64 {
683 self.blockchain.storage.read().best_number
684 }
685
686 pub fn set_block_number(&self, number: u64) {
688 let mut env = self.env.write();
689 env.evm_env.block_env.number = number;
690 }
691
692 pub fn coinbase(&self) -> Address {
694 self.env.read().evm_env.block_env.beneficiary
695 }
696
697 pub fn chain_id(&self) -> U256 {
699 U256::from(self.env.read().evm_env.cfg_env.chain_id)
700 }
701
702 pub fn set_chain_id(&self, chain_id: u64) {
703 self.env.write().evm_env.cfg_env.chain_id = chain_id;
704 }
705
706 pub async fn current_balance(&self, address: Address) -> DatabaseResult<U256> {
708 Ok(self.get_account(address).await?.balance)
709 }
710
711 pub async fn current_nonce(&self, address: Address) -> DatabaseResult<u64> {
713 Ok(self.get_account(address).await?.nonce)
714 }
715
716 pub fn set_coinbase(&self, address: Address) {
718 self.env.write().evm_env.block_env.beneficiary = address;
719 }
720
721 pub async fn set_nonce(&self, address: Address, nonce: U256) -> DatabaseResult<()> {
723 self.db.write().await.set_nonce(address, nonce.try_into().unwrap_or(u64::MAX))
724 }
725
726 pub async fn set_balance(&self, address: Address, balance: U256) -> DatabaseResult<()> {
728 self.db.write().await.set_balance(address, balance)
729 }
730
731 pub async fn set_code(&self, address: Address, code: Bytes) -> DatabaseResult<()> {
733 self.db.write().await.set_code(address, code.0.into())
734 }
735
736 pub async fn set_storage_at(
738 &self,
739 address: Address,
740 slot: U256,
741 val: B256,
742 ) -> DatabaseResult<()> {
743 self.db.write().await.set_storage_at(address, slot.into(), val)
744 }
745
746 pub fn spec_id(&self) -> SpecId {
748 self.env.read().evm_env.cfg_env.spec
749 }
750
751 pub fn is_eip1559(&self) -> bool {
753 (self.spec_id() as u8) >= (SpecId::LONDON as u8)
754 }
755
756 pub fn is_eip3675(&self) -> bool {
758 (self.spec_id() as u8) >= (SpecId::MERGE as u8)
759 }
760
761 pub fn is_eip2930(&self) -> bool {
763 (self.spec_id() as u8) >= (SpecId::BERLIN as u8)
764 }
765
766 pub fn is_eip4844(&self) -> bool {
768 (self.spec_id() as u8) >= (SpecId::CANCUN as u8)
769 }
770
771 pub fn is_eip7702(&self) -> bool {
773 (self.spec_id() as u8) >= (SpecId::PRAGUE as u8)
774 }
775
776 pub fn is_optimism(&self) -> bool {
778 self.env.read().is_optimism
779 }
780
781 pub fn blob_params(&self) -> BlobParams {
783 if self.env.read().evm_env.cfg_env.spec >= SpecId::PRAGUE {
784 BlobParams::prague()
785 } else {
786 BlobParams::cancun()
787 }
788 }
789
790 pub fn ensure_eip1559_active(&self) -> Result<(), BlockchainError> {
792 if self.is_eip1559() {
793 return Ok(());
794 }
795 Err(BlockchainError::EIP1559TransactionUnsupportedAtHardfork)
796 }
797
798 pub fn ensure_eip2930_active(&self) -> Result<(), BlockchainError> {
800 if self.is_eip2930() {
801 return Ok(());
802 }
803 Err(BlockchainError::EIP2930TransactionUnsupportedAtHardfork)
804 }
805
806 pub fn ensure_eip4844_active(&self) -> Result<(), BlockchainError> {
807 if self.is_eip4844() {
808 return Ok(());
809 }
810 Err(BlockchainError::EIP4844TransactionUnsupportedAtHardfork)
811 }
812
813 pub fn ensure_eip7702_active(&self) -> Result<(), BlockchainError> {
814 if self.is_eip7702() {
815 return Ok(());
816 }
817 Err(BlockchainError::EIP7702TransactionUnsupportedAtHardfork)
818 }
819
820 pub fn ensure_op_deposits_active(&self) -> Result<(), BlockchainError> {
822 if self.is_optimism() {
823 return Ok(())
824 }
825 Err(BlockchainError::DepositTransactionUnsupported)
826 }
827
828 pub fn gas_limit(&self) -> u64 {
830 self.env.read().evm_env.block_env.gas_limit
831 }
832
833 pub fn set_gas_limit(&self, gas_limit: u64) {
835 self.env.write().evm_env.block_env.gas_limit = gas_limit;
836 }
837
838 pub fn base_fee(&self) -> u64 {
840 self.fees.base_fee()
841 }
842
843 pub fn is_min_priority_fee_enforced(&self) -> bool {
845 self.fees.is_min_priority_fee_enforced()
846 }
847
848 pub fn excess_blob_gas_and_price(&self) -> Option<BlobExcessGasAndPrice> {
849 self.fees.excess_blob_gas_and_price()
850 }
851
852 pub fn set_base_fee(&self, basefee: u64) {
854 self.fees.set_base_fee(basefee)
855 }
856
857 pub fn set_gas_price(&self, price: u128) {
859 self.fees.set_gas_price(price)
860 }
861
862 pub fn elasticity(&self) -> f64 {
863 self.fees.elasticity()
864 }
865
866 pub fn total_difficulty(&self) -> U256 {
871 self.blockchain.storage.read().total_difficulty
872 }
873
874 pub async fn create_state_snapshot(&self) -> U256 {
878 let num = self.best_number();
879 let hash = self.best_hash();
880 let id = self.db.write().await.snapshot_state();
881 trace!(target: "backend", "creating snapshot {} at {}", id, num);
882 self.active_state_snapshots.lock().insert(id, (num, hash));
883 id
884 }
885
886 pub async fn revert_state_snapshot(&self, id: U256) -> Result<bool, BlockchainError> {
888 let block = { self.active_state_snapshots.lock().remove(&id) };
889 if let Some((num, hash)) = block {
890 let best_block_hash = {
891 let current_height = self.best_number();
893 let mut storage = self.blockchain.storage.write();
894
895 for n in ((num + 1)..=current_height).rev() {
896 trace!(target: "backend", "reverting block {}", n);
897 if let Some(hash) = storage.hashes.remove(&n) {
898 if let Some(block) = storage.blocks.remove(&hash) {
899 for tx in block.transactions {
900 let _ = storage.transactions.remove(&tx.hash());
901 }
902 }
903 }
904 }
905
906 storage.best_number = num;
907 storage.best_hash = hash;
908 hash
909 };
910 let block =
911 self.block_by_hash(best_block_hash).await?.ok_or(BlockchainError::BlockNotFound)?;
912
913 let reset_time = block.header.timestamp;
914 self.time.reset(reset_time);
915
916 let mut env = self.env.write();
917 env.evm_env.block_env = BlockEnv {
918 number: num,
919 timestamp: block.header.timestamp,
920 difficulty: block.header.difficulty,
921 prevrandao: Some(block.header.mix_hash.unwrap_or_default()),
923 gas_limit: block.header.gas_limit,
924 beneficiary: env.evm_env.block_env.beneficiary,
926 basefee: env.evm_env.block_env.basefee,
927 ..Default::default()
928 }
929 }
930 Ok(self.db.write().await.revert_state(id, RevertStateSnapshotAction::RevertRemove))
931 }
932
933 pub fn list_state_snapshots(&self) -> BTreeMap<U256, (u64, B256)> {
934 self.active_state_snapshots.lock().clone().into_iter().collect()
935 }
936
937 pub async fn serialized_state(
939 &self,
940 preserve_historical_states: bool,
941 ) -> Result<SerializableState, BlockchainError> {
942 let at = self.env.read().evm_env.block_env.clone();
943 let best_number = self.blockchain.storage.read().best_number;
944 let blocks = self.blockchain.storage.read().serialized_blocks();
945 let transactions = self.blockchain.storage.read().serialized_transactions();
946 let historical_states = if preserve_historical_states {
947 Some(self.states.write().serialized_states())
948 } else {
949 None
950 };
951
952 let state = self.db.read().await.dump_state(
953 at,
954 best_number,
955 blocks,
956 transactions,
957 historical_states,
958 )?;
959 state.ok_or_else(|| {
960 RpcError::invalid_params("Dumping state not supported with the current configuration")
961 .into()
962 })
963 }
964
965 pub async fn dump_state(
967 &self,
968 preserve_historical_states: bool,
969 ) -> Result<Bytes, BlockchainError> {
970 let state = self.serialized_state(preserve_historical_states).await?;
971 let mut encoder = GzEncoder::new(Vec::new(), Compression::default());
972 encoder
973 .write_all(&serde_json::to_vec(&state).unwrap_or_default())
974 .map_err(|_| BlockchainError::DataUnavailable)?;
975 Ok(encoder.finish().unwrap_or_default().into())
976 }
977
978 pub async fn load_state(&self, state: SerializableState) -> Result<bool, BlockchainError> {
980 self.blockchain.storage.write().load_blocks(state.blocks.clone());
982 self.blockchain.storage.write().load_transactions(state.transactions.clone());
983 if let Some(block) = state.block.clone() {
985 self.env.write().evm_env.block_env = block.clone();
986
987 let fork_num_and_hash = self.get_fork().map(|f| (f.block_number(), f.block_hash()));
990
991 if let Some((number, hash)) = fork_num_and_hash {
992 let best_number = state.best_block_number.unwrap_or(block.number);
993 trace!(target: "backend", state_block_number=?best_number, fork_block_number=?number);
994 if best_number > number {
998 self.blockchain.storage.write().best_number = best_number;
999 let best_hash =
1000 self.blockchain.storage.read().hash(best_number.into()).ok_or_else(
1001 || {
1002 BlockchainError::RpcError(RpcError::internal_error_with(format!(
1003 "Best hash not found for best number {best_number}",
1004 )))
1005 },
1006 )?;
1007 self.blockchain.storage.write().best_hash = best_hash;
1008 } else {
1009 self.blockchain.storage.write().best_number = number;
1012 self.blockchain.storage.write().best_hash = hash;
1013 }
1014 } else {
1015 let best_number = state.best_block_number.unwrap_or(block.number);
1016 self.blockchain.storage.write().best_number = best_number;
1017
1018 let best_hash =
1020 self.blockchain.storage.read().hash(best_number.into()).ok_or_else(|| {
1021 BlockchainError::RpcError(RpcError::internal_error_with(format!(
1022 "Best hash not found for best number {best_number}",
1023 )))
1024 })?;
1025
1026 self.blockchain.storage.write().best_hash = best_hash;
1027 }
1028 }
1029
1030 if let Some(latest) = state.blocks.iter().max_by_key(|b| b.header.number) {
1031 let header = &latest.header;
1032 let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
1033 header.gas_used,
1034 header.gas_limit,
1035 header.base_fee_per_gas.unwrap_or_default(),
1036 );
1037 let next_block_excess_blob_gas = self.fees.get_next_block_blob_excess_gas(
1038 header.excess_blob_gas.unwrap_or_default(),
1039 header.blob_gas_used.unwrap_or_default(),
1040 );
1041
1042 self.fees.set_base_fee(next_block_base_fee);
1044 self.fees.set_blob_excess_gas_and_price(BlobExcessGasAndPrice::new(
1045 next_block_excess_blob_gas,
1046 false,
1047 ));
1048 }
1049
1050 if !self.db.write().await.load_state(state.clone())? {
1051 return Err(RpcError::invalid_params(
1052 "Loading state not supported with the current configuration",
1053 )
1054 .into());
1055 }
1056
1057 if let Some(historical_states) = state.historical_states {
1058 self.states.write().load_states(historical_states);
1059 }
1060
1061 Ok(true)
1062 }
1063
1064 pub async fn load_state_bytes(&self, buf: Bytes) -> Result<bool, BlockchainError> {
1066 let orig_buf = &buf.0[..];
1067 let mut decoder = GzDecoder::new(orig_buf);
1068 let mut decoded_data = Vec::new();
1069
1070 let state: SerializableState = serde_json::from_slice(if decoder.header().is_some() {
1071 decoder
1072 .read_to_end(decoded_data.as_mut())
1073 .map_err(|_| BlockchainError::FailedToDecodeStateDump)?;
1074 &decoded_data
1075 } else {
1076 &buf.0
1077 })
1078 .map_err(|_| BlockchainError::FailedToDecodeStateDump)?;
1079
1080 self.load_state(state).await
1081 }
1082
1083 fn next_env(&self) -> Env {
1085 let mut env = self.env.read().clone();
1086 env.evm_env.block_env.number = env.evm_env.block_env.number.saturating_add(1);
1088 env.evm_env.block_env.basefee = self.base_fee();
1089 env.evm_env.block_env.timestamp = self.time.current_call_timestamp();
1090 env
1091 }
1092
1093 fn new_evm_with_inspector_ref<'db, I>(
1095 &self,
1096 db: &'db dyn DatabaseRef<Error = DatabaseError>,
1097 env: &Env,
1098 inspector: &'db mut I,
1099 ) -> EitherEvm<
1100 WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>,
1101 &'db mut I,
1102 PrecompilesMap,
1103 >
1104 where
1105 I: Inspector<EthEvmContext<WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>>>
1106 + Inspector<OpContext<WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>>>,
1107 WrapDatabaseRef<&'db dyn DatabaseRef<Error = DatabaseError>>:
1108 Database<Error = DatabaseError>,
1109 {
1110 let mut evm = new_evm_with_inspector_ref(db, env, inspector);
1111
1112 if self.odyssey {
1113 inject_precompiles(&mut evm, vec![P256VERIFY]);
1114 }
1115
1116 if let Some(factory) = &self.precompile_factory {
1117 inject_precompiles(&mut evm, factory.precompiles());
1118 }
1119
1120 evm
1121 }
1122
1123 pub async fn inspect_tx(
1125 &self,
1126 tx: Arc<PoolTransaction>,
1127 ) -> Result<
1128 (InstructionResult, Option<Output>, u64, State, Vec<revm::primitives::Log>),
1129 BlockchainError,
1130 > {
1131 let mut env = self.next_env();
1132 env.tx = tx.pending_transaction.to_revm_tx_env();
1133
1134 if env.is_optimism {
1135 env.tx.enveloped_tx =
1136 Some(alloy_rlp::encode(&tx.pending_transaction.transaction.transaction).into());
1137 }
1138
1139 let db = self.db.read().await;
1140 let mut inspector = self.build_inspector();
1141 let mut evm = self.new_evm_with_inspector_ref(db.as_dyn(), &env, &mut inspector);
1142 let ResultAndState { result, state } = evm.transact(env.tx)?;
1143 let (exit_reason, gas_used, out, logs) = match result {
1144 ExecutionResult::Success { reason, gas_used, logs, output, .. } => {
1145 (reason.into(), gas_used, Some(output), Some(logs))
1146 }
1147 ExecutionResult::Revert { gas_used, output } => {
1148 (InstructionResult::Revert, gas_used, Some(Output::Call(output)), None)
1149 }
1150 ExecutionResult::Halt { reason, gas_used } => {
1151 let eth_reason = op_haltreason_to_instruction_result(reason);
1152 (eth_reason, gas_used, None, None)
1153 }
1154 };
1155
1156 drop(evm);
1157 inspector.print_logs();
1158
1159 if self.print_traces {
1160 inspector.print_traces();
1161 }
1162
1163 Ok((exit_reason, out, gas_used, state, logs.unwrap_or_default()))
1164 }
1165
1166 pub async fn pending_block(&self, pool_transactions: Vec<Arc<PoolTransaction>>) -> BlockInfo {
1170 self.with_pending_block(pool_transactions, |_, block| block).await
1171 }
1172
1173 pub async fn with_pending_block<F, T>(
1177 &self,
1178 pool_transactions: Vec<Arc<PoolTransaction>>,
1179 f: F,
1180 ) -> T
1181 where
1182 F: FnOnce(Box<dyn MaybeFullDatabase + '_>, BlockInfo) -> T,
1183 {
1184 let db = self.db.read().await;
1185 let env = self.next_env();
1186
1187 let mut cache_db = CacheDB::new(&*db);
1188
1189 let storage = self.blockchain.storage.read();
1190
1191 let executor = TransactionExecutor {
1192 db: &mut cache_db,
1193 validator: self,
1194 pending: pool_transactions.into_iter(),
1195 block_env: env.evm_env.block_env.clone(),
1196 cfg_env: env.evm_env.cfg_env,
1197 parent_hash: storage.best_hash,
1198 gas_used: 0,
1199 blob_gas_used: 0,
1200 enable_steps_tracing: self.enable_steps_tracing,
1201 print_logs: self.print_logs,
1202 print_traces: self.print_traces,
1203 precompile_factory: self.precompile_factory.clone(),
1204 odyssey: self.odyssey,
1205 optimism: self.is_optimism(),
1206 blob_params: self.blob_params(),
1207 };
1208
1209 let executed = executor.execute();
1211 f(Box::new(cache_db), executed.block)
1212 }
1213
1214 pub async fn mine_block(
1219 &self,
1220 pool_transactions: Vec<Arc<PoolTransaction>>,
1221 ) -> MinedBlockOutcome {
1222 self.do_mine_block(pool_transactions).await
1223 }
1224
1225 async fn do_mine_block(
1226 &self,
1227 pool_transactions: Vec<Arc<PoolTransaction>>,
1228 ) -> MinedBlockOutcome {
1229 let _mining_guard = self.mining.lock().await;
1230 trace!(target: "backend", "creating new block with {} transactions", pool_transactions.len());
1231
1232 let (outcome, header, block_hash) = {
1233 let current_base_fee = self.base_fee();
1234 let current_excess_blob_gas_and_price = self.excess_blob_gas_and_price();
1235
1236 let mut env = self.env.read().clone();
1237
1238 if env.evm_env.block_env.basefee == 0 {
1239 env.evm_env.cfg_env.disable_base_fee = true;
1242 }
1243
1244 let block_number = self.blockchain.storage.read().best_number.saturating_add(1);
1245
1246 if is_arbitrum(env.evm_env.cfg_env.chain_id) {
1248 env.evm_env.block_env.number = block_number;
1250 } else {
1251 env.evm_env.block_env.number = env.evm_env.block_env.number.saturating_add(1);
1252 }
1253
1254 env.evm_env.block_env.basefee = current_base_fee;
1255 env.evm_env.block_env.blob_excess_gas_and_price = current_excess_blob_gas_and_price;
1256
1257 env.evm_env.block_env.prevrandao = Some(B256::random());
1259
1260 let best_hash = self.blockchain.storage.read().best_hash;
1261
1262 if self.prune_state_history_config.is_state_history_supported() {
1263 let db = self.db.read().await.current_state();
1264 self.states.write().insert(best_hash, db);
1266 }
1267
1268 let (executed_tx, block_hash) = {
1269 let mut db = self.db.write().await;
1270
1271 env.evm_env.block_env.timestamp = self.time.next_timestamp();
1275
1276 let executor = TransactionExecutor {
1277 db: &mut **db,
1278 validator: self,
1279 pending: pool_transactions.into_iter(),
1280 block_env: env.evm_env.block_env.clone(),
1281 cfg_env: env.evm_env.cfg_env.clone(),
1282 parent_hash: best_hash,
1283 gas_used: 0,
1284 blob_gas_used: 0,
1285 enable_steps_tracing: self.enable_steps_tracing,
1286 print_logs: self.print_logs,
1287 print_traces: self.print_traces,
1288 odyssey: self.odyssey,
1289 precompile_factory: self.precompile_factory.clone(),
1290 optimism: self.is_optimism(),
1291 blob_params: self.blob_params(),
1292 };
1293 let executed_tx = executor.execute();
1294
1295 let block_hash = executed_tx.block.block.header.hash_slow();
1297 db.insert_block_hash(U256::from(executed_tx.block.block.header.number), block_hash);
1298
1299 (executed_tx, block_hash)
1300 };
1301
1302 let ExecutedTransactions { block, included, invalid } = executed_tx;
1304 let BlockInfo { block, transactions, receipts } = block;
1305
1306 let header = block.header.clone();
1307
1308 trace!(
1309 target: "backend",
1310 "Mined block {} with {} tx {:?}",
1311 block_number,
1312 transactions.len(),
1313 transactions.iter().map(|tx| tx.transaction_hash).collect::<Vec<_>>()
1314 );
1315 let mut storage = self.blockchain.storage.write();
1316 storage.best_number = block_number;
1318 storage.best_hash = block_hash;
1319 if !self.is_eip3675() {
1322 storage.total_difficulty =
1323 storage.total_difficulty.saturating_add(header.difficulty);
1324 }
1325
1326 storage.blocks.insert(block_hash, block);
1327 storage.hashes.insert(block_number, block_hash);
1328
1329 node_info!("");
1330 for (info, receipt) in transactions.into_iter().zip(receipts) {
1332 node_info!(" Transaction: {:?}", info.transaction_hash);
1334 if let Some(contract) = &info.contract_address {
1335 node_info!(" Contract created: {contract}");
1336 }
1337 node_info!(" Gas used: {}", receipt.cumulative_gas_used());
1338 if !info.exit.is_ok() {
1339 let r = RevertDecoder::new().decode(
1340 info.out.as_ref().map(|b| &b[..]).unwrap_or_default(),
1341 Some(info.exit),
1342 );
1343 node_info!(" Error: reverted with: {r}");
1344 }
1345 node_info!("");
1346
1347 let mined_tx = MinedTransaction { info, receipt, block_hash, block_number };
1348 storage.transactions.insert(mined_tx.info.transaction_hash, mined_tx);
1349 }
1350
1351 if let Some(transaction_block_keeper) = self.transaction_block_keeper {
1353 if storage.blocks.len() > transaction_block_keeper {
1354 let to_clear = block_number
1355 .saturating_sub(transaction_block_keeper.try_into().unwrap_or(u64::MAX));
1356 storage.remove_block_transactions_by_number(to_clear)
1357 }
1358 }
1359
1360 env.evm_env.block_env.difficulty = U256::from(0);
1362
1363 *self.env.write() = env;
1365
1366 let timestamp = utc_from_secs(header.timestamp);
1367
1368 node_info!(" Block Number: {}", block_number);
1369 node_info!(" Block Hash: {:?}", block_hash);
1370 if timestamp.year() > 9999 {
1371 node_info!(" Block Time: {:?}\n", timestamp.to_rfc3339());
1373 } else {
1374 node_info!(" Block Time: {:?}\n", timestamp.to_rfc2822());
1375 }
1376
1377 let outcome = MinedBlockOutcome { block_number, included, invalid };
1378
1379 (outcome, header, block_hash)
1380 };
1381 let next_block_base_fee = self.fees.get_next_block_base_fee_per_gas(
1382 header.gas_used,
1383 header.gas_limit,
1384 header.base_fee_per_gas.unwrap_or_default(),
1385 );
1386 let next_block_excess_blob_gas = self.fees.get_next_block_blob_excess_gas(
1387 header.excess_blob_gas.unwrap_or_default(),
1388 header.blob_gas_used.unwrap_or_default(),
1389 );
1390
1391 self.fees.set_base_fee(next_block_base_fee);
1393 self.fees.set_blob_excess_gas_and_price(BlobExcessGasAndPrice::new(
1394 next_block_excess_blob_gas,
1395 false,
1396 ));
1397
1398 self.notify_on_new_block(header, block_hash);
1400
1401 outcome
1402 }
1403
1404 pub async fn call(
1410 &self,
1411 request: WithOtherFields<TransactionRequest>,
1412 fee_details: FeeDetails,
1413 block_request: Option<BlockRequest>,
1414 overrides: EvmOverrides,
1415 ) -> Result<(InstructionResult, Option<Output>, u128, State), BlockchainError> {
1416 self.with_database_at(block_request, |state, mut block| {
1417 let block_number = block.number;
1418 let (exit, out, gas, state) = {
1419 let mut cache_db = CacheDB::new(state);
1420 if let Some(state_overrides) = overrides.state {
1421 state::apply_state_overrides(state_overrides.into_iter().collect(), &mut cache_db)?;
1422 }
1423 if let Some(block_overrides) = overrides.block {
1424 state::apply_block_overrides(*block_overrides, &mut cache_db, &mut block);
1425 }
1426 self.call_with_state(cache_db.as_dyn(), request, fee_details, block)
1427 }?;
1428 trace!(target: "backend", "call return {:?} out: {:?} gas {} on block {}", exit, out, gas, block_number);
1429 Ok((exit, out, gas, state))
1430 }).await?
1431 }
1432
1433 fn build_call_env(
1441 &self,
1442 request: WithOtherFields<TransactionRequest>,
1443 fee_details: FeeDetails,
1444 block_env: BlockEnv,
1445 ) -> Env {
1446 let WithOtherFields::<TransactionRequest> {
1447 inner:
1448 TransactionRequest {
1449 from,
1450 to,
1451 gas,
1452 value,
1453 input,
1454 access_list,
1455 blob_versioned_hashes,
1456 authorization_list,
1457 nonce,
1458 sidecar: _,
1459 chain_id,
1460 transaction_type,
1461 max_fee_per_gas,
1462 max_priority_fee_per_gas,
1463 .. },
1465 other,
1466 } = request;
1467
1468 let tx_type = transaction_type.unwrap_or_else(|| {
1469 if authorization_list.is_some() {
1470 EIP7702_TX_TYPE_ID
1471 } else if blob_versioned_hashes.is_some() {
1472 EIP4844_TX_TYPE_ID
1473 } else if max_fee_per_gas.is_some() || max_priority_fee_per_gas.is_some() {
1474 EIP1559_TX_TYPE_ID
1475 } else if access_list.is_some() {
1476 EIP2930_TX_TYPE_ID
1477 } else {
1478 LEGACY_TX_TYPE_ID
1479 }
1480 });
1481
1482 let FeeDetails {
1483 gas_price,
1484 max_fee_per_gas,
1485 max_priority_fee_per_gas,
1486 max_fee_per_blob_gas,
1487 } = fee_details;
1488
1489 let gas_limit = gas.unwrap_or(block_env.gas_limit);
1490 let mut env = self.env.read().clone();
1491 env.evm_env.block_env = block_env;
1492 env.evm_env.cfg_env.disable_block_gas_limit = true;
1495
1496 env.evm_env.cfg_env.disable_base_fee = true;
1502
1503 let gas_price = gas_price.or(max_fee_per_gas).unwrap_or_else(|| {
1504 self.fees().raw_gas_price().saturating_add(MIN_SUGGESTED_PRIORITY_FEE)
1505 });
1506 let caller = from.unwrap_or_default();
1507 let to = to.as_ref().and_then(TxKind::to);
1508 let blob_hashes = blob_versioned_hashes.unwrap_or_default();
1509 let mut base = TxEnv {
1510 caller,
1511 gas_limit,
1512 gas_price,
1513 gas_priority_fee: max_priority_fee_per_gas,
1514 max_fee_per_blob_gas: max_fee_per_blob_gas
1515 .or_else(|| {
1516 if !blob_hashes.is_empty() {
1517 env.evm_env.block_env.blob_gasprice()
1518 } else {
1519 Some(0)
1520 }
1521 })
1522 .unwrap_or_default(),
1523 kind: match to {
1524 Some(addr) => TxKind::Call(*addr),
1525 None => TxKind::Create,
1526 },
1527 tx_type,
1528 value: value.unwrap_or_default(),
1529 data: input.into_input().unwrap_or_default(),
1530 chain_id: Some(chain_id.unwrap_or(self.env.read().evm_env.cfg_env.chain_id)),
1531 access_list: access_list.unwrap_or_default(),
1532 blob_hashes,
1533 ..Default::default()
1534 };
1535 base.set_signed_authorization(authorization_list.unwrap_or_default());
1536 env.tx = OpTransaction { base, ..Default::default() };
1537
1538 if let Some(nonce) = nonce {
1539 env.tx.base.nonce = nonce;
1540 } else {
1541 env.evm_env.cfg_env.disable_nonce_check = true;
1543 }
1544
1545 if env.evm_env.block_env.basefee == 0 {
1546 env.evm_env.cfg_env.disable_base_fee = true;
1549 }
1550
1551 if transaction_type == Some(DEPOSIT_TX_TYPE_ID) && has_optimism_fields(&other) {
1553 let deposit = DepositTransactionParts {
1554 source_hash: other
1555 .get_deserialized::<B256>("sourceHash")
1556 .map(|sh| sh.unwrap_or_default())
1557 .unwrap_or_default(),
1558 mint: other
1559 .get_deserialized::<u128>("mint")
1560 .map(|m| m.unwrap_or_default())
1561 .or(None),
1562 is_system_transaction: other
1563 .get_deserialized::<bool>("isSystemTx")
1564 .map(|st| st.unwrap_or_default())
1565 .unwrap_or_default(),
1566 };
1567 env.tx.deposit = deposit;
1568 }
1569
1570 env
1571 }
1572
1573 fn build_inspector(&self) -> AnvilInspector {
1575 let mut inspector = AnvilInspector::default();
1576
1577 if self.print_logs {
1578 inspector = inspector.with_log_collector();
1579 }
1580 if self.print_traces {
1581 inspector = inspector.with_trace_printer();
1582 }
1583
1584 inspector
1585 }
1586
1587 pub async fn simulate(
1589 &self,
1590 request: SimulatePayload,
1591 block_request: Option<BlockRequest>,
1592 ) -> Result<Vec<SimulatedBlock<AnyRpcBlock>>, BlockchainError> {
1593 self.with_database_at(block_request, |state, mut block_env| {
1594 let SimulatePayload {
1595 block_state_calls,
1596 trace_transfers,
1597 validation,
1598 return_full_transactions,
1599 } = request;
1600 let mut cache_db = CacheDB::new(state);
1601 let mut block_res = Vec::with_capacity(block_state_calls.len());
1602
1603 for block in block_state_calls {
1605 let SimBlock { block_overrides, state_overrides, calls } = block;
1606 let mut call_res = Vec::with_capacity(calls.len());
1607 let mut log_index = 0;
1608 let mut gas_used = 0;
1609 let mut transactions = Vec::with_capacity(calls.len());
1610 let mut receipts = Vec::new();
1611 let mut logs= Vec::new();
1612
1613 if let Some(state_overrides) = state_overrides {
1615 state::apply_state_overrides(state_overrides, &mut cache_db)?;
1616 }
1617 if let Some(block_overrides) = block_overrides {
1618 state::apply_block_overrides(block_overrides, &mut cache_db, &mut block_env);
1619 }
1620
1621 for (req_idx, request) in calls.into_iter().enumerate() {
1623 let fee_details = FeeDetails::new(
1624 request.gas_price,
1625 request.max_fee_per_gas,
1626 request.max_priority_fee_per_gas,
1627 request.max_fee_per_blob_gas,
1628 )?
1629 .or_zero_fees();
1630
1631 let mut env = self.build_call_env(
1632 WithOtherFields::new(request.clone()),
1633 fee_details,
1634 block_env.clone(),
1635 );
1636
1637 env.evm_env.cfg_env.disable_eip3607 = true;
1639
1640 if !validation {
1641 env.evm_env.cfg_env.disable_base_fee = !validation;
1642 env.evm_env.block_env.basefee = 0;
1643 }
1644
1645 let ResultAndState { result, state } = if trace_transfers {
1647 let mut inspector = TransferInspector::new(false).with_logs(true);
1650 let mut evm= self.new_evm_with_inspector_ref(
1651 cache_db.as_dyn(),
1652 &env,
1653 &mut inspector,
1654 );
1655
1656 trace!(target: "backend", env=?env.evm_env, spec=?env.evm_env.spec_id(),"simulate evm env");
1657 evm.transact(env.tx)?
1658 } else {
1659 let mut inspector = self.build_inspector();
1660 let mut evm = self.new_evm_with_inspector_ref(
1661 cache_db.as_dyn(),
1662 &env,
1663 &mut inspector,
1664 );
1665 trace!(target: "backend", env=?env.evm_env, spec=?env.evm_env.spec_id(),"simulate evm env");
1666 evm.transact(env.tx)?
1667 };
1668 trace!(target: "backend", ?result, ?request, "simulate call");
1669
1670 cache_db.commit(state);
1672 gas_used += result.gas_used();
1673
1674 let from = request.from.unwrap_or_default();
1677 let request =
1678 transaction_request_to_typed(WithOtherFields::new(request)).unwrap();
1679 let tx = build_typed_transaction(
1680 request,
1681 Signature::new(Default::default(), Default::default(), false),
1682 )?;
1683 let rpc_tx = transaction_build(
1684 None,
1685 MaybeImpersonatedTransaction::impersonated(tx, from),
1686 None,
1687 None,
1688 Some(block_env.basefee),
1689 );
1690 transactions.push(rpc_tx);
1691
1692 let return_data = result.output().cloned().unwrap_or_default();
1693 let sim_res = SimCallResult {
1694 return_data,
1695 gas_used: result.gas_used(),
1696 status: result.is_success(),
1697 error: result.is_success().not().then(|| {
1698 alloy_rpc_types::simulate::SimulateError {
1699 code: -3200,
1700 message: "execution failed".to_string(),
1701 }
1702 }),
1703 logs: result.clone()
1704 .into_logs()
1705 .into_iter()
1706 .enumerate()
1707 .map(|(idx, log)| Log {
1708 inner: log,
1709 block_number: Some(block_env.number),
1710 block_timestamp: Some(block_env.timestamp),
1711 transaction_index: Some(req_idx as u64),
1712 log_index: Some((idx + log_index) as u64),
1713 removed: false,
1714
1715 block_hash: None,
1716 transaction_hash: None,
1717 })
1718 .collect(),
1719 };
1720 let receipt = Receipt {
1721 status: result.is_success().into(),
1722 cumulative_gas_used: result.gas_used(),
1723 logs:sim_res.logs.clone()
1724 };
1725 receipts.push(receipt.with_bloom());
1726 logs.extend(sim_res.logs.clone().iter().map(|log| log.inner.clone()));
1727 log_index += sim_res.logs.len();
1728 call_res.push(sim_res);
1729 }
1730 let transactions_envelopes: Vec<AnyTxEnvelope> = transactions
1731 .iter()
1732 .map(|tx| AnyTxEnvelope::from(tx.clone()))
1733 .collect();
1734 let header = Header {
1735 logs_bloom: logs_bloom(logs.iter()),
1736 transactions_root: calculate_transaction_root(&transactions_envelopes),
1737 receipts_root: calculate_receipt_root(&transactions_envelopes),
1738 parent_hash: Default::default(),
1739 ommers_hash: Default::default(),
1740 beneficiary: block_env.beneficiary,
1741 state_root: Default::default(),
1742 difficulty: Default::default(),
1743 number: block_env.number,
1744 gas_limit: block_env.gas_limit,
1745 gas_used,
1746 timestamp: block_env.timestamp,
1747 extra_data: Default::default(),
1748 mix_hash: Default::default(),
1749 nonce: Default::default(),
1750 base_fee_per_gas: Some(block_env.basefee),
1751 withdrawals_root: None,
1752 blob_gas_used: None,
1753 excess_blob_gas: None,
1754 parent_beacon_block_root: None,
1755 requests_hash: None,
1756 };
1757 let mut block = alloy_rpc_types::Block {
1758 header: AnyRpcHeader {
1759 hash: header.hash_slow(),
1760 inner: header.into(),
1761 total_difficulty: None,
1762 size: None,
1763 },
1764 uncles: vec![],
1765 transactions: BlockTransactions::Full(transactions),
1766 withdrawals: None,
1767 };
1768
1769 if !return_full_transactions {
1770 block.transactions.convert_to_hashes();
1771 }
1772
1773 let simulated_block = SimulatedBlock {
1774 inner: AnyRpcBlock::new(WithOtherFields::new(block)),
1775 calls: call_res,
1776 };
1777
1778 block_env.number += 1;
1780 block_env.timestamp += 12;
1781 block_env.basefee = simulated_block
1782 .inner
1783 .header
1784 .next_block_base_fee(BaseFeeParams::ethereum())
1785 .unwrap_or_default();
1786
1787 block_res.push(simulated_block);
1788 }
1789
1790 Ok(block_res)
1791 })
1792 .await?
1793 }
1794
1795 pub fn call_with_state(
1796 &self,
1797 state: &dyn DatabaseRef<Error = DatabaseError>,
1798 request: WithOtherFields<TransactionRequest>,
1799 fee_details: FeeDetails,
1800 block_env: BlockEnv,
1801 ) -> Result<(InstructionResult, Option<Output>, u128, State), BlockchainError> {
1802 let mut inspector = self.build_inspector();
1803
1804 let env = self.build_call_env(request, fee_details, block_env);
1805 let mut evm = self.new_evm_with_inspector_ref(state, &env, &mut inspector);
1806 let ResultAndState { result, state } = evm.transact(env.tx)?;
1807 let (exit_reason, gas_used, out) = match result {
1808 ExecutionResult::Success { reason, gas_used, output, .. } => {
1809 (reason.into(), gas_used, Some(output))
1810 }
1811 ExecutionResult::Revert { gas_used, output } => {
1812 (InstructionResult::Revert, gas_used, Some(Output::Call(output)))
1813 }
1814 ExecutionResult::Halt { reason, gas_used } => {
1815 (op_haltreason_to_instruction_result(reason), gas_used, None)
1816 }
1817 };
1818 drop(evm);
1819 inspector.print_logs();
1820
1821 if self.print_traces {
1822 inspector.into_print_traces();
1823 }
1824
1825 Ok((exit_reason, out, gas_used as u128, state))
1826 }
1827
1828 pub async fn call_with_tracing(
1829 &self,
1830 request: WithOtherFields<TransactionRequest>,
1831 fee_details: FeeDetails,
1832 block_request: Option<BlockRequest>,
1833 opts: GethDebugTracingCallOptions,
1834 ) -> Result<GethTrace, BlockchainError> {
1835 let GethDebugTracingCallOptions { tracing_options, block_overrides, state_overrides } =
1836 opts;
1837 let GethDebugTracingOptions { config, tracer, tracer_config, .. } = tracing_options;
1838
1839 self.with_database_at(block_request, |state, mut block| {
1840 let block_number = block.number;
1841
1842 let mut cache_db = CacheDB::new(state);
1843 if let Some(state_overrides) = state_overrides {
1844 state::apply_state_overrides(state_overrides, &mut cache_db)?;
1845 }
1846 if let Some(block_overrides) = block_overrides {
1847 state::apply_block_overrides(block_overrides, &mut cache_db, &mut block);
1848 }
1849
1850 if let Some(tracer) = tracer {
1851 return match tracer {
1852 GethDebugTracerType::BuiltInTracer(tracer) => match tracer {
1853 GethDebugBuiltInTracerType::CallTracer => {
1854 let call_config = tracer_config
1855 .into_call_config()
1856 .map_err(|e| (RpcError::invalid_params(e.to_string())))?;
1857
1858 let mut inspector = self.build_inspector().with_tracing_config(
1859 TracingInspectorConfig::from_geth_call_config(&call_config),
1860 );
1861
1862 let env = self.build_call_env(request, fee_details, block);
1863 let mut evm = self.new_evm_with_inspector_ref(
1864 cache_db.as_dyn(),
1865 &env,
1866 &mut inspector,
1867 );
1868 let ResultAndState { result, state: _ } = evm.transact(env.tx)?;
1869
1870 drop(evm);
1871 let tracing_inspector = inspector.tracer.expect("tracer disappeared");
1872
1873 Ok(tracing_inspector
1874 .into_geth_builder()
1875 .geth_call_traces(call_config, result.gas_used())
1876 .into())
1877 }
1878 GethDebugBuiltInTracerType::NoopTracer => Ok(NoopFrame::default().into()),
1879 GethDebugBuiltInTracerType::FourByteTracer |
1880 GethDebugBuiltInTracerType::PreStateTracer |
1881 GethDebugBuiltInTracerType::MuxTracer |
1882 GethDebugBuiltInTracerType::FlatCallTracer => {
1883 Err(RpcError::invalid_params("unsupported tracer type").into())
1884 }
1885 },
1886
1887 GethDebugTracerType::JsTracer(_code) => {
1888 Err(RpcError::invalid_params("unsupported tracer type").into())
1889 }
1890 }
1891 }
1892
1893 let mut inspector = self
1895 .build_inspector()
1896 .with_tracing_config(TracingInspectorConfig::from_geth_config(&config));
1897
1898 let env = self.build_call_env(request, fee_details, block);
1899 let mut evm = self.new_evm_with_inspector_ref(cache_db.as_dyn(), &env, &mut inspector);
1900 let ResultAndState { result, state: _ } = evm.transact(env.tx)?;
1901
1902 let (exit_reason, gas_used, out) = match result {
1903 ExecutionResult::Success { reason, gas_used, output, .. } => {
1904 (reason.into(), gas_used, Some(output))
1905 }
1906 ExecutionResult::Revert { gas_used, output } => {
1907 (InstructionResult::Revert, gas_used, Some(Output::Call(output)))
1908 }
1909 ExecutionResult::Halt { reason, gas_used } => {
1910 (op_haltreason_to_instruction_result(reason), gas_used, None)
1911 }
1912 };
1913
1914 drop(evm);
1915 let tracing_inspector = inspector.tracer.expect("tracer disappeared");
1916 let return_value = out.as_ref().map(|o| o.data().clone()).unwrap_or_default();
1917
1918 trace!(target: "backend", ?exit_reason, ?out, %gas_used, %block_number, "trace call");
1919
1920 let res = tracing_inspector
1921 .into_geth_builder()
1922 .geth_traces(gas_used, return_value, config)
1923 .into();
1924
1925 Ok(res)
1926 })
1927 .await?
1928 }
1929
1930 pub fn build_access_list_with_state(
1931 &self,
1932 state: &dyn DatabaseRef<Error = DatabaseError>,
1933 request: WithOtherFields<TransactionRequest>,
1934 fee_details: FeeDetails,
1935 block_env: BlockEnv,
1936 ) -> Result<(InstructionResult, Option<Output>, u64, AccessList), BlockchainError> {
1937 let mut inspector =
1938 AccessListInspector::new(request.access_list.clone().unwrap_or_default());
1939
1940 let env = self.build_call_env(request, fee_details, block_env);
1941 let mut evm = self.new_evm_with_inspector_ref(state, &env, &mut inspector);
1942 let ResultAndState { result, state: _ } = evm.transact(env.tx)?;
1943 let (exit_reason, gas_used, out) = match result {
1944 ExecutionResult::Success { reason, gas_used, output, .. } => {
1945 (reason.into(), gas_used, Some(output))
1946 }
1947 ExecutionResult::Revert { gas_used, output } => {
1948 (InstructionResult::Revert, gas_used, Some(Output::Call(output)))
1949 }
1950 ExecutionResult::Halt { reason, gas_used } => {
1951 (op_haltreason_to_instruction_result(reason), gas_used, None)
1952 }
1953 };
1954 drop(evm);
1955 let access_list = inspector.access_list();
1956 Ok((exit_reason, out, gas_used, access_list))
1957 }
1958
1959 fn get_receipts(&self, tx_hashes: impl IntoIterator<Item = TxHash>) -> Vec<TypedReceipt> {
1961 let storage = self.blockchain.storage.read();
1962 let mut receipts = vec![];
1963
1964 for hash in tx_hashes {
1965 if let Some(tx) = storage.transactions.get(&hash) {
1966 receipts.push(tx.receipt.clone());
1967 }
1968 }
1969
1970 receipts
1971 }
1972
1973 async fn logs_for_block(
1975 &self,
1976 filter: Filter,
1977 hash: B256,
1978 ) -> Result<Vec<Log>, BlockchainError> {
1979 if let Some(block) = self.blockchain.get_block_by_hash(&hash) {
1980 return Ok(self.mined_logs_for_block(filter, block));
1981 }
1982
1983 if let Some(fork) = self.get_fork() {
1984 return Ok(fork.logs(&filter).await?);
1985 }
1986
1987 Ok(Vec::new())
1988 }
1989
1990 fn mined_logs_for_block(&self, filter: Filter, block: Block) -> Vec<Log> {
1992 let mut all_logs = Vec::new();
1993 let block_hash = block.header.hash_slow();
1994 let mut block_log_index = 0u32;
1995
1996 let storage = self.blockchain.storage.read();
1997
1998 for tx in block.transactions {
1999 let Some(tx) = storage.transactions.get(&tx.hash()) else {
2000 continue;
2001 };
2002
2003 let logs = tx.receipt.logs();
2004 let transaction_hash = tx.info.transaction_hash;
2005
2006 for log in logs {
2007 if filter.matches(log) {
2008 all_logs.push(Log {
2009 inner: log.clone(),
2010 block_hash: Some(block_hash),
2011 block_number: Some(block.header.number),
2012 block_timestamp: Some(block.header.timestamp),
2013 transaction_hash: Some(transaction_hash),
2014 transaction_index: Some(tx.info.transaction_index),
2015 log_index: Some(block_log_index as u64),
2016 removed: false,
2017 });
2018 }
2019 block_log_index += 1;
2020 }
2021 }
2022 all_logs
2023 }
2024
2025 async fn logs_for_range(
2027 &self,
2028 filter: &Filter,
2029 mut from: u64,
2030 to: u64,
2031 ) -> Result<Vec<Log>, BlockchainError> {
2032 let mut all_logs = Vec::new();
2033
2034 if let Some(fork) = self.get_fork() {
2036 let mut to_on_fork = to;
2037
2038 if !fork.predates_fork(to) {
2039 to_on_fork = fork.block_number();
2041 }
2042
2043 if fork.predates_fork_inclusive(from) {
2044 let filter = filter.clone().from_block(from).to_block(to_on_fork);
2046 all_logs = fork.logs(&filter).await?;
2047
2048 from = fork.block_number() + 1;
2050 }
2051 }
2052
2053 for number in from..=to {
2054 if let Some(block) = self.get_block(number) {
2055 all_logs.extend(self.mined_logs_for_block(filter.clone(), block));
2056 }
2057 }
2058
2059 Ok(all_logs)
2060 }
2061
2062 pub async fn logs(&self, filter: Filter) -> Result<Vec<Log>, BlockchainError> {
2064 trace!(target: "backend", "get logs [{:?}]", filter);
2065 if let Some(hash) = filter.get_block_hash() {
2066 self.logs_for_block(filter, hash).await
2067 } else {
2068 let best = self.best_number();
2069 let to_block =
2070 self.convert_block_number(filter.block_option.get_to_block().copied()).min(best);
2071 let from_block =
2072 self.convert_block_number(filter.block_option.get_from_block().copied());
2073 if from_block > best {
2074 return Ok(vec![]);
2076 }
2077
2078 self.logs_for_range(&filter, from_block, to_block).await
2079 }
2080 }
2081
2082 pub async fn block_by_hash(&self, hash: B256) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2083 trace!(target: "backend", "get block by hash {:?}", hash);
2084 if let tx @ Some(_) = self.mined_block_by_hash(hash) {
2085 return Ok(tx);
2086 }
2087
2088 if let Some(fork) = self.get_fork() {
2089 return Ok(fork.block_by_hash(hash).await?);
2090 }
2091
2092 Ok(None)
2093 }
2094
2095 pub async fn block_by_hash_full(
2096 &self,
2097 hash: B256,
2098 ) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2099 trace!(target: "backend", "get block by hash {:?}", hash);
2100 if let tx @ Some(_) = self.get_full_block(hash) {
2101 return Ok(tx);
2102 }
2103
2104 if let Some(fork) = self.get_fork() {
2105 return Ok(fork.block_by_hash_full(hash).await?)
2106 }
2107
2108 Ok(None)
2109 }
2110
2111 fn mined_block_by_hash(&self, hash: B256) -> Option<AnyRpcBlock> {
2112 let block = self.blockchain.get_block_by_hash(&hash)?;
2113 Some(self.convert_block(block))
2114 }
2115
2116 pub(crate) async fn mined_transactions_by_block_number(
2117 &self,
2118 number: BlockNumber,
2119 ) -> Option<Vec<AnyRpcTransaction>> {
2120 if let Some(block) = self.get_block(number) {
2121 return self.mined_transactions_in_block(&block);
2122 }
2123 None
2124 }
2125
2126 pub(crate) fn mined_transactions_in_block(
2128 &self,
2129 block: &Block,
2130 ) -> Option<Vec<AnyRpcTransaction>> {
2131 let mut transactions = Vec::with_capacity(block.transactions.len());
2132 let base_fee = block.header.base_fee_per_gas;
2133 let storage = self.blockchain.storage.read();
2134 for hash in block.transactions.iter().map(|tx| tx.hash()) {
2135 let info = storage.transactions.get(&hash)?.info.clone();
2136 let tx = block.transactions.get(info.transaction_index as usize)?.clone();
2137
2138 let tx = transaction_build(Some(hash), tx, Some(block), Some(info), base_fee);
2139 transactions.push(tx);
2140 }
2141 Some(transactions)
2142 }
2143
2144 pub async fn block_by_number(
2145 &self,
2146 number: BlockNumber,
2147 ) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2148 trace!(target: "backend", "get block by number {:?}", number);
2149 if let tx @ Some(_) = self.mined_block_by_number(number) {
2150 return Ok(tx);
2151 }
2152
2153 if let Some(fork) = self.get_fork() {
2154 let number = self.convert_block_number(Some(number));
2155 if fork.predates_fork_inclusive(number) {
2156 return Ok(fork.block_by_number(number).await?)
2157 }
2158 }
2159
2160 Ok(None)
2161 }
2162
2163 pub async fn block_by_number_full(
2164 &self,
2165 number: BlockNumber,
2166 ) -> Result<Option<AnyRpcBlock>, BlockchainError> {
2167 trace!(target: "backend", "get block by number {:?}", number);
2168 if let tx @ Some(_) = self.get_full_block(number) {
2169 return Ok(tx);
2170 }
2171
2172 if let Some(fork) = self.get_fork() {
2173 let number = self.convert_block_number(Some(number));
2174 if fork.predates_fork_inclusive(number) {
2175 return Ok(fork.block_by_number_full(number).await?)
2176 }
2177 }
2178
2179 Ok(None)
2180 }
2181
2182 pub fn get_block(&self, id: impl Into<BlockId>) -> Option<Block> {
2183 let hash = match id.into() {
2184 BlockId::Hash(hash) => hash.block_hash,
2185 BlockId::Number(number) => {
2186 let storage = self.blockchain.storage.read();
2187 let slots_in_an_epoch = self.slots_in_an_epoch;
2188 match number {
2189 BlockNumber::Latest => storage.best_hash,
2190 BlockNumber::Earliest => storage.genesis_hash,
2191 BlockNumber::Pending => return None,
2192 BlockNumber::Number(num) => *storage.hashes.get(&num)?,
2193 BlockNumber::Safe => {
2194 if storage.best_number > (slots_in_an_epoch) {
2195 *storage.hashes.get(&(storage.best_number - (slots_in_an_epoch)))?
2196 } else {
2197 storage.genesis_hash }
2199 }
2200 BlockNumber::Finalized => {
2201 if storage.best_number > (slots_in_an_epoch * 2) {
2202 *storage.hashes.get(&(storage.best_number - (slots_in_an_epoch * 2)))?
2203 } else {
2204 storage.genesis_hash
2205 }
2206 }
2207 }
2208 }
2209 };
2210 self.get_block_by_hash(hash)
2211 }
2212
2213 pub fn get_block_by_hash(&self, hash: B256) -> Option<Block> {
2214 self.blockchain.get_block_by_hash(&hash)
2215 }
2216
2217 pub fn mined_block_by_number(&self, number: BlockNumber) -> Option<AnyRpcBlock> {
2218 let block = self.get_block(number)?;
2219 let mut block = self.convert_block(block);
2220 block.transactions.convert_to_hashes();
2221 Some(block)
2222 }
2223
2224 pub fn get_full_block(&self, id: impl Into<BlockId>) -> Option<AnyRpcBlock> {
2225 let block = self.get_block(id)?;
2226 let transactions = self.mined_transactions_in_block(&block)?;
2227 let mut block = self.convert_block(block);
2228 block.inner.transactions = BlockTransactions::Full(transactions);
2229
2230 Some(block)
2231 }
2232
2233 pub fn convert_block(&self, block: Block) -> AnyRpcBlock {
2235 let size = U256::from(alloy_rlp::encode(&block).len() as u32);
2236
2237 let Block { header, transactions, .. } = block;
2238
2239 let hash = header.hash_slow();
2240 let Header { number, withdrawals_root, .. } = header;
2241
2242 let block = AlloyBlock {
2243 header: AlloyHeader {
2244 inner: AnyHeader::from(header),
2245 hash,
2246 total_difficulty: Some(self.total_difficulty()),
2247 size: Some(size),
2248 },
2249 transactions: alloy_rpc_types::BlockTransactions::Hashes(
2250 transactions.into_iter().map(|tx| tx.hash()).collect(),
2251 ),
2252 uncles: vec![],
2253 withdrawals: withdrawals_root.map(|_| Default::default()),
2254 };
2255
2256 let mut block = WithOtherFields::new(block);
2257
2258 if is_arbitrum(self.env.read().evm_env.cfg_env.chain_id) {
2260 block.other.insert("l1BlockNumber".to_string(), number.into());
2262 }
2263
2264 AnyRpcBlock::from(block)
2265 }
2266
2267 pub async fn ensure_block_number<T: Into<BlockId>>(
2273 &self,
2274 block_id: Option<T>,
2275 ) -> Result<u64, BlockchainError> {
2276 let current = self.best_number();
2277 let requested =
2278 match block_id.map(Into::into).unwrap_or(BlockId::Number(BlockNumber::Latest)) {
2279 BlockId::Hash(hash) => {
2280 self.block_by_hash(hash.block_hash)
2281 .await?
2282 .ok_or(BlockchainError::BlockNotFound)?
2283 .header
2284 .number
2285 }
2286 BlockId::Number(num) => match num {
2287 BlockNumber::Latest | BlockNumber::Pending => self.best_number(),
2288 BlockNumber::Earliest => U64::ZERO.to::<u64>(),
2289 BlockNumber::Number(num) => num,
2290 BlockNumber::Safe => current.saturating_sub(self.slots_in_an_epoch),
2291 BlockNumber::Finalized => current.saturating_sub(self.slots_in_an_epoch * 2),
2292 },
2293 };
2294
2295 if requested > current {
2296 Err(BlockchainError::BlockOutOfRange(current, requested))
2297 } else {
2298 Ok(requested)
2299 }
2300 }
2301
2302 pub fn convert_block_number(&self, block: Option<BlockNumber>) -> u64 {
2303 let current = self.best_number();
2304 match block.unwrap_or(BlockNumber::Latest) {
2305 BlockNumber::Latest | BlockNumber::Pending => current,
2306 BlockNumber::Earliest => 0,
2307 BlockNumber::Number(num) => num,
2308 BlockNumber::Safe => current.saturating_sub(self.slots_in_an_epoch),
2309 BlockNumber::Finalized => current.saturating_sub(self.slots_in_an_epoch * 2),
2310 }
2311 }
2312
2313 pub async fn with_database_at<F, T>(
2315 &self,
2316 block_request: Option<BlockRequest>,
2317 f: F,
2318 ) -> Result<T, BlockchainError>
2319 where
2320 F: FnOnce(Box<dyn MaybeFullDatabase + '_>, BlockEnv) -> T,
2321 {
2322 let block_number = match block_request {
2323 Some(BlockRequest::Pending(pool_transactions)) => {
2324 let result = self
2325 .with_pending_block(pool_transactions, |state, block| {
2326 let block = block.block;
2327 let block = BlockEnv {
2328 number: block.header.number,
2329 beneficiary: block.header.beneficiary,
2330 timestamp: block.header.timestamp,
2331 difficulty: block.header.difficulty,
2332 prevrandao: Some(block.header.mix_hash),
2333 basefee: block.header.base_fee_per_gas.unwrap_or_default(),
2334 gas_limit: block.header.gas_limit,
2335 ..Default::default()
2336 };
2337 f(state, block)
2338 })
2339 .await;
2340 return Ok(result);
2341 }
2342 Some(BlockRequest::Number(bn)) => Some(BlockNumber::Number(bn)),
2343 None => None,
2344 };
2345 let block_number = self.convert_block_number(block_number);
2346
2347 if block_number < self.env.read().evm_env.block_env.number {
2348 if let Some((block_hash, block)) = self
2349 .block_by_number(BlockNumber::Number(block_number))
2350 .await?
2351 .map(|block| (block.header.hash, block))
2352 {
2353 if let Some(state) = self.states.write().get(&block_hash) {
2354 let block = BlockEnv {
2355 number: block_number,
2356 beneficiary: block.header.beneficiary,
2357 timestamp: block.header.timestamp,
2358 difficulty: block.header.difficulty,
2359 prevrandao: block.header.mix_hash,
2360 basefee: block.header.base_fee_per_gas.unwrap_or_default(),
2361 gas_limit: block.header.gas_limit,
2362 ..Default::default()
2363 };
2364 return Ok(f(Box::new(state), block));
2365 }
2366 }
2367
2368 warn!(target: "backend", "Not historic state found for block={}", block_number);
2369 return Err(BlockchainError::BlockOutOfRange(
2370 self.env.read().evm_env.block_env.number,
2371 block_number,
2372 ));
2373 }
2374
2375 let db = self.db.read().await;
2376 let block = self.env.read().evm_env.block_env.clone();
2377 Ok(f(Box::new(&**db), block))
2378 }
2379
2380 pub async fn storage_at(
2381 &self,
2382 address: Address,
2383 index: U256,
2384 block_request: Option<BlockRequest>,
2385 ) -> Result<B256, BlockchainError> {
2386 self.with_database_at(block_request, |db, _| {
2387 trace!(target: "backend", "get storage for {:?} at {:?}", address, index);
2388 let val = db.storage_ref(address, index)?;
2389 Ok(val.into())
2390 })
2391 .await?
2392 }
2393
2394 pub async fn get_code(
2399 &self,
2400 address: Address,
2401 block_request: Option<BlockRequest>,
2402 ) -> Result<Bytes, BlockchainError> {
2403 self.with_database_at(block_request, |db, _| self.get_code_with_state(&db, address)).await?
2404 }
2405
2406 pub fn get_code_with_state(
2407 &self,
2408 state: &dyn DatabaseRef<Error = DatabaseError>,
2409 address: Address,
2410 ) -> Result<Bytes, BlockchainError> {
2411 trace!(target: "backend", "get code for {:?}", address);
2412 let account = state.basic_ref(address)?.unwrap_or_default();
2413 if account.code_hash == KECCAK_EMPTY {
2414 return Ok(Default::default());
2416 }
2417 let code = if let Some(code) = account.code {
2418 code
2419 } else {
2420 state.code_by_hash_ref(account.code_hash)?
2421 };
2422 Ok(code.bytes()[..code.len()].to_vec().into())
2423 }
2424
2425 pub async fn get_balance(
2429 &self,
2430 address: Address,
2431 block_request: Option<BlockRequest>,
2432 ) -> Result<U256, BlockchainError> {
2433 self.with_database_at(block_request, |db, _| self.get_balance_with_state(db, address))
2434 .await?
2435 }
2436
2437 pub async fn get_account_at_block(
2438 &self,
2439 address: Address,
2440 block_request: Option<BlockRequest>,
2441 ) -> Result<Account, BlockchainError> {
2442 self.with_database_at(block_request, |block_db, _| {
2443 let db = block_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?;
2444 let account = db.get(&address).cloned().unwrap_or_default();
2445 let storage_root = storage_root(&account.storage);
2446 let code_hash = account.info.code_hash;
2447 let balance = account.info.balance;
2448 let nonce = account.info.nonce;
2449 Ok(Account { balance, nonce, code_hash, storage_root })
2450 })
2451 .await?
2452 }
2453
2454 pub fn get_balance_with_state<D>(
2455 &self,
2456 state: D,
2457 address: Address,
2458 ) -> Result<U256, BlockchainError>
2459 where
2460 D: DatabaseRef<Error = DatabaseError>,
2461 {
2462 trace!(target: "backend", "get balance for {:?}", address);
2463 Ok(state.basic_ref(address)?.unwrap_or_default().balance)
2464 }
2465
2466 pub async fn get_nonce(
2470 &self,
2471 address: Address,
2472 block_request: BlockRequest,
2473 ) -> Result<u64, BlockchainError> {
2474 if let BlockRequest::Pending(pool_transactions) = &block_request {
2475 if let Some(value) = get_pool_transactions_nonce(pool_transactions, address) {
2476 return Ok(value);
2477 }
2478 }
2479 let final_block_request = match block_request {
2480 BlockRequest::Pending(_) => BlockRequest::Number(self.best_number()),
2481 BlockRequest::Number(bn) => BlockRequest::Number(bn),
2482 };
2483
2484 self.with_database_at(Some(final_block_request), |db, _| {
2485 trace!(target: "backend", "get nonce for {:?}", address);
2486 Ok(db.basic_ref(address)?.unwrap_or_default().nonce)
2487 })
2488 .await?
2489 }
2490
2491 pub async fn trace_transaction(
2493 &self,
2494 hash: B256,
2495 ) -> Result<Vec<LocalizedTransactionTrace>, BlockchainError> {
2496 if let Some(traces) = self.mined_parity_trace_transaction(hash) {
2497 return Ok(traces);
2498 }
2499
2500 if let Some(fork) = self.get_fork() {
2501 return Ok(fork.trace_transaction(hash).await?)
2502 }
2503
2504 Ok(vec![])
2505 }
2506
2507 pub(crate) fn mined_parity_trace_transaction(
2509 &self,
2510 hash: B256,
2511 ) -> Option<Vec<LocalizedTransactionTrace>> {
2512 self.blockchain.storage.read().transactions.get(&hash).map(|tx| tx.parity_traces())
2513 }
2514
2515 pub(crate) fn mined_transaction(&self, hash: B256) -> Option<MinedTransaction> {
2517 self.blockchain.storage.read().transactions.get(&hash).cloned()
2518 }
2519
2520 pub(crate) fn mined_parity_trace_block(
2522 &self,
2523 block: u64,
2524 ) -> Option<Vec<LocalizedTransactionTrace>> {
2525 let block = self.get_block(block)?;
2526 let mut traces = vec![];
2527 let storage = self.blockchain.storage.read();
2528 for tx in block.transactions {
2529 traces.extend(storage.transactions.get(&tx.hash())?.parity_traces());
2530 }
2531 Some(traces)
2532 }
2533
2534 pub async fn debug_trace_transaction(
2536 &self,
2537 hash: B256,
2538 opts: GethDebugTracingOptions,
2539 ) -> Result<GethTrace, BlockchainError> {
2540 if let Some(trace) = self.mined_geth_trace_transaction(hash, opts.clone()) {
2541 return trace;
2542 }
2543
2544 if let Some(fork) = self.get_fork() {
2545 return Ok(fork.debug_trace_transaction(hash, opts).await?)
2546 }
2547
2548 Ok(GethTrace::Default(Default::default()))
2549 }
2550
2551 fn mined_geth_trace_transaction(
2552 &self,
2553 hash: B256,
2554 opts: GethDebugTracingOptions,
2555 ) -> Option<Result<GethTrace, BlockchainError>> {
2556 self.blockchain.storage.read().transactions.get(&hash).map(|tx| tx.geth_trace(opts))
2557 }
2558
2559 pub async fn trace_block(
2561 &self,
2562 block: BlockNumber,
2563 ) -> Result<Vec<LocalizedTransactionTrace>, BlockchainError> {
2564 let number = self.convert_block_number(Some(block));
2565 if let Some(traces) = self.mined_parity_trace_block(number) {
2566 return Ok(traces);
2567 }
2568
2569 if let Some(fork) = self.get_fork() {
2570 if fork.predates_fork(number) {
2571 return Ok(fork.trace_block(number).await?)
2572 }
2573 }
2574
2575 Ok(vec![])
2576 }
2577
2578 pub async fn transaction_receipt(
2579 &self,
2580 hash: B256,
2581 ) -> Result<Option<ReceiptResponse>, BlockchainError> {
2582 if let Some(receipt) = self.mined_transaction_receipt(hash) {
2583 return Ok(Some(receipt.inner));
2584 }
2585
2586 if let Some(fork) = self.get_fork() {
2587 let receipt = fork.transaction_receipt(hash).await?;
2588 let number = self.convert_block_number(
2589 receipt.clone().and_then(|r| r.block_number).map(BlockNumber::from),
2590 );
2591
2592 if fork.predates_fork_inclusive(number) {
2593 return Ok(receipt);
2594 }
2595 }
2596
2597 Ok(None)
2598 }
2599
2600 pub async fn trace_filter(
2602 &self,
2603 filter: TraceFilter,
2604 ) -> Result<Vec<LocalizedTransactionTrace>, BlockchainError> {
2605 let matcher = filter.matcher();
2606 let start = filter.from_block.unwrap_or(0);
2607 let end = filter.to_block.unwrap_or_else(|| self.best_number());
2608
2609 if start > end {
2610 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2611 "invalid block range, ensure that to block is greater than from block".to_string(),
2612 )));
2613 }
2614
2615 let dist = end - start;
2616 if dist > 300 {
2617 return Err(BlockchainError::RpcError(RpcError::invalid_params(
2618 "block range too large, currently limited to 300".to_string(),
2619 )));
2620 }
2621
2622 let mut trace_tasks = vec![];
2624 for num in start..=end {
2625 trace_tasks.push(self.trace_block(num.into()));
2626 }
2627
2628 let traces = futures::future::try_join_all(trace_tasks).await?;
2630 let filtered_traces =
2631 traces.into_iter().flatten().filter(|trace| matcher.matches(&trace.trace));
2632
2633 let filtered_traces: Vec<_> = if let Some(after) = filter.after {
2635 filtered_traces.skip(after as usize).collect()
2636 } else {
2637 filtered_traces.collect()
2638 };
2639
2640 let filtered_traces: Vec<_> = if let Some(count) = filter.count {
2641 filtered_traces.into_iter().take(count as usize).collect()
2642 } else {
2643 filtered_traces
2644 };
2645
2646 Ok(filtered_traces)
2647 }
2648
2649 pub fn mined_receipts(&self, hash: B256) -> Option<Vec<TypedReceipt>> {
2651 let block = self.mined_block_by_hash(hash)?;
2652 let mut receipts = Vec::new();
2653 let storage = self.blockchain.storage.read();
2654 for tx in block.transactions.hashes() {
2655 let receipt = storage.transactions.get(&tx)?.receipt.clone();
2656 receipts.push(receipt);
2657 }
2658 Some(receipts)
2659 }
2660
2661 pub fn mined_block_receipts(&self, id: impl Into<BlockId>) -> Option<Vec<ReceiptResponse>> {
2663 let mut receipts = Vec::new();
2664 let block = self.get_block(id)?;
2665
2666 for transaction in block.transactions {
2667 let receipt = self.mined_transaction_receipt(transaction.hash())?;
2668 receipts.push(receipt.inner);
2669 }
2670
2671 Some(receipts)
2672 }
2673
2674 pub(crate) fn mined_transaction_receipt(&self, hash: B256) -> Option<MinedTransactionReceipt> {
2676 let MinedTransaction { info, receipt: tx_receipt, block_hash, .. } =
2677 self.blockchain.get_transaction_by_hash(&hash)?;
2678
2679 let index = info.transaction_index as usize;
2680 let block = self.blockchain.get_block_by_hash(&block_hash)?;
2681 let transaction = block.transactions[index].clone();
2682
2683 let excess_blob_gas = block.header.excess_blob_gas;
2685 let blob_gas_price =
2686 alloy_eips::eip4844::calc_blob_gasprice(excess_blob_gas.unwrap_or_default());
2687 let blob_gas_used = transaction.blob_gas();
2688
2689 let effective_gas_price = match transaction.transaction {
2690 TypedTransaction::Legacy(t) => t.tx().gas_price,
2691 TypedTransaction::EIP2930(t) => t.tx().gas_price,
2692 TypedTransaction::EIP1559(t) => block
2693 .header
2694 .base_fee_per_gas
2695 .map_or(self.base_fee() as u128, |g| g as u128)
2696 .saturating_add(t.tx().max_priority_fee_per_gas),
2697 TypedTransaction::EIP4844(t) => block
2698 .header
2699 .base_fee_per_gas
2700 .map_or(self.base_fee() as u128, |g| g as u128)
2701 .saturating_add(t.tx().tx().max_priority_fee_per_gas),
2702 TypedTransaction::EIP7702(t) => block
2703 .header
2704 .base_fee_per_gas
2705 .map_or(self.base_fee() as u128, |g| g as u128)
2706 .saturating_add(t.tx().max_priority_fee_per_gas),
2707 TypedTransaction::Deposit(_) => 0_u128,
2708 };
2709
2710 let receipts = self.get_receipts(block.transactions.iter().map(|tx| tx.hash()));
2711 let next_log_index = receipts[..index].iter().map(|r| r.logs().len()).sum::<usize>();
2712
2713 let receipt = tx_receipt.as_receipt_with_bloom().receipt.clone();
2714 let receipt = Receipt {
2715 status: receipt.status,
2716 cumulative_gas_used: receipt.cumulative_gas_used,
2717 logs: receipt
2718 .logs
2719 .into_iter()
2720 .enumerate()
2721 .map(|(index, log)| alloy_rpc_types::Log {
2722 inner: log,
2723 block_hash: Some(block_hash),
2724 block_number: Some(block.header.number),
2725 block_timestamp: Some(block.header.timestamp),
2726 transaction_hash: Some(info.transaction_hash),
2727 transaction_index: Some(info.transaction_index),
2728 log_index: Some((next_log_index + index) as u64),
2729 removed: false,
2730 })
2731 .collect(),
2732 };
2733 let receipt_with_bloom =
2734 ReceiptWithBloom { receipt, logs_bloom: tx_receipt.as_receipt_with_bloom().logs_bloom };
2735
2736 let inner = match tx_receipt {
2737 TypedReceipt::EIP1559(_) => TypedReceipt::EIP1559(receipt_with_bloom),
2738 TypedReceipt::Legacy(_) => TypedReceipt::Legacy(receipt_with_bloom),
2739 TypedReceipt::EIP2930(_) => TypedReceipt::EIP2930(receipt_with_bloom),
2740 TypedReceipt::EIP4844(_) => TypedReceipt::EIP4844(receipt_with_bloom),
2741 TypedReceipt::EIP7702(_) => TypedReceipt::EIP7702(receipt_with_bloom),
2742 TypedReceipt::Deposit(r) => TypedReceipt::Deposit(DepositReceipt {
2743 inner: receipt_with_bloom,
2744 deposit_nonce: r.deposit_nonce,
2745 deposit_receipt_version: r.deposit_receipt_version,
2746 }),
2747 };
2748
2749 let inner = TransactionReceipt {
2750 inner,
2751 transaction_hash: info.transaction_hash,
2752 transaction_index: Some(info.transaction_index),
2753 block_number: Some(block.header.number),
2754 gas_used: info.gas_used,
2755 contract_address: info.contract_address,
2756 effective_gas_price,
2757 block_hash: Some(block_hash),
2758 from: info.from,
2759 to: info.to,
2760 blob_gas_price: Some(blob_gas_price),
2761 blob_gas_used,
2762 };
2763
2764 Some(MinedTransactionReceipt { inner, out: info.out.map(|o| o.0.into()) })
2765 }
2766
2767 pub async fn block_receipts(
2769 &self,
2770 number: BlockId,
2771 ) -> Result<Option<Vec<ReceiptResponse>>, BlockchainError> {
2772 if let Some(receipts) = self.mined_block_receipts(number) {
2773 return Ok(Some(receipts));
2774 }
2775
2776 if let Some(fork) = self.get_fork() {
2777 let number = match self.ensure_block_number(Some(number)).await {
2778 Err(_) => return Ok(None),
2779 Ok(n) => n,
2780 };
2781
2782 if fork.predates_fork_inclusive(number) {
2783 let receipts = fork.block_receipts(number).await?;
2784
2785 return Ok(receipts);
2786 }
2787 }
2788
2789 Ok(None)
2790 }
2791
2792 pub async fn transaction_by_block_number_and_index(
2793 &self,
2794 number: BlockNumber,
2795 index: Index,
2796 ) -> Result<Option<AnyRpcTransaction>, BlockchainError> {
2797 if let Some(block) = self.mined_block_by_number(number) {
2798 return Ok(self.mined_transaction_by_block_hash_and_index(block.header.hash, index));
2799 }
2800
2801 if let Some(fork) = self.get_fork() {
2802 let number = self.convert_block_number(Some(number));
2803 if fork.predates_fork(number) {
2804 return Ok(fork.transaction_by_block_number_and_index(number, index.into()).await?)
2805 }
2806 }
2807
2808 Ok(None)
2809 }
2810
2811 pub async fn transaction_by_block_hash_and_index(
2812 &self,
2813 hash: B256,
2814 index: Index,
2815 ) -> Result<Option<AnyRpcTransaction>, BlockchainError> {
2816 if let tx @ Some(_) = self.mined_transaction_by_block_hash_and_index(hash, index) {
2817 return Ok(tx);
2818 }
2819
2820 if let Some(fork) = self.get_fork() {
2821 return Ok(fork.transaction_by_block_hash_and_index(hash, index.into()).await?)
2822 }
2823
2824 Ok(None)
2825 }
2826
2827 pub fn mined_transaction_by_block_hash_and_index(
2828 &self,
2829 block_hash: B256,
2830 index: Index,
2831 ) -> Option<AnyRpcTransaction> {
2832 let (info, block, tx) = {
2833 let storage = self.blockchain.storage.read();
2834 let block = storage.blocks.get(&block_hash).cloned()?;
2835 let index: usize = index.into();
2836 let tx = block.transactions.get(index)?.clone();
2837 let info = storage.transactions.get(&tx.hash())?.info.clone();
2838 (info, block, tx)
2839 };
2840
2841 Some(transaction_build(
2842 Some(info.transaction_hash),
2843 tx,
2844 Some(&block),
2845 Some(info),
2846 block.header.base_fee_per_gas,
2847 ))
2848 }
2849
2850 pub async fn transaction_by_hash(
2851 &self,
2852 hash: B256,
2853 ) -> Result<Option<AnyRpcTransaction>, BlockchainError> {
2854 trace!(target: "backend", "transaction_by_hash={:?}", hash);
2855 if let tx @ Some(_) = self.mined_transaction_by_hash(hash) {
2856 return Ok(tx);
2857 }
2858
2859 if let Some(fork) = self.get_fork() {
2860 return fork.transaction_by_hash(hash).await.map_err(BlockchainError::AlloyForkProvider)
2861 }
2862
2863 Ok(None)
2864 }
2865
2866 pub fn mined_transaction_by_hash(&self, hash: B256) -> Option<AnyRpcTransaction> {
2867 let (info, block) = {
2868 let storage = self.blockchain.storage.read();
2869 let MinedTransaction { info, block_hash, .. } =
2870 storage.transactions.get(&hash)?.clone();
2871 let block = storage.blocks.get(&block_hash).cloned()?;
2872 (info, block)
2873 };
2874 let tx = block.transactions.get(info.transaction_index as usize)?.clone();
2875
2876 Some(transaction_build(
2877 Some(info.transaction_hash),
2878 tx,
2879 Some(&block),
2880 Some(info),
2881 block.header.base_fee_per_gas,
2882 ))
2883 }
2884
2885 pub async fn prove_account_at(
2889 &self,
2890 address: Address,
2891 keys: Vec<B256>,
2892 block_request: Option<BlockRequest>,
2893 ) -> Result<AccountProof, BlockchainError> {
2894 let block_number = block_request.as_ref().map(|r| r.block_number());
2895
2896 self.with_database_at(block_request, |block_db, _| {
2897 trace!(target: "backend", "get proof for {:?} at {:?}", address, block_number);
2898 let db = block_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?;
2899 let account = db.get(&address).cloned().unwrap_or_default();
2900
2901 let mut builder = HashBuilder::default()
2902 .with_proof_retainer(ProofRetainer::new(vec![Nibbles::unpack(keccak256(address))]));
2903
2904 for (key, account) in trie_accounts(db) {
2905 builder.add_leaf(key, &account);
2906 }
2907
2908 let _ = builder.root();
2909
2910 let proof = builder
2911 .take_proof_nodes()
2912 .into_nodes_sorted()
2913 .into_iter()
2914 .map(|(_, v)| v)
2915 .collect();
2916 let storage_proofs = prove_storage(&account.storage, &keys);
2917
2918 let account_proof = AccountProof {
2919 address,
2920 balance: account.info.balance,
2921 nonce: account.info.nonce,
2922 code_hash: account.info.code_hash,
2923 storage_hash: storage_root(&account.storage),
2924 account_proof: proof,
2925 storage_proof: keys
2926 .into_iter()
2927 .zip(storage_proofs)
2928 .map(|(key, proof)| {
2929 let storage_key: U256 = key.into();
2930 let value = account.storage.get(&storage_key).cloned().unwrap_or_default();
2931 StorageProof { key: JsonStorageKey::Hash(key), value, proof }
2932 })
2933 .collect(),
2934 };
2935
2936 Ok(account_proof)
2937 })
2938 .await?
2939 }
2940
2941 pub fn new_block_notifications(&self) -> NewBlockNotifications {
2943 let (tx, rx) = unbounded();
2944 self.new_block_listeners.lock().push(tx);
2945 trace!(target: "backed", "added new block listener");
2946 rx
2947 }
2948
2949 fn notify_on_new_block(&self, header: Header, hash: B256) {
2951 self.new_block_listeners.lock().retain(|tx| !tx.is_closed());
2954
2955 let notification = NewBlockNotification { hash, header: Arc::new(header) };
2956
2957 self.new_block_listeners
2958 .lock()
2959 .retain(|tx| tx.unbounded_send(notification.clone()).is_ok());
2960 }
2961
2962 pub async fn reorg(
2969 &self,
2970 depth: u64,
2971 tx_pairs: HashMap<u64, Vec<Arc<PoolTransaction>>>,
2972 common_block: Block,
2973 ) -> Result<(), BlockchainError> {
2974 self.rollback(common_block).await?;
2975 for i in 0..depth {
2977 let to_be_mined = tx_pairs.get(&i).cloned().unwrap_or_else(Vec::new);
2978 let outcome = self.do_mine_block(to_be_mined).await;
2979 node_info!(
2980 " Mined reorg block number {}. With {} valid txs and with invalid {} txs",
2981 outcome.block_number,
2982 outcome.included.len(),
2983 outcome.invalid.len()
2984 );
2985 }
2986
2987 Ok(())
2988 }
2989
2990 pub async fn rollback(&self, common_block: Block) -> Result<(), BlockchainError> {
2995 let common_state = {
2997 let mut state = self.states.write();
2998 let state_db = state
2999 .get(&common_block.header.hash_slow())
3000 .ok_or(BlockchainError::DataUnavailable)?;
3001 let db_full = state_db.maybe_as_full_db().ok_or(BlockchainError::DataUnavailable)?;
3002 db_full.clone()
3003 };
3004
3005 {
3006 self.db.write().await.clear();
3008 for (address, acc) in common_state {
3009 for (key, value) in acc.storage {
3010 self.db.write().await.set_storage_at(address, key.into(), value.into())?;
3011 }
3012 self.db.write().await.insert_account(address, acc.info);
3013 }
3014 }
3015
3016 {
3017 self.blockchain
3019 .storage
3020 .write()
3021 .unwind_to(common_block.header.number, common_block.header.hash_slow());
3022
3023 let mut env = self.env.write();
3025 env.evm_env.block_env.number = common_block.header.number;
3026 env.evm_env.block_env.timestamp = common_block.header.timestamp;
3027 env.evm_env.block_env.gas_limit = common_block.header.gas_limit;
3028 env.evm_env.block_env.difficulty = common_block.header.difficulty;
3029 env.evm_env.block_env.prevrandao = Some(common_block.header.mix_hash);
3030
3031 self.time.reset(env.evm_env.block_env.timestamp);
3032 }
3033 Ok(())
3034 }
3035}
3036
3037fn get_pool_transactions_nonce(
3039 pool_transactions: &[Arc<PoolTransaction>],
3040 address: Address,
3041) -> Option<u64> {
3042 if let Some(highest_nonce) = pool_transactions
3043 .iter()
3044 .filter(|tx| *tx.pending_transaction.sender() == address)
3045 .map(|tx| tx.pending_transaction.nonce())
3046 .max()
3047 {
3048 let tx_count = highest_nonce.saturating_add(1);
3049 return Some(tx_count)
3050 }
3051 None
3052}
3053
3054#[async_trait::async_trait]
3055impl TransactionValidator for Backend {
3056 async fn validate_pool_transaction(
3057 &self,
3058 tx: &PendingTransaction,
3059 ) -> Result<(), BlockchainError> {
3060 let address = *tx.sender();
3061 let account = self.get_account(address).await?;
3062 let env = self.next_env();
3063 Ok(self.validate_pool_transaction_for(tx, &account, &env)?)
3064 }
3065
3066 fn validate_pool_transaction_for(
3067 &self,
3068 pending: &PendingTransaction,
3069 account: &AccountInfo,
3070 env: &Env,
3071 ) -> Result<(), InvalidTransactionError> {
3072 let tx = &pending.transaction;
3073
3074 if let Some(tx_chain_id) = tx.chain_id() {
3075 let chain_id = self.chain_id();
3076 if chain_id.to::<u64>() != tx_chain_id {
3077 if let Some(legacy) = tx.as_legacy() {
3078 if env.evm_env.cfg_env.spec >= SpecId::SPURIOUS_DRAGON &&
3080 legacy.tx().chain_id.is_none()
3081 {
3082 warn!(target: "backend", ?chain_id, ?tx_chain_id, "incompatible EIP155-based V");
3083 return Err(InvalidTransactionError::IncompatibleEIP155);
3084 }
3085 } else {
3086 warn!(target: "backend", ?chain_id, ?tx_chain_id, "invalid chain id");
3087 return Err(InvalidTransactionError::InvalidChainId);
3088 }
3089 }
3090 }
3091
3092 if tx.gas_limit() < MIN_TRANSACTION_GAS as u64 {
3093 warn!(target: "backend", "[{:?}] gas too low", tx.hash());
3094 return Err(InvalidTransactionError::GasTooLow);
3095 }
3096
3097 if !env.evm_env.cfg_env.disable_block_gas_limit &&
3099 tx.gas_limit() > env.evm_env.block_env.gas_limit
3100 {
3101 warn!(target: "backend", "[{:?}] gas too high", tx.hash());
3102 return Err(InvalidTransactionError::GasTooHigh(ErrDetail {
3103 detail: String::from("tx.gas_limit > env.block.gas_limit"),
3104 }));
3105 }
3106
3107 let is_deposit_tx =
3109 matches!(&pending.transaction.transaction, TypedTransaction::Deposit(_));
3110 let nonce = tx.nonce();
3111 if nonce < account.nonce && !is_deposit_tx {
3112 warn!(target: "backend", "[{:?}] nonce too low", tx.hash());
3113 return Err(InvalidTransactionError::NonceTooLow);
3114 }
3115
3116 if env.evm_env.cfg_env.spec >= SpecId::LONDON {
3117 if tx.gas_price() < env.evm_env.block_env.basefee.into() && !is_deposit_tx {
3118 warn!(target: "backend", "max fee per gas={}, too low, block basefee={}",tx.gas_price(), env.evm_env.block_env.basefee);
3119 return Err(InvalidTransactionError::FeeCapTooLow);
3120 }
3121
3122 if let (Some(max_priority_fee_per_gas), Some(max_fee_per_gas)) =
3123 (tx.essentials().max_priority_fee_per_gas, tx.essentials().max_fee_per_gas)
3124 {
3125 if max_priority_fee_per_gas > max_fee_per_gas {
3126 warn!(target: "backend", "max priority fee per gas={}, too high, max fee per gas={}", max_priority_fee_per_gas, max_fee_per_gas);
3127 return Err(InvalidTransactionError::TipAboveFeeCap);
3128 }
3129 }
3130 }
3131
3132 if env.evm_env.cfg_env.spec >= SpecId::CANCUN && tx.transaction.is_eip4844() {
3134 if let Some(max_fee_per_blob_gas) = tx.essentials().max_fee_per_blob_gas {
3136 if let Some(blob_gas_and_price) = &env.evm_env.block_env.blob_excess_gas_and_price {
3137 if max_fee_per_blob_gas < blob_gas_and_price.blob_gasprice {
3138 warn!(target: "backend", "max fee per blob gas={}, too low, block blob gas price={}", max_fee_per_blob_gas, blob_gas_and_price.blob_gasprice);
3139 return Err(InvalidTransactionError::BlobFeeCapTooLow);
3140 }
3141 }
3142 }
3143
3144 let tx = match &tx.transaction {
3146 TypedTransaction::EIP4844(tx) => tx.tx(),
3147 _ => unreachable!(),
3148 };
3149
3150 let blob_count = tx.tx().blob_versioned_hashes.len();
3151
3152 if blob_count == 0 {
3154 return Err(InvalidTransactionError::NoBlobHashes)
3155 }
3156
3157 let max_blob_count = self.blob_params().max_blob_count as usize;
3159 if blob_count > max_blob_count {
3160 return Err(InvalidTransactionError::TooManyBlobs(blob_count, max_blob_count))
3161 }
3162
3163 if !self.skip_blob_validation(Some(*pending.sender())) {
3165 if let Err(err) = tx.validate(EnvKzgSettings::default().get()) {
3166 return Err(InvalidTransactionError::BlobTransactionValidationError(err))
3167 }
3168 }
3169 }
3170
3171 let max_cost = tx.max_cost();
3172 let value = tx.value();
3173
3174 match &tx.transaction {
3175 TypedTransaction::Deposit(deposit_tx) => {
3176 if value > account.balance + U256::from(deposit_tx.mint) {
3182 warn!(target: "backend", "[{:?}] insufficient balance={}, required={} account={:?}", tx.hash(), account.balance + U256::from(deposit_tx.mint), value, *pending.sender());
3183 return Err(InvalidTransactionError::InsufficientFunds);
3184 }
3185 }
3186 _ => {
3187 let req_funds = max_cost.checked_add(value.saturating_to()).ok_or_else(|| {
3189 warn!(target: "backend", "[{:?}] cost too high", tx.hash());
3190 InvalidTransactionError::InsufficientFunds
3191 })?;
3192 if account.balance < U256::from(req_funds) {
3193 warn!(target: "backend", "[{:?}] insufficient allowance={}, required={} account={:?}", tx.hash(), account.balance, req_funds, *pending.sender());
3194 return Err(InvalidTransactionError::InsufficientFunds);
3195 }
3196 }
3197 }
3198
3199 Ok(())
3200 }
3201
3202 fn validate_for(
3203 &self,
3204 tx: &PendingTransaction,
3205 account: &AccountInfo,
3206 env: &Env,
3207 ) -> Result<(), InvalidTransactionError> {
3208 self.validate_pool_transaction_for(tx, account, env)?;
3209 if tx.nonce() > account.nonce {
3210 return Err(InvalidTransactionError::NonceTooHigh);
3211 }
3212 Ok(())
3213 }
3214}
3215
3216pub fn transaction_build(
3218 tx_hash: Option<B256>,
3219 eth_transaction: MaybeImpersonatedTransaction,
3220 block: Option<&Block>,
3221 info: Option<TransactionInfo>,
3222 base_fee: Option<u64>,
3223) -> AnyRpcTransaction {
3224 if let TypedTransaction::Deposit(ref deposit_tx) = eth_transaction.transaction {
3225 let dep_tx = deposit_tx;
3226
3227 let ser = serde_json::to_value(dep_tx).expect("could not serialize TxDeposit");
3228 let maybe_deposit_fields = OtherFields::try_from(ser);
3229
3230 match maybe_deposit_fields {
3231 Ok(mut fields) => {
3232 fields.insert("v".to_string(), serde_json::to_value("0x0").unwrap());
3235 fields.insert("r".to_string(), serde_json::to_value(B256::ZERO).unwrap());
3236 fields.insert(String::from("s"), serde_json::to_value(B256::ZERO).unwrap());
3237 fields.insert(String::from("nonce"), serde_json::to_value("0x0").unwrap());
3238
3239 let inner = UnknownTypedTransaction {
3240 ty: AnyTxType(DEPOSIT_TX_TYPE_ID),
3241 fields,
3242 memo: Default::default(),
3243 };
3244
3245 let envelope = AnyTxEnvelope::Unknown(UnknownTxEnvelope {
3246 hash: eth_transaction.hash(),
3247 inner,
3248 });
3249
3250 let tx = Transaction {
3251 inner: Recovered::new_unchecked(envelope, deposit_tx.from),
3252 block_hash: block
3253 .as_ref()
3254 .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))),
3255 block_number: block.as_ref().map(|block| block.header.number),
3256 transaction_index: info.as_ref().map(|info| info.transaction_index),
3257 effective_gas_price: None,
3258 };
3259
3260 return AnyRpcTransaction::from(WithOtherFields::new(tx));
3261 }
3262 Err(_) => {
3263 error!(target: "backend", "failed to serialize deposit transaction");
3264 }
3265 }
3266 }
3267
3268 let mut transaction: Transaction = eth_transaction.clone().into();
3269
3270 let effective_gas_price = if !eth_transaction.is_dynamic_fee() {
3271 transaction.effective_gas_price(base_fee)
3272 } else if block.is_none() && info.is_none() {
3273 transaction.max_fee_per_gas()
3275 } else {
3276 let base_fee = base_fee.map_or(0u128, |g| g as u128);
3279 let max_priority_fee_per_gas = transaction.max_priority_fee_per_gas().unwrap_or(0);
3280
3281 base_fee.saturating_add(max_priority_fee_per_gas)
3282 };
3283
3284 transaction.effective_gas_price = Some(effective_gas_price);
3285
3286 let envelope = transaction.inner;
3287
3288 let hash = tx_hash.unwrap_or(*envelope.tx_hash());
3294
3295 let envelope = match envelope.into_inner() {
3296 TxEnvelope::Legacy(signed_tx) => {
3297 let (t, sig, _) = signed_tx.into_parts();
3298 let new_signed = Signed::new_unchecked(t, sig, hash);
3299 AnyTxEnvelope::Ethereum(TxEnvelope::Legacy(new_signed))
3300 }
3301 TxEnvelope::Eip1559(signed_tx) => {
3302 let (t, sig, _) = signed_tx.into_parts();
3303 let new_signed = Signed::new_unchecked(t, sig, hash);
3304 AnyTxEnvelope::Ethereum(TxEnvelope::Eip1559(new_signed))
3305 }
3306 TxEnvelope::Eip2930(signed_tx) => {
3307 let (t, sig, _) = signed_tx.into_parts();
3308 let new_signed = Signed::new_unchecked(t, sig, hash);
3309 AnyTxEnvelope::Ethereum(TxEnvelope::Eip2930(new_signed))
3310 }
3311 TxEnvelope::Eip4844(signed_tx) => {
3312 let (t, sig, _) = signed_tx.into_parts();
3313 let new_signed = Signed::new_unchecked(t, sig, hash);
3314 AnyTxEnvelope::Ethereum(TxEnvelope::Eip4844(new_signed))
3315 }
3316 TxEnvelope::Eip7702(signed_tx) => {
3317 let (t, sig, _) = signed_tx.into_parts();
3318 let new_signed = Signed::new_unchecked(t, sig, hash);
3319 AnyTxEnvelope::Ethereum(TxEnvelope::Eip7702(new_signed))
3320 }
3321 };
3322
3323 let tx = Transaction {
3324 inner: Recovered::new_unchecked(
3325 envelope,
3326 eth_transaction.recover().expect("can recover signed tx"),
3327 ),
3328 block_hash: block
3329 .as_ref()
3330 .map(|block| B256::from(keccak256(alloy_rlp::encode(&block.header)))),
3331 block_number: block.as_ref().map(|block| block.header.number),
3332 transaction_index: info.as_ref().map(|info| info.transaction_index),
3333 effective_gas_price: Some(effective_gas_price),
3335 };
3336 AnyRpcTransaction::from(WithOtherFields::new(tx))
3337}
3338
3339pub fn prove_storage(storage: &HashMap<U256, U256>, keys: &[B256]) -> Vec<Vec<Bytes>> {
3345 let keys: Vec<_> = keys.iter().map(|key| Nibbles::unpack(keccak256(key))).collect();
3346
3347 let mut builder = HashBuilder::default().with_proof_retainer(ProofRetainer::new(keys.clone()));
3348
3349 for (key, value) in trie_storage(storage) {
3350 builder.add_leaf(key, &value);
3351 }
3352
3353 let _ = builder.root();
3354
3355 let mut proofs = Vec::new();
3356 let all_proof_nodes = builder.take_proof_nodes();
3357
3358 for proof_key in keys {
3359 let matching_proof_nodes =
3362 all_proof_nodes.matching_nodes_sorted(&proof_key).into_iter().map(|(_, node)| node);
3363 proofs.push(matching_proof_nodes.collect());
3364 }
3365
3366 proofs
3367}
3368
3369pub fn is_arbitrum(chain_id: u64) -> bool {
3370 if let Ok(chain) = NamedChain::try_from(chain_id) {
3371 return chain.is_arbitrum()
3372 }
3373 false
3374}
3375
3376pub fn op_haltreason_to_instruction_result(op_reason: OpHaltReason) -> InstructionResult {
3377 match op_reason {
3378 OpHaltReason::Base(eth_h) => eth_h.into(),
3379 OpHaltReason::FailedDeposit => InstructionResult::Stop,
3380 }
3381}