action_lock.rs
Overview
This file implements the authority switch protocol for managing block production and attestation locking in a multi-threaded blockchain node environment. Its primary responsibility is to maintain and update locks on blocks in various rounds, coordinate block producer threads, process incoming requests related to round changes, and handle the lifecycle and state transitions of blocks as they move through prefinalization and finalization stages.
The protocol ensures consensus on the "locked" block per round, protects against conflicting attestations, and orchestrates block production with respect to the network's current state and authority votes. Durability of locks is guaranteed via persistent storage to avoid stake slashing on restarts.
Main Entities and Structures
BlockRef
pub struct BlockRef {
block_seq_no: BlockSeqNo,
block_identifier: BlockIdentifier,
}
Purpose: Represents a reference to a block, consisting of its sequence number and unique identifier.
Implements
TryFrom<&BlockState>to try to create aBlockReffrom a block state, returning errors if sequence number or round is missing.
Usage Example:
let block_ref = BlockRef::try_from(&block_state)?;
StartBlockProducerThreadInitialParameters
pub struct StartBlockProducerThreadInitialParameters {
thread_identifier: ThreadIdentifier,
parent_block_identifier: BlockIdentifier,
parent_block_seq_no: BlockSeqNo,
round: BlockRound,
nacked_blocks_bad_block: Vec<Arc<Envelope<GoshBLS, AckiNackiBlock>>>,
proof_of_valid_start: Vec<Envelope<GoshBLS, Lock>>,
}
Holds initial parameters required for starting a block producer thread.
Contains the thread ID, parent block identification, round, and proofs needed to validate the start.
BlockProducerCommand
pub enum BlockProducerCommand {
Start(StartBlockProducerThreadInitialParameters),
}
Enum for commands sent to block producer threads. Currently supports only
Start.
ActionLock
pub struct ActionLock {
parent_block_producer_selector_data: ProducerSelector,
parent_block: BlockRef,
parent_prefinalization_proof: Option<Envelope<GoshBLS, AttestationData>>,
locked_round: BlockRound,
locked_block: Option<(BlockRound, BlockRef)>,
locked_bad_block_nacks: HashSet<BlockIdentifier>,
}
Represents the lock state associated with a block height.
Stores which block is currently locked for a particular round.
Contains the proof of parent block prefinalization and BLS selector data.
Tracks "bad block" nacks that must be included in the produced block.
Authority
pub struct Authority {
authorities: HashMap<ThreadIdentifier, Arc<Mutex<ThreadAuthority>>>,
round_buckets: RoundTime,
data_dir: PathBuf,
node_identifier: NodeIdentifier,
bls_keys_map: Arc<Mutex<HashMap<PubKey, (Secret, RndSeed)>>>,
block_repository: RepositoryImpl,
block_state_repository: BlockStateRepository,
network_direct_tx: NetDirectSender<NodeIdentifier, NetworkMessage>,
bp_production_count: Arc<AtomicI32>,
network_broadcast_tx: NetBroadcastSender<NetworkMessage>,
node_joining_timeout: Duration,
action_lock_db: ActionLockStorage,
max_lookback_block_height_distance: usize,
self_addr: SocketAddr,
action_lock_collections: HashMap<ThreadIdentifier, ActionLockCollection>,
}
Central structure managing all thread authorities.
Holds repositories, network channels, cryptographic keys, and collections of action locks.
Provides method
get_thread_authorityto get or create aThreadAuthorityfor a given thread.
ThreadAuthority
pub struct ThreadAuthority {
thread_id: ThreadIdentifier,
round_buckets: RoundTime,
node_identifier: NodeIdentifier,
bls_keys_map: Arc<Mutex<HashMap<PubKey, (Secret, RndSeed)>>>,
action_lock: ActionLockCollection,
confirmed_bad_block_nacks: HashMap<SiblingsBlockHeightKey, HashSet<BlockIdentifier>>,
collecting_next_round: HashMap<(SiblingsBlockHeightKey, BlockRound), CollectedAuthoritySwitchRoundRequests>,
closed_round: HashMap<SiblingsBlockHeightKey, BlockRound>,
block_producers: Option<std::sync::mpsc::Sender<BlockProducerCommand>>,
block_repository: RepositoryImpl,
block_state_repository: BlockStateRepository,
network_direct_tx: NetDirectSender<NodeIdentifier, NetworkMessage>,
bp_production_count: Arc<AtomicI32>,
network_broadcast_tx: NetBroadcastSender<NetworkMessage>,
node_joining_timeout: Duration,
last_node_joining_sent: Instant,
max_lookback_block_height_distance: usize,
self_node_authority_tx: Option<XInstrumentedSender<(NetworkMessage, SocketAddr)>>,
self_addr: SocketAddr,
}
Manages authority-related operations for a single thread.
Maintains local action locks, bad block nacks, round requests, and communication channels.
Implements core protocol logic such as locking attestations, handling next round requests, and starting block producers.
ActionLockCollection
pub struct ActionLockCollection {
preloaded: HashMap<BlockHeight, Option<ActionLock>>,
data_dir: PathBuf,
action_lock_db: ActionLockStorage,
}
Manages cached and persisted
ActionLockinstances indexed byBlockHeight.Responsible for loading, saving, inserting, and removing locks.
Ensures durability of locks by interfacing with persistent storage (
ActionLockStorage).
Key Functions and Methods
Authority::get_thread_authority
Retrieves or creates a
ThreadAuthorityinstance for a given thread identifier.Lazily initializes
ThreadAuthoritywith required dependencies and state.
ThreadAuthority::try_lock_send_attestation_action
pub fn try_lock_send_attestation_action(
&mut self,
block_identifier: &BlockIdentifier,
) -> ActionLockResult
Attempts to lock an attestation action for a given block.
Checks block state for finalization, invalidation, and nack resolution.
Computes local round based on elapsed time since parent block.
Updates or creates an
ActionLockif the block round is newer or equal.Returns
OkSendAttestationif lock is acquired; otherwiseRejected.
Usage Example:
match thread_authority.try_lock_send_attestation_action(&block_id) {
ActionLockResult::OkSendAttestation => { /* proceed with attestation */ }
ActionLockResult::Rejected => { /* do not attest */ }
}
ThreadAuthority::on_block_producer_stalled
pub fn on_block_producer_stalled(&mut self) -> OnBlockProducerStalledResult
Triggered when block production is stalled.
Retrieves last prefinalized block and determines next block height.
Calls
start_next_roundto initiate the next production round or retry later.
ThreadAuthority::start_next_round
fn start_next_round(
&mut self,
parent_block: BlockState,
block_height: BlockHeight,
) -> OnBlockProducerStalledResult
Core logic for starting the next block production round.
Loads or removes stale
ActionLock.Calculates local round and verifies timing constraints.
Prepares attestation data for locked block and ancestors.
Constructs and signs a
Lockmessage.Sends
NextRoundrequests to the current and next block producers.Returns
OnBlockProducerStalledResultindicating next deadline and round info.
ThreadAuthority::on_next_round_incoming_request
pub fn on_next_round_incoming_request(
&mut self,
next_round_message: NextRound,
sender: Option<SocketAddr>,
unprocessed_blocks_cache: UnfinalizedCandidateBlockCollection,
) -> OnNextRoundIncomingRequestResult
Handles incoming
NextRoundrequests from other nodes.Validates signatures, block height, and lock state.
Checks if the request is for this node and if round is not closed.
Collects requests for quorum counting.
If quorum (50%+1) is reached:
Aggregates attestations and locked blocks.
Decides whether to broadcast
NextRoundSuccessor start block production.
Implements rejection for stale rounds or duplicate prefinalized blocks.
ThreadAuthority::on_next_round_success
pub fn on_next_round_success(&mut self, next_round_success: &NextRoundSuccess)
Processes broadcast messages indicating consensus on the next round.
Updates or creates
ActionLockwith the winning locked block.Invalidates competing blocks that lost the authority switch.
Stores new lock state and triggers any further processing.
ActionLockCollection Methods
new(data_dir: PathBuf, action_lock_db: ActionLockStorage) -> Self
Initializes the collection.get_mut(&mut self, block_height: &BlockHeight, block_state_repository: &BlockStateRepository) -> Option<&mut ActionLock>
Returns mutable reference to an active lock for the height; preloads if necessary.get(&mut self, block_height: &BlockHeight, block_state_repository: &BlockStateRepository) -> Option<&ActionLock>
Returns immutable reference to an active lock.insert(&mut self, block_height: BlockHeight, action_lock: ActionLock)
Inserts or updates a lock.remove(&mut self, block_height: &BlockHeight)
Marks a lock as inactive.drop_old_locks(&mut self, block_height: &BlockHeight)
Removes locks older than the given height in the same thread.save(&self, block_height: &BlockHeight)
Persists a lock to disk or database.preload(&mut self, block_height: &BlockHeight)
Loads a lock from storage if not already cached.
Important Implementation Details
Durability:
ActionLockinstances are persisted on disk or throughActionLockStorage. This is critical to avoid stake slashing on node restarts.Round Calculation:
UsesRoundTimeand elapsed duration from the parent block timestamp to determine the current round number and remaining time.Locking Logic:
The locking mechanism ensures only one block per round can be locked, with updates possible if a newer round or block appears.Quorum Collection:
IncomingNextRoundrequests are collected, and when a quorum (>50%) is reached, aNextRoundSuccessmessage is broadcasted.Signature Verification:
Every incoming lock message verifies BLS signatures against the block keeper set (bk_set) to validate authenticity.Block Producer Coordination:
The file manages block producer threads by sending commands to start production when appropriate.Handling NACKs:
Keeps track of bad block NACKs to ensure they are included in new blocks to maintain consensus validity.Timing and Retry:
Implements retry logic with configurable timeouts when blocks are stalled or network conditions prevent progress.
Interactions with Other System Components
Block Repositories:
Interacts withblock_repositoryandblock_state_repositoryto fetch block state and metadata.Network Messaging:
Usesnetwork_direct_txandnetwork_broadcast_txto send direct and broadcast messages, respectively, for the authority switch protocol.BLS Cryptography:
Uses BLS keys and envelopes for signing and verifying messages related to locks and attestations.Block Producer Threads:
Sends commands to block producer threads (BlockProducerCommand) to start producing new blocks when conditions are met.Node Joining Broadcast:
Broadcasts node joining messages when this node is not part of the current block keeper set.ActionLockStorage:
Persistent storage interface for saving and loading action locks to ensure durability.Utilities:
Uses guarded mutability utilities (AllowGuardedMut,GuardedMut) for safe concurrent access to block states.
Visual Diagram
classDiagram
class Authority {
+get_thread_authority()
}
class ThreadAuthority {
+try_lock_send_attestation_action()
+on_block_producer_stalled()
+start_next_round()
+on_next_round_incoming_request()
+on_next_round_success()
+register_block_producer()
+register_self_node_authority_tx()
}
class ActionLockCollection {
+get_mut()
+get()
+insert()
+remove()
+drop_old_locks()
+save()
+preload()
}
class ActionLock {
-parent_block_producer_selector_data
-parent_block
-parent_prefinalization_proof
-locked_round
-locked_block
-locked_bad_block_nacks
}
class BlockRef {
-block_seq_no
-block_identifier
}
class BlockProducerCommand {
<<enum>>
}
Authority "1" --> "*" ThreadAuthority : manages
ThreadAuthority "1" --> "1" ActionLockCollection : owns
ActionLockCollection "1" --> "*" ActionLock : manages
ActionLock *-- BlockRef : references
ThreadAuthority --> BlockProducerCommand : sends
This diagram depicts the main relationships:
Authoritymanages multipleThreadAuthorityinstances, one per thread.Each
ThreadAuthorityowns anActionLockCollectionthat manages multipleActionLocks.ActionLockinstances referenceBlockRefs to mark locked blocks.ThreadAuthoritysendsBlockProducerCommandto block producer threads.
Error Enums
BlockRefTryFromBlockStateError
Indicates missing sequence number or round when converting aBlockStatetoBlockRef.ActionLockResult
Possible results from attempting to lock send attestation: success or rejection.OnNextRoundIncomingRequestResult
Enum describing the outcome of processing an incoming next round request, including starting production, broadcasting success, rejecting, or ignoring.
Additional Notes
The file uses several concurrency primitives (
Arc,Mutex,AtomicI32) to safely share state across threads.It relies on cryptographic envelopes and BLS signatures for secure message signing and verification.
Timing is managed carefully with system time and durations to maintain consensus round synchronization.
The locking mechanism serves as a core part of the consensus protocol ensuring safety during block production and attestation phases.
The file interfaces with other modules such as block state repository, network messaging components, and cryptography libraries, integrating tightly into the node's consensus machinery.
For related concepts, see topics on Block State Management, BLS Cryptography, Network Messaging, and Consensus Protocols.