Skip to main content

Blockchain

Struct Blockchain 

Source
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: Mempool

Transaction mempool for pending transactions.

§options: BlockchainOptions

Configuration 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

Source

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.

Source

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

Source

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

Source

pub fn build_payload( &self, payload: Block, ) -> Result<PayloadBuildResult, ChainError>

Completes the payload building process, return the block value

Source

pub fn apply_withdrawals( &self, context: &mut PayloadBuildContext, ) -> Result<(), EvmError>

Source

pub fn apply_system_operations( &self, context: &mut PayloadBuildContext, ) -> Result<(), EvmError>

Source

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

Source

pub fn fill_transactions( &self, context: &mut PayloadBuildContext, ) -> Result<(), ChainError>

Fills the payload with transactions taken from the mempool Returns the block value

Source

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.

Source

pub fn extract_requests( &self, context: &mut PayloadBuildContext, ) -> Result<(), EvmError>

Source

pub fn finalize_payload( &self, context: &mut PayloadBuildContext, ) -> Result<(), ChainError>

Source§

impl Blockchain

Source

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

Source

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

Source

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.

Source

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.

Source

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.

Source

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

Source

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.

Source

pub fn new(store: Store, blockchain_opts: BlockchainOptions) -> Self

Source

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.

Source

pub fn default_with_store(store: Store) -> Self

Source

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.

Source

pub async fn generate_witness_for_blocks( &self, blocks: &[Block], ) -> Result<ExecutionWitness, ChainError>

Source

pub async fn generate_witness_for_blocks_with_fee_configs( &self, blocks: &[Block], fee_configs: Option<&[FeeConfig]>, ) -> Result<ExecutionWitness, ChainError>

Source

pub fn generate_witness_from_account_updates( &self, account_updates: Vec<AccountUpdate>, block: &Block, parent_header: BlockHeader, logger: &DatabaseLogger, ) -> Result<ExecutionWitness, ChainError>

Source

pub fn store_block( &self, block: Block, account_updates_list: AccountUpdatesList, execution_result: BlockExecutionResult, ) -> Result<(), ChainError>

Source

pub fn add_block(&self, block: Block) -> Result<(), ChainError>

Source

pub fn add_block_pipeline( &self, block: Block, bal: Option<&BlockAccessList>, ) -> Result<(), ChainError>

Source

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.

Source

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.

Source

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.

Source

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

Source

pub fn remove_transaction_from_pool( &self, hash: &H256, ) -> Result<(), StoreError>

Remove a transaction from the mempool

Source

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)

Source

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.

Source

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

Source

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

Source

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.

Source

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

Source

pub fn get_p2p_transaction_by_hash( &self, hash: &H256, ) -> Result<P2PTransaction, StoreError>

Source

pub fn new_evm(&self, vm_db: StoreVmDatabase) -> Result<Evm, EvmError>

Source

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§

Source§

impl Debug for Blockchain

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> ArchivePointee for T

Source§

type ArchivedMetadata = ()

The archived version of the pointer metadata for this type.
Source§

fn pointer_metadata( _: &<T as ArchivePointee>::ArchivedMetadata, ) -> <T as Pointee>::Metadata

Converts some archived metadata to the pointer metadata for itself.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T, U> ExactFrom<T> for U
where U: TryFrom<T>,

Source§

fn exact_from(value: T) -> U

Source§

impl<T, U> ExactInto<U> for T
where U: ExactFrom<T>,

Source§

fn exact_into(self) -> U

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts 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 more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts 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 more
Source§

impl<T> LayoutRaw for T

Source§

fn layout_raw(_: <T as Pointee>::Metadata) -> Result<Layout, LayoutError>

Returns the layout of the type.
Source§

impl<T, N1, N2> Niching<NichedOption<T, N1>> for N2
where T: SharedNiching<N1, N2>, N1: Niching<T>, N2: Niching<T>,

Source§

unsafe fn is_niched(niched: *const NichedOption<T, N1>) -> bool

Returns whether the given value has been niched. Read more
Source§

fn resolve_niched(out: Place<NichedOption<T, N1>>)

Writes data to out indicating that a T is niched.
Source§

impl<T, U> OverflowingInto<U> for T
where U: OverflowingFrom<T>,

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Pointee for T

Source§

type Metadata = ()

The metadata type for pointers and references to this type.
Source§

impl<T, U> RoundingInto<U> for T
where U: RoundingFrom<T>,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> SaturatingInto<U> for T
where U: SaturatingFrom<T>,

Source§

impl<T> ToDebugString for T
where T: Debug,

Source§

fn to_debug_string(&self) -> String

Returns the String produced by Ts Debug implementation.

§Examples
use malachite_base::strings::ToDebugString;

assert_eq!([1, 2, 3].to_debug_string(), "[1, 2, 3]");
assert_eq!(
    [vec![2, 3], vec![], vec![4]].to_debug_string(),
    "[[2, 3], [], [4]]"
);
assert_eq!(Some(5).to_debug_string(), "Some(5)");
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T, U> WrappingInto<U> for T
where U: WrappingFrom<T>,

Source§

fn wrapping_into(self) -> U