pub struct BlockBuilder {Show 23 fields
pub height: u64,
pub epoch: u64,
pub parent_hash: Bytes32,
pub l1_height: u32,
pub l1_hash: Bytes32,
pub proposer_index: u32,
pub spend_bundles: Vec<SpendBundle>,
pub slash_proposal_payloads: Vec<Vec<u8>>,
pub total_cost: Cost,
pub total_fees: u64,
pub additions: Vec<Coin>,
pub removals: Vec<Bytes32>,
pub l1_collateral_coin_id: Option<Bytes32>,
pub l1_reserve_coin_id: Option<Bytes32>,
pub l1_prev_epoch_finalizer_coin_id: Option<Bytes32>,
pub l1_curr_epoch_finalizer_coin_id: Option<Bytes32>,
pub l1_network_coin_id: Option<Bytes32>,
pub collateral_registry_root: Bytes32,
pub cid_state_root: Bytes32,
pub node_registry_root: Bytes32,
pub namespace_update_root: Bytes32,
pub dfsp_finalize_commitment_root: Bytes32,
pub extension_data: Bytes32,
}Expand description
Incremental accumulator for a single L2 block body and header metadata (SPEC §6.1–6.2, BLD-001).
Usage: Construct with Self::new, optionally configure L1 proof anchors / DFSP roots / L2BlockHeader::extension_data
via Self::set_l1_proofs, Self::set_dfsp_roots, Self::set_extension_data (BLD-004), add spend bundles via
Self::add_spend_bundle (BLD-002) and slash payloads via Self::add_slash_proposal (BLD-003), then call
build(...) (BLD-005) to obtain a signed crate::L2Block.
The struct exposes public fields so
advanced callers or tests can inspect partial state without accessor boilerplate; treat them as read-mostly except
through official builder methods once those exist.
Rationale: Public fields match the BLD-001 specification prose and mirror the SPEC §6.1 layout (caller context,
accumulated body, running totals). Coin and SpendBundle stay on chia-protocol types per project rules
(docs/prompt/start.md — Chia ecosystem first).
Removals type: NORMATIVE names this Vec<CoinId>; chia-protocol does not export a separate CoinId newtype in
the versions we pin — coin IDs are the same 32-byte values as Bytes32 (see BLK-004 / crate::L2Block::all_removals).
Fields§
§height: u64Block height this builder is assembling (immutable for the lifetime of the builder).
epoch: u64Epoch index (crate::L2BlockHeader::epoch semantics).
parent_hash: Bytes32Parent L2 block header hash (chain link).
l1_height: u32Anchoring L1 block height for light-client / bridge logic.
l1_hash: Bytes32Anchoring L1 block hash.
proposer_index: u32Proposer slot index in the validator set for this block.
spend_bundles: Vec<SpendBundle>Spend bundles accumulated in insertion order (body).
slash_proposal_payloads: Vec<Vec<u8>>Raw slash-proposal payloads (opaque bytes per protocol).
total_cost: CostRunning sum of CLVM costs for bundles accepted so far (Cost / BLK-006).
total_fees: u64Running sum of fees from accepted bundles.
additions: Vec<Coin>Flattened Coin outputs extracted from spends (Self::add_spend_bundle / BLD-002).
removals: Vec<Bytes32>Spent coin IDs (same bytes as coin.coin_id() / NORMATIVE CoinId).
l1_collateral_coin_id: Option<Bytes32>L1 collateral proof anchor (L2BlockHeader::l1_collateral_coin_id); None until Self::set_l1_proofs.
l1_reserve_coin_id: Option<Bytes32>Network validator collateral set anchor (L2BlockHeader::l1_reserve_coin_id).
l1_prev_epoch_finalizer_coin_id: Option<Bytes32>Previous-epoch finalizer proof coin (L2BlockHeader::l1_prev_epoch_finalizer_coin_id).
l1_curr_epoch_finalizer_coin_id: Option<Bytes32>Current-epoch finalizer proof coin (L2BlockHeader::l1_curr_epoch_finalizer_coin_id).
l1_network_coin_id: Option<Bytes32>Network singleton proof coin (L2BlockHeader::l1_network_coin_id).
collateral_registry_root: Bytes32DFSP collateral registry root (L2BlockHeader::collateral_registry_root); defaults EMPTY_ROOT per SVL-002.
cid_state_root: Bytes32DFSP CID state root (L2BlockHeader::cid_state_root).
node_registry_root: Bytes32DFSP node registry root (L2BlockHeader::node_registry_root).
namespace_update_root: Bytes32Namespace update delta root (L2BlockHeader::namespace_update_root).
dfsp_finalize_commitment_root: Bytes32DFSP finalize commitment root (L2BlockHeader::dfsp_finalize_commitment_root).
extension_data: Bytes32Header extension slot (L2BlockHeader::extension_data); default ZERO_HASH matches L2BlockHeader::new.
Implementations§
Source§impl BlockBuilder
impl BlockBuilder
Sourcepub fn new(
height: u64,
epoch: u64,
parent_hash: Bytes32,
l1_height: u32,
l1_hash: Bytes32,
proposer_index: u32,
) -> Self
pub fn new( height: u64, epoch: u64, parent_hash: Bytes32, l1_height: u32, l1_hash: Bytes32, proposer_index: u32, ) -> Self
Create an empty builder anchored at the given chain / L1 context (BLD-001).
Contract: All accumulation fields start empty or zero; identity arguments are copied into the struct so the caller may reuse their locals afterward without aliasing the builder’s internal state.
Sourcepub fn add_spend_bundle(
&mut self,
bundle: SpendBundle,
cost: Cost,
fee: u64,
) -> Result<(), BuilderError>
pub fn add_spend_bundle( &mut self, bundle: SpendBundle, cost: Cost, fee: u64, ) -> Result<(), BuilderError>
Append a SpendBundle after validating CLVM cost and serialized block-size budgets (BLD-002).
Parameters: cost / fee are caller-supplied aggregates for this bundle (typically from
dig_clvm::validate_spend_bundle / execution preview). The builder trusts these numbers for budgeting only;
L2BlockHeader::total_cost consistency is enforced later at execution tier (EXE-007) and in build() (BLD-005).
Budget order: cost is checked first (cheap, no cloning). Size uses a bincode probe that temporarily
[clone]s the candidate bundle — if the probe fails, bundle is still owned by the caller on Err.
Mutation contract: On Err, no field of self changes. On Ok, additions/removals/totals/spend_bundles
advance together so partial state is impossible.
Additions / removals: Mirrors crate::L2Block::all_additions / crate::L2Block::all_removals —
SpendBundle::additions (CLVM-simulated CREATE_COINs) plus one removal Bytes32 per [CoinSpend].
Sourcepub fn remaining_cost(&self) -> Cost
pub fn remaining_cost(&self) -> Cost
Remaining CLVM cost budget before hitting MAX_COST_PER_BLOCK (BLD-002).
Usage: Proposers can gate bundle selection without duplicating protocol constants. Saturates at zero if
total_cost ever overshoots (should not happen if only Self::add_spend_bundle mutates cost).
Sourcepub fn spend_bundle_count(&self) -> usize
pub fn spend_bundle_count(&self) -> usize
Number of spend bundles accepted so far (same as spend_bundles.len()).
Sourcepub fn add_slash_proposal(
&mut self,
payload: Vec<u8>,
) -> Result<(), BuilderError>
pub fn add_slash_proposal( &mut self, payload: Vec<u8>, ) -> Result<(), BuilderError>
Append an opaque slash-proposal payload after enforcing protocol caps (BLD-003).
Count: Rejects when Self::slash_proposal_payloads already holds MAX_SLASH_PROPOSALS_PER_BLOCK
rows — the guard uses >= so the next push would exceed the cap (BuilderError::TooManySlashProposals).
Size: Rejects when payload.len() > MAX_SLASH_PROPOSAL_PAYLOAD_BYTES
(BuilderError::SlashProposalTooLarge). A payload whose length equals the limit is accepted (strict >).
Check order (spec): Count is validated before size so that a builder already at the count cap surfaces
BuilderError::TooManySlashProposals even if the candidate payload is also oversized — callers get a stable
primary failure mode (BLD-003 implementation notes).
Mutation contract: On Err, slash_proposal_payloads and all other fields are unchanged. On Ok, only
slash_proposal_payloads grows; spend-bundle state is untouched (slash bytes still participate in the BLD-002
bincode(L2Block) size probe on later Self::add_spend_bundle calls).
Sourcepub fn set_l1_proofs(
&mut self,
collateral: Bytes32,
reserve: Bytes32,
prev_finalizer: Bytes32,
curr_finalizer: Bytes32,
network_coin: Bytes32,
)
pub fn set_l1_proofs( &mut self, collateral: Bytes32, reserve: Bytes32, prev_finalizer: Bytes32, curr_finalizer: Bytes32, network_coin: Bytes32, )
Set all five L1 proof anchor coin IDs at once (BLD-004).
Semantics: Each argument becomes Some(hash) on the builder, matching L2BlockHeader’s optional L1 proof
fields (L2BlockHeader::l1_collateral_coin_id … L2BlockHeader::l1_network_coin_id). Callers omitting L1
proofs should leave these as None (default from Self::new).
Overwrite: Later calls replace the entire quintuple — there is no partial merge.
Sourcepub fn set_dfsp_roots(
&mut self,
collateral_registry_root: Bytes32,
cid_state_root: Bytes32,
node_registry_root: Bytes32,
namespace_update_root: Bytes32,
dfsp_finalize_commitment_root: Bytes32,
)
pub fn set_dfsp_roots( &mut self, collateral_registry_root: Bytes32, cid_state_root: Bytes32, node_registry_root: Bytes32, namespace_update_root: Bytes32, dfsp_finalize_commitment_root: Bytes32, )
Set all five DFSP data-layer Merkle roots (BLD-004).
Semantics: Mirrors L2BlockHeader’s DFSP root block (L2BlockHeader::collateral_registry_root …
L2BlockHeader::dfsp_finalize_commitment_root). Pre-activation callers typically keep EMPTY_ROOT values
(SVL-002); post-activation, pass real roots before build() (BLD-005 validates against version).
Sourcepub fn set_extension_data(&mut self, extension_data: Bytes32)
pub fn set_extension_data(&mut self, extension_data: Bytes32)
Set the header extension hash (BLD-004).
Semantics: Stored as L2BlockHeader::extension_data; Self::new initializes to ZERO_HASH like
L2BlockHeader::new.
Sourcepub fn build(
self,
state_root: Bytes32,
receipts_root: Bytes32,
signer: &dyn BlockSigner,
) -> Result<L2Block, BuilderError>
pub fn build( self, state_root: Bytes32, receipts_root: Bytes32, signer: &dyn BlockSigner, ) -> Result<L2Block, BuilderError>
Finalize this builder into a signed L2Block (BLD-005).
Parameters: state_root / receipts_root come from the execution + receipt pipeline outside this crate
(see module-level Rationale). signer produces the BLS attestation over L2BlockHeader::hash (HSH-001).
Pipeline: Computes Merkle roots and counts using the same public functions as L2Block::validate_structure
(compute_spends_root, compute_additions_root, compute_removals_root, L2Block::slash_proposals_root_from,
compute_filter_hash), sets wall-clock L2BlockHeader::timestamp, runs the two-pass block_size fill
(assemble with block_size == 0, measure L2Block::compute_size, write), then signs.
Errors: BuilderError::EmptyBlock if no spend bundles (ERR-004);
BuilderError::MissingDfspRoots when VERSION_V2 applies but all DFSP roots are still
EMPTY_ROOT; BuilderError::SigningFailed wraps crate::traits::SignerError.
DFSP activation: Uses crate::DFSP_ACTIVATION_HEIGHT. For tests or fork simulation with a different
activation height, call Self::build_with_dfsp_activation instead.
Sourcepub fn build_with_dfsp_activation(
self,
state_root: Bytes32,
receipts_root: Bytes32,
signer: &dyn BlockSigner,
dfsp_activation_height: u64,
) -> Result<L2Block, BuilderError>
pub fn build_with_dfsp_activation( self, state_root: Bytes32, receipts_root: Bytes32, signer: &dyn BlockSigner, dfsp_activation_height: u64, ) -> Result<L2Block, BuilderError>
Like Self::build, but supplies an explicit dfsp_activation_height for BLK-007 / SVL-001 version selection and
the BLD-005 DFSP-root precondition (BuilderError::MissingDfspRoots).
Rationale: Crate tests keep DFSP_ACTIVATION_HEIGHT at u64::MAX (DFSP off) so normal build() always
selects crate::VERSION_V1. Passing a finite dfsp_activation_height ≤ Self::height forces V2 in
integration tests without recompiling constants.
Auto Trait Implementations§
impl Freeze for BlockBuilder
impl RefUnwindSafe for BlockBuilder
impl Send for BlockBuilder
impl Sync for BlockBuilder
impl Unpin for BlockBuilder
impl UnsafeUnpin for BlockBuilder
impl UnwindSafe for BlockBuilder
Blanket Implementations§
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> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self to use its Binary implementation when Debug-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self to use its Display implementation when
Debug-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self to use its LowerExp implementation when
Debug-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self to use its LowerHex implementation when
Debug-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self to use its Octal implementation when Debug-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self to use its Pointer implementation when
Debug-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self to use its UpperExp implementation when
Debug-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self to use its UpperHex implementation when
Debug-formatted.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> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self, then passes self.as_ref() into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self, then passes self.as_mut() into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self, then passes self.deref() into the pipe function.Source§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B> of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B> of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R> view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R> view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap() only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow() only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut() only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref() only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut() only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref() only in debug builds, and is erased in release
builds.