pub struct Blockchain {
pub mempool: Mempool,
pub options: BlockchainOptions,
pub payloads: Arc<Mutex<Vec<(u64, PayloadOrTask)>>>,
/* private fields */
}Expand description
Core blockchain implementation for block validation and execution.
The Blockchain struct is the main entry point for all blockchain operations:
- Adding and validating blocks
- Managing the transaction mempool
- Building payloads for block production
- Handling fork choice updates
§Thread Safety
Blockchain uses interior mutability for thread-safe access to shared state.
The mempool and payload storage are protected by appropriate synchronization primitives.
§Example
let blockchain = Blockchain::new(store, BlockchainOptions::default());
// Validate and add a block
blockchain.add_block(&block)?;
// Check sync status
if blockchain.is_synced() {
// Process transactions from mempool
}Fields§
§mempool: MempoolTransaction mempool for pending transactions.
options: BlockchainOptionsConfiguration options for blockchain behavior.
payloads: Arc<Mutex<Vec<(u64, PayloadOrTask)>>>Cache of recently built payloads.
Maps payload IDs to either completed payloads or in-progress build tasks. Kept around in case consensus requests the same payload twice.
Implementations§
Source§impl Blockchain
impl Blockchain
Sourcepub async fn get_payload(
&self,
payload_id: u64,
) -> Result<PayloadBuildResult, ChainError>
pub async fn get_payload( &self, payload_id: u64, ) -> Result<PayloadBuildResult, ChainError>
Attempts to fetch a payload given it’s id. If the payload is still being built, it will be finished. Fails if there is no payload or active payload build task for the given id.
Sourcepub async fn initiate_payload_build(
self: Arc<Blockchain>,
payload: Block,
payload_id: u64,
)
pub async fn initiate_payload_build( self: Arc<Blockchain>, payload: Block, payload_id: u64, )
Starts a payload build process. The built payload can be retrieved by calling get_payload.
The build process will run for the full block building timeslot or until get_payload is called
Sourcepub async fn build_payload_loop(
self: Arc<Blockchain>,
payload: Block,
cancel_token: CancellationToken,
) -> Result<PayloadBuildResult, ChainError>
pub async fn build_payload_loop( self: Arc<Blockchain>, payload: Block, cancel_token: CancellationToken, ) -> Result<PayloadBuildResult, ChainError>
Build the given payload and keep on rebuilding it until either the time slot
given by SECONDS_PER_SLOT is up or the cancel_token is cancelled
Sourcepub fn build_payload(
&self,
payload: Block,
) -> Result<PayloadBuildResult, ChainError>
pub fn build_payload( &self, payload: Block, ) -> Result<PayloadBuildResult, ChainError>
Completes the payload building process, return the block value
pub fn apply_withdrawals( &self, context: &mut PayloadBuildContext, ) -> Result<(), EvmError>
pub fn apply_system_operations( &self, context: &mut PayloadBuildContext, ) -> Result<(), EvmError>
Sourcepub fn fetch_mempool_transactions(
&self,
context: &mut PayloadBuildContext,
) -> Result<(TransactionQueue, TransactionQueue), ChainError>
pub fn fetch_mempool_transactions( &self, context: &mut PayloadBuildContext, ) -> Result<(TransactionQueue, TransactionQueue), ChainError>
Fetches suitable transactions from the mempool Returns two transaction queues, one for plain and one for blob txs
Sourcepub fn fill_transactions(
&self,
context: &mut PayloadBuildContext,
) -> Result<(), ChainError>
pub fn fill_transactions( &self, context: &mut PayloadBuildContext, ) -> Result<(), ChainError>
Fills the payload with transactions taken from the mempool Returns the block value
Sourcepub fn apply_tx_to_payload(
&self,
head: HeadTransaction,
context: &mut PayloadBuildContext,
) -> Result<(), ChainError>
pub fn apply_tx_to_payload( &self, head: HeadTransaction, context: &mut PayloadBuildContext, ) -> Result<(), ChainError>
Apply a single transaction to the in-progress payload.
Runs the full per-tx pipeline: EIP-8037 2D inclusion check, EIP-7928
BAL index/checkpoint setup, sender/recipient recording, dispatch to
blob/plain execution, and on failure rolls the BAL recorder back so
rejected txs leave no trace. On success the tx is appended to the
payload body and the receipt to context.receipts.
Caller is responsible for mempool bookkeeping (advancing or dropping the sender’s queue) — this function only mutates the payload context.
pub fn extract_requests( &self, context: &mut PayloadBuildContext, ) -> Result<(), EvmError>
pub fn finalize_payload( &self, context: &mut PayloadBuildContext, ) -> Result<(), ChainError>
Source§impl Blockchain
impl Blockchain
Sourcepub async fn trace_transaction_calls(
&self,
tx_hash: H256,
reexec: u32,
timeout: Duration,
only_top_call: bool,
with_log: bool,
) -> Result<CallTrace, ChainError>
pub async fn trace_transaction_calls( &self, tx_hash: H256, reexec: u32, timeout: Duration, only_top_call: bool, with_log: bool, ) -> Result<CallTrace, ChainError>
Outputs the call trace for the given transaction
May need to re-execute blocks in order to rebuild the transaction’s prestate, up to the amount given by reexec
Sourcepub async fn trace_block_calls(
&self,
block: Block,
reexec: u32,
timeout: Duration,
only_top_call: bool,
with_log: bool,
) -> Result<Vec<(H256, CallTrace)>, ChainError>
pub async fn trace_block_calls( &self, block: Block, reexec: u32, timeout: Duration, only_top_call: bool, with_log: bool, ) -> Result<Vec<(H256, CallTrace)>, ChainError>
Outputs the call trace for each transaction in the block along with the transaction’s hash
May need to re-execute blocks in order to rebuild the transaction’s prestate, up to the amount given by reexec
Returns transaction call traces from oldest to newest
Sourcepub async fn trace_transaction_prestate(
&self,
tx_hash: H256,
reexec: u32,
timeout: Duration,
diff_mode: bool,
include_empty: bool,
) -> Result<PrestateResult, ChainError>
pub async fn trace_transaction_prestate( &self, tx_hash: H256, reexec: u32, timeout: Duration, diff_mode: bool, include_empty: bool, ) -> Result<PrestateResult, ChainError>
Outputs the prestate trace for the given transaction.
If diff_mode is true, returns both pre and post state; otherwise returns only pre state.
include_empty keeps default-state entries in pre (only valid when diff_mode is false).
May need to re-execute blocks in order to rebuild the transaction’s prestate, up to the amount given by reexec.
Sourcepub async fn trace_block_prestate(
&self,
block: Block,
reexec: u32,
timeout: Duration,
diff_mode: bool,
include_empty: bool,
) -> Result<Vec<(H256, PrestateResult)>, ChainError>
pub async fn trace_block_prestate( &self, block: Block, reexec: u32, timeout: Duration, diff_mode: bool, include_empty: bool, ) -> Result<Vec<(H256, PrestateResult)>, ChainError>
Outputs the prestate trace for each transaction in the block along with the transaction’s hash.
If diff_mode is true, returns both pre and post state per tx; otherwise returns only pre state.
include_empty keeps default-state entries in pre (only valid when diff_mode is false).
May need to re-execute blocks in order to rebuild the block’s prestate, up to the amount given by reexec.
Returns prestate traces from oldest to newest transaction.
Sourcepub async fn trace_transaction_opcodes(
&self,
tx_hash: H256,
reexec: u32,
timeout: Duration,
cfg: OpcodeTracerConfig,
) -> Result<OpcodeTraceResult, ChainError>
pub async fn trace_transaction_opcodes( &self, tx_hash: H256, reexec: u32, timeout: Duration, cfg: OpcodeTracerConfig, ) -> Result<OpcodeTraceResult, ChainError>
Outputs the per-opcode (EIP-3155) trace for the given transaction.
May need to re-execute blocks in order to rebuild the transaction’s prestate, up to the amount given by reexec.
Sourcepub async fn trace_block_opcodes(
&self,
block: Block,
reexec: u32,
timeout: Duration,
cfg: OpcodeTracerConfig,
) -> Result<Vec<(H256, OpcodeTraceResult)>, ChainError>
pub async fn trace_block_opcodes( &self, block: Block, reexec: u32, timeout: Duration, cfg: OpcodeTracerConfig, ) -> Result<Vec<(H256, OpcodeTraceResult)>, ChainError>
Outputs the opcode (EIP-3155) trace for each transaction in the block along with
the transaction’s hash.
May need to re-execute blocks in order to rebuild the block’s prestate, up to the amount
given by reexec.
Returns traces from oldest to newest transaction.
Source§impl Blockchain
impl Blockchain
Sourcepub fn build_merkle_pool() -> Arc<ThreadPool>
pub fn build_merkle_pool() -> Arc<ThreadPool>
Build a fresh 17-thread merkleization pool. Used by the default
constructors; tests that build many Blockchains should share one pool
via default_with_store_and_pool to avoid spawning the pool repeatedly.
pub fn new(store: Store, blockchain_opts: BlockchainOptions) -> Self
Sourcepub fn default_with_store_and_pool(store: Store, pool: Arc<ThreadPool>) -> Self
pub fn default_with_store_and_pool(store: Store, pool: Arc<ThreadPool>) -> Self
Like default_with_store, but reuses an externally-owned merkleization
pool. Intended for test harnesses that build many short-lived
Blockchain instances; sharing the pool avoids spawning 17 fresh OS
threads per instance.
SAFETY: the caller must ensure each pool has only one concurrent
in_place_scope user at a time. The internal merkle protocol requires
all 16 worker jobs to run concurrently (they cross-communicate via
channels); sharing a pool across simultaneous callers deadlocks.
pub fn default_with_store(store: Store) -> Self
Sourcepub fn generate_bal_for_block(
&self,
block: &Block,
) -> Result<Option<BlockAccessList>, ChainError>
pub fn generate_bal_for_block( &self, block: &Block, ) -> Result<Option<BlockAccessList>, ChainError>
Generates Block Access List by re-executing a block. Returns None for pre-Amsterdam blocks. This is used by engine_getPayloadBodiesByHashV2 and engine_getPayloadBodiesByRangeV2.
pub async fn generate_witness_for_blocks( &self, blocks: &[Block], ) -> Result<ExecutionWitness, ChainError>
pub async fn generate_witness_for_blocks_with_fee_configs( &self, blocks: &[Block], fee_configs: Option<&[FeeConfig]>, ) -> Result<ExecutionWitness, ChainError>
pub fn generate_witness_from_account_updates( &self, account_updates: Vec<AccountUpdate>, block: &Block, parent_header: BlockHeader, logger: &DatabaseLogger, ) -> Result<ExecutionWitness, ChainError>
pub fn store_block( &self, block: Block, account_updates_list: AccountUpdatesList, execution_result: BlockExecutionResult, ) -> Result<(), ChainError>
pub fn add_block(&self, block: Block) -> Result<(), ChainError>
pub fn add_block_pipeline( &self, block: Block, bal: Option<&BlockAccessList>, ) -> Result<(), ChainError>
Sourcepub fn add_block_pipeline_bal(
&self,
block: Block,
bal: Option<&BlockAccessList>,
) -> Result<Option<BlockAccessList>, ChainError>
pub fn add_block_pipeline_bal( &self, block: Block, bal: Option<&BlockAccessList>, ) -> Result<Option<BlockAccessList>, ChainError>
Same as [add_block_pipeline] but also returns the BAL produced during execution.
A BAL only exists from Amsterdam onward. On the parallel validation path the BAL
comes from the header and drives execution rather than being rebuilt, so the
returned value is None; the sequential path (block production or
--no-bal-parallel-exec) rebuilds it and returns Some(bal). Pre-Amsterdam blocks
never record a BAL, so the returned value is always None.
Sourcepub fn add_block_pipeline_with_witness(
&self,
block: Block,
bal: Option<&BlockAccessList>,
) -> Result<ExecutionWitness, ChainError>
pub fn add_block_pipeline_with_witness( &self, block: Block, bal: Option<&BlockAccessList>, ) -> Result<ExecutionWitness, ChainError>
Same as [add_block_pipeline] but returns the execution witness produced
while importing the block.
Sourcepub async fn add_blocks_in_batch(
&self,
blocks: Vec<Block>,
bals: &[Option<BlockAccessList>],
cancellation_token: CancellationToken,
) -> Result<(), (ChainError, Option<BatchBlockProcessingFailure>)>
pub async fn add_blocks_in_batch( &self, blocks: Vec<Block>, bals: &[Option<BlockAccessList>], cancellation_token: CancellationToken, ) -> Result<(), (ChainError, Option<BatchBlockProcessingFailure>)>
Adds multiple blocks in a batch.
If an error occurs, returns a tuple containing:
- The error type (
ChainError). - [
BatchProcessingFailure] (if the error was caused by block processing).
Note: only the last block’s state trie is stored in the db
bals holds the per-block Block Access Lists fetched during sync, aligned
by index with blocks. Pass an empty slice when no BALs are available
(e.g. block import from RLP); the persistence step then stores none. Only
BALs matching their block’s header commitment are persisted.
Sourcepub async fn add_transaction_to_pool(
&self,
transaction: Transaction,
) -> Result<H256, MempoolError>
pub async fn add_transaction_to_pool( &self, transaction: Transaction, ) -> Result<H256, MempoolError>
Add a transaction to the mempool checking that the transaction is valid
Sourcepub fn remove_transaction_from_pool(
&self,
hash: &H256,
) -> Result<(), StoreError>
pub fn remove_transaction_from_pool( &self, hash: &H256, ) -> Result<(), StoreError>
Remove a transaction from the mempool
Sourcepub fn remove_block_transactions_from_pool(
&self,
block: &Block,
) -> Result<(), StoreError>
pub fn remove_block_transactions_from_pool( &self, block: &Block, ) -> Result<(), StoreError>
Remove all transactions in the executed block from the pool (if we have them)
Sourcepub fn remove_stale_blob_txs(
&self,
head_hash: BlockHash,
) -> Result<(), StoreError>
pub fn remove_stale_blob_txs( &self, head_hash: BlockHash, ) -> Result<(), StoreError>
Drop blob txs with nonce below the sender’s on-chain nonce at head_hash.
Per-block pruning only covers the head block, so stale blob txs from
non-head canonical blocks leak in and are never evicted (value/nonce
eviction pins low nonces). Resetting against on-chain nonces clears them.
Sourcepub async fn validate_transaction(
&self,
tx: &Transaction,
sender: Address,
) -> Result<Option<H256>, MempoolError>
pub async fn validate_transaction( &self, tx: &Transaction, sender: Address, ) -> Result<Option<H256>, MempoolError>
Returns the hash of the transaction to replace in case the nonce already exists
Sourcepub fn set_synced(&self)
pub fn set_synced(&self)
Marks the node’s chain as up to date with the current chain Once the initial sync has taken place, the node will be considered as sync
Sourcepub fn set_not_synced(&self)
pub fn set_not_synced(&self)
Marks the node’s chain as not up to date with the current chain. This will be used when the node is one batch or more behind the current chain.
Sourcepub fn is_synced(&self) -> bool
pub fn is_synced(&self) -> bool
Returns whether the node’s chain is up to date with the current chain This will be true if the initial sync has already taken place and does not reflect whether there is an ongoing sync process The node should accept incoming p2p transactions if this method returns true
pub fn get_p2p_transaction_by_hash( &self, hash: &H256, ) -> Result<P2PTransaction, StoreError>
pub fn new_evm(&self, vm_db: StoreVmDatabase) -> Result<Evm, EvmError>
Sourcepub async fn current_fork(&self) -> Result<Fork, StoreError>
pub async fn current_fork(&self) -> Result<Fork, StoreError>
Get the current fork of the chain, based on the latest block’s timestamp
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for Blockchain
impl !RefUnwindSafe for Blockchain
impl !UnwindSafe for Blockchain
impl Send for Blockchain
impl Sync for Blockchain
impl Unpin for Blockchain
impl UnsafeUnpin for Blockchain
Blanket Implementations§
Source§impl<T> ArchivePointee for T
impl<T> ArchivePointee for T
Source§type ArchivedMetadata = ()
type ArchivedMetadata = ()
Source§fn pointer_metadata(
_: &<T as ArchivePointee>::ArchivedMetadata,
) -> <T as Pointee>::Metadata
fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§impl<T> LayoutRaw for T
impl<T> LayoutRaw for T
Source§fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>
Source§impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
Source§unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool
Source§fn resolve_niched(out: Place<NichedOption<T, N1>>)
fn resolve_niched(out: Place<NichedOption<T, N1>>)
out indicating that a T is niched.