state.rs
Overview
This file defines the core data structure and associated logic for tracking the state of blocks within the system's consensus and validation layer. The primary entity is the AckiNackiBlockState, which serves as a comprehensive, write-once ledger of signals and facts about a block's status as it progresses through various stages such as validation, attestation, finalization, and storage.
The AckiNackiBlockState encapsulates metadata about a block, its relationships to other blocks, attestation proofs, verification flags, and bookkeeping related to block keepers and attestations. This structure enables the system to apply deterministic rules about block acceptance and finalization, critical for maintaining consensus integrity.
Supporting types like AttestationTarget, AttestationTargets, and EventTimestamps provide abstractions for attestation thresholds and timing metrics relevant to block processing.
Detailed Descriptions
Constants
MAX_STATE_ANCESTORS: NonZeroUsizeDefines the maximum number of ancestor blocks to keep track of for any block state.
Set to 10 by default.
Structs
AttestationTarget
Purpose: Represents a single attestation target, defining how many attestations are required and the deadline generation.
Fields:
generation_deadline: usize— The generation by which attestation must be completed.required_attestation_count: usize— Number of attestations required to meet this target.
Traits: Clone, Serialize, Deserialize, Debug, PartialEq, Copy, Getters, TypedBuilder
Usage: Used to specify attestation criteria for blocks to be considered finalized or pre-finalized.
AttestationTargets
Purpose: Holds two attestation targets: a primary and a fallback.
Fields:
primary: AttestationTarget— Main attestation target.fallback: AttestationTarget— Secondary fallback attestation target.
Traits: Clone, Serialize, Deserialize, Debug, PartialEq, Copy, Getters, TypedBuilder
AckiNackiBlockState
Purpose: Central structure to track all relevant signals and state facts for a single block.
Design Notes:
Implements a write-once pattern for all fields to ensure immutability after data is set.
Prefix conventions:
is_*for block-related fields.has_*for other blocks' states.was_*for signals from other nodes.
The struct is serializable and supports getters/setters with special patterns to enforce write-once semantics.
Maintains detailed information about attestations, finalization proofs, block ancestry, validation status, and bookkeeping.
Key Fields:
block_seq_no: Option<BlockSeqNo>— Sequence number of the block.block_identifier: BlockIdentifier— Unique identifier of the block.thread_identifier: Option<ThreadIdentifier>— Thread ID the block belongs to.parent_block_identifier: Option<BlockIdentifier>— Identifier of parent block.ancestors: Option<Vec<BlockIdentifier>>— List of ancestor blocks up to MAX_STATE_ANCESTORS.block_round: Option<BlockRound>— Round number in consensus.block_height: Option<BlockHeight>— Height of the block in the chain.producer: Option<NodeIdentifier>— Node that produced the block.block_time_ms: Option<u64>— Timestamp of the block.prefinalization_proof: Option<Envelope<GoshBLS, AttestationData>>— Proof that block cannot be finalized later unless a NACK is received.primary_finalization_proof: Option<Envelope<GoshBLS, AttestationData>>— Proof of primary finalization.fallback_finalization_proof: Option<Envelope<GoshBLS, AttestationData>>— Proof of fallback finalization.detached_attestations: Vec<Envelope<GoshBLS, AttestationData>>— Attestations received but not processed yet.signatures_verified: Option<bool>— Flag indicating if signatures were verified.common_checks_passed: Option<bool>— Flag for basic block data verification.applied: Option<bool>— Indicates if block was applied to parent state.validated: Option<bool>— Validation result flag.finalizes_blocks: Option<BTreeSet<BlockIndex>>— Blocks finalized by this block.must_be_validated: Option<bool>— Indicates immutability conditions related to validation.finalized: Option<bool>— Finalization status.prefinalized: Option<bool>— Prefinalization status.ancestor_blocks_finalization_checkpoints: Option<AncestorBlocksFinalizationCheckpoints>— Checkpoints for ancestor finalization.stored: Option<bool>— Indicates if block is stored in repository.invalidated: Option<bool>— Flag indicating block invalidity.bad_block_accusers: Vec<(HashMap<SignerIndex, u16>, <GoshBLS as BLSSignatureScheme>::Signature)>— Separate BLS signatures to track accusations.at_least_one_verified_bad_block_accuser: Option<bool>— Flag for verified bad block accusers.resolved_nacks_count: u64— Counter for resolved NACKs.bk_set, future_bk_set, descendant_bk_set, descendant_future_bk_set: Option<Arc> — Block keeper sets managing consensus authority.
has_parent_finalized: Option<bool>— Indicates if the parent block is finalized.producer_selector_data: Option<ProducerSelector>— Data to select block producers for descendants.has_all_cross_thread_ref_data_available, has_all_cross_thread_references_finalized, has_cross_thread_ref_data_prepared: Option flags for cross-thread reference data completeness.
has_primary_attestation_target_met, has_fallback_attestation_target_met: Option flags indicating attestation targets met.
attestation_target: Option<AttestationTargets>— Current attestation targets.verified_attestations: HashMap<(BlockIdentifier, AttestationTargetType), HashSet<SignerIndex>>— Verified attestations for this block indexed by block and target type.block_stats: Option<BlockStatistics>— Statistical data about the block.known_children: HashMap<ThreadIdentifier, HashSet<BlockIdentifier>>— Child blocks indexed by thread.own_attestation, own_fallback_attestation: Option<Envelope<GoshBLS, AttestationData>> — This node’s own attestations.
retracted_attestation: Option<Envelope<GoshBLS, NackData>>— Retracted attestations (NACKs).known_attestation_interested_parties: HashSet<NodeIdentifier>— Nodes interested in attestations for this block.envelope_hash: Option<AckiNackiEnvelopeHash>— Hash of the block envelope.has_block_attestations_processed: Option<bool>— Flag indicating block attestations processing status.file_path: PathBuf— Path to the stored block state file.notifications: Vec<Notification>— Subscribers to block state changes.event_timestamps: EventTimestamps— Timing metrics related to block state events.object_state_version, last_saved_object_state_version: u64 — Versioning for saved state changes.
Traits:
Serialize, Deserialize, Default,
Getters, SettersCustom Debug (only prints limited fields for brevity)
Displayfor string representation.
Notable Methods:
new(block_identifier: BlockIdentifier) -> SelfCreates a new block state instance for a given block identifier.
Initializes has_all_cross_thread_references_finalized to
true.
add_detached_attestations(&mut self, attestation: Envelope<GoshBLS, AttestationData>)Adds attestations that cannot be processed immediately.
has_attestations_target_met(&self) -> boolReturns
trueif primary attestation target has been met.
can_be_finalized(&self) -> boolChecks if block meets all conditions for finalization, including:
Signatures verified, not invalidated.
All NACKs resolved.
Block applied.
Parent finalized.
Cross-thread references available and prepared.
apply_can_be_skipped(&self) -> boolDetermines if block application step can be skipped due to finalized or verified status.
has_bad_block_nacks_resolved(&self) -> boolReturns true if there are no bad block accusers or validation succeeded.
set_parent_block_identifier(&mut self, block_identifier: BlockIdentifier) -> anyhow::Result<()>Sets the parent block identifier.
set_finalized(&mut self) -> anyhow::Result<()>Marks the block as finalized and triggers change notification.
set_invalidated(&mut self) -> anyhow::Result<()>Marks the block as invalidated and triggers change notification.
set_stored(&mut self, block: &Envelope<GoshBLS, AckiNackiBlock>) -> anyhow::Result<()>Marks block as stored and computes envelope hash.
set_applied(&mut self, start_time: std::time::Instant, _end_time: std::time::Instant) -> anyhow::Result<()>Marks block as applied and records application start time.
has_all_nacks_resolved(&self) -> boolAlias for checking if bad block NACKs are resolved.
is_invalidated(&self) -> boolReturns true if block is invalidated.
is_signatures_verified(&self) -> boolReturns true if signatures verification succeeded.
is_finalized(&self) -> boolReturns true if block is finalized.
is_prefinalized(&self) -> boolReturns true if block is prefinalized.
is_stored(&self) -> boolReturns true if block is stored.
is_block_already_applied(&self) -> boolReturns true if block application step completed.
add_suspicious(&mut self, accusers: HashMap<SignerIndex, u16>, signatures: <GoshBLS as BLSSignatureScheme>::Signature) -> anyhow::Result<()>Adds a suspicious accuser signature set if not already present.
verified_attestations_for(&self, block_identifier: &BlockIdentifier, attestation_target_type: AttestationTargetType) -> Option<HashSet<SignerIndex>>Retrieves verified attestations for a given block and attestation target type.
Returns None if signatures not verified.
try_add_attestations_interest(&mut self, node_identifier: NodeIdentifier) -> anyhow::Result<bool>Attempts to add a node to the interested parties for attestations.
Returns
trueif new interest was added.
add_verified_attestations_for(&mut self, block_identifier: BlockIdentifier, attestation_target_type: AttestationTargetType, attestation_signers: HashSet<SignerIndex>) -> anyhow::Result<()>Adds a set of verified attestations for a block and target type.
add_child(&mut self, child_block_thread_identifier: ThreadIdentifier, child_block_identifier: BlockIdentifier) -> anyhow::Result<()>Adds a child block to the known children map.
known_children(&self, child_block_thread_identifier: &ThreadIdentifier) -> Option<&HashSet<BlockIdentifier>>Retrieves known children for a specific thread.
known_children_for_all_threads(&self) -> HashSet<BlockIdentifier>Retrieves all known children across all threads.
get_signer_index_for_node_id(&self, node_id: &NodeIdentifier) -> Option<SignerIndex>Gets the signer index for a given node ID from the block keeper set.
get_bk_data_for_node_id(&self, node_id: &NodeIdentifier) -> Option<BlockKeeperData>Retrieves block keeper data for a node.
dump(&mut self) -> anyhow::Result<()>Saves the current block state.
save(&mut self) -> anyhow::Result<()>Internal save implementation increasing state version and persisting.
notify_changed(&mut self) -> anyhow::Result<()>Marks the state as changed and updates version.
set_prefinalized(&mut self, proof: Envelope<GoshBLS, AttestationData>) -> anyhow::Result<()>Sets the block as prefinalized with an attestation proof.
add_subscriber(&mut self, notifications: Notification)Adds a notification subscriber.
remove_subscriber(&mut self, notifications: &Notification)Removes a notification subscriber.
EventTimestamps
Purpose: Records various timing metrics related to block state events.
Fields:
received_ms: Option<u64>— When the block was received (ms).attestation_sent_ms: Option<u64>— When attestations were sent.verify_all_block_signatures_ms_total: Option<u128>— Total time spent verifying signatures.block_process_timestamp_was_reported: bool— Flag if processing timestamp was reported.block_applied_timestamp_ms: Option<u64>— When block was applied (ms).
Traits: Copy, Clone, Debug, Serialize, Deserialize, Default
Trait Implementations
AllowGuardedMut for
AckiNackiBlockStateProvides controlled mutable access via inner_guarded_mut method.
Executes the provided closure on mutable reference to the state.
Custom Debug implementation for concise debug output focusing on block_seq_no and block_identifier.
Displayimplementation for string representation showing block id and sequence number.
Important Implementation Details and Algorithms
Write-Once Pattern: All fields in
AckiNackiBlockStateare designed to be set once and only once, enforced via setter macros (derive_setters) with assert_none to prevent overwriting. This ensures history immutability and consistent state progression.Attestation Proofs:
Differentiates between prefinalization proof and finalization proofs (primary and fallback).
Finalization requires complex attestation thresholds (e.g., 66%, or 50%+1 with fallback).
Attestations are tracked and verified before finalization is allowed.
Bad Block Accuser Tracking:
Stores separate BLS signatures from accusers to provide verifiable evidence against malicious blocks.
Accusers are tracked individually to facilitate blame assignment.
Block Keeper Sets:
Maintains multiple BlockKeeperSet instances representing current, future, and descendant block keepers.
These sets influence the block producer selection and attestation validation.
Cross-Thread References:
Uses flags to track availability and finalization of cross-thread reference data, crucial in multi-threaded blockchains or sharded architectures.
Notification Mechanism:
Subscribers can register to receive notifications on state changes.
The touch method updates notification timestamps, useful for monitoring or triggering updates.
Versioning:
Tracks object state version and last saved version to support persistence and state synchronization.
Interactions with Other Components
AncestorBlocksFinalizationCheckpoints
Used to track finalization checkpoints of ancestor blocks.
BlockKeeperSet and BlockKeeperData
Represents sets of validators or authorities responsible for block finalization and consensus.
Envelope<GoshBLS, AttestationData>Encapsulates cryptographic attestations and signatures using the BLS signature scheme.
Subscriber pattern for propagating state changes to interested components.
BlockIdentifier, BlockSeqNo, ThreadIdentifier, etc.Various types representing unique identifiers for blocks, threads, and sequences, facilitating block lineage tracking.
ProducerSelectorUsed to compute or store which nodes are responsible for block production downstream.
Differentiates between primary and fallback attestation targets.
Persistence Layer
The save and
notify_changedmethods interact with a private persistence module (super::private::save) to serialize and store block state.
Usage Examples
use some_crate::state::AckiNackiBlockState;
use some_crate::types::{BlockIdentifier, Envelope, GoshBLS, AttestationData};
// Create a new block state for a block
let block_id = BlockIdentifier::new(...);
let mut block_state = AckiNackiBlockState::new(block_id);
// Add detached attestations
let attestation: Envelope<GoshBLS, AttestationData> = ...;
block_state.add_detached_attestations(attestation);
// Check if attestation targets have been met
if block_state.has_attestations_target_met() {
// Proceed with finalization
}
// Mark block as finalized
block_state.set_finalized()?;
Visual Diagram
classDiagram
class AckiNackiBlockState {
+block_seq_no: Option<BlockSeqNo>
+block_identifier: BlockIdentifier
+thread_identifier: Option<ThreadIdentifier>
+parent_block_identifier: Option<BlockIdentifier>
+ancestors: Option<Vec<BlockIdentifier>>
+block_round: Option<BlockRound>
+block_height: Option<BlockHeight>
+producer: Option<NodeIdentifier>
+signatures_verified: Option<bool>
+finalized: Option<bool>
+invalidated: Option<bool>
+verified_attestations: HashMap<(BlockIdentifier, AttestationTargetType), HashSet<SignerIndex>>
+known_children: HashMap<ThreadIdentifier, HashSet<BlockIdentifier>>
+bad_block_accusers: Vec<(HashMap<SignerIndex, u16>, Signature)>
+notifications: Vec<Notification>
+event_timestamps: EventTimestamps
+add_detached_attestations()
+can_be_finalized