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