mod.rs
Overview
This file implements the Attestation Send Service, responsible for managing the creation, tracking, and distribution of attestations related to unfinalized blocks within the blockchain protocol. It periodically evaluates the state of candidate blocks, generates attestations as needed, and sends them to interested parties in the network. The service ensures that attestations are sent in compliance with protocol timing constraints and handles retransmission logic. It also collects and reports metrics associated with block attestation events.
The file primarily contains the AttestationSendService struct, which encapsulates the core logic, and the AttestationSendServiceHandler struct, which manages the service execution thread.
Key Components
Enum: AttestationAction
enum AttestationAction {
ThisBlock(Envelope<GoshBLS, AttestationData>),
// Fork variant commented out
}
Represents an action related to an attestation.
Currently supports only the
ThisBlockvariant, which wraps an attestation envelope.The commented-out
Forkvariant hints at future support for attestations involving forked candidate blocks.
Struct: TrackedState
struct TrackedState {
block_state: BlockState,
interested_parties_received_blocks: Option<HashSet<(NodeIdentifier, AttestationTargetType)>>,
first_send_timestamp: Option<std::time::Instant>,
last_send_timestamp: Option<std::time::Instant>,
last_send_destinations: Option<HashSet<(NodeIdentifier, AttestationTargetType)>>,
}
Maintains tracking information per candidate block.
Fields:
block_state: The current state of the candidate block.interested_parties_received_blocks: Keeps track of which nodes (and attestation target types) have received the block.first_send_timestamp: Time when the attestation was first sent.last_send_timestamp: Time when the attestation was last sent.last_send_destinations: Nodes (and attestation target types) to which the attestation was last sent.
Implements getter and setter methods via derive macros.
Used internally by
AttestationSendServiceto manage candidate block attestations.
Struct: AttestationSendService
pub struct AttestationSendService {
pub pulse_timeout: Duration,
resend_attestation_timeout: Duration,
node_id: NodeIdentifier,
thread_id: ThreadIdentifier,
bls_keys_map: Arc<Mutex<HashMap<PubKey, (Secret, RndSeed)>>>,
block_state_repository: BlockStateRepository,
tracking: HashMap<BlockIdentifier, TrackedState>,
block_state_repository_last_modified: u32,
condidates_set_last_modified: u32,
network_direct_tx: NetDirectSender<NodeIdentifier, NetworkMessage>,
start_time: Instant,
_rng: SmallRng,
metrics: Option<BlockProductionMetrics>,
authority: Arc<Mutex<Authority>>,
}
Core service handling attestation generation and distribution.
Important fields:
pulse_timeout: Duration controlling the timing between attestation pulses.resend_attestation_timeout: Timeout for resending attestations to nodes.node_id: Identifier of this node.thread_id: Identifier of the thread managing the service.bls_keys_map: Map of BLS public keys to their secrets and seeds, used for signing.block_state_repository: Repository managing block states.tracking: Map of block identifiers to their tracking state.network_direct_tx: Network channel to send messages directly to nodes._rng: Random number generator used for internal non-security randomization.metrics: Optional metrics collector to report block production and attestation metrics.authority: Authority manager for locking and concurrency control.
Methods of AttestationSendService
evaluate
pub fn evaluate(
&mut self,
candidates: &UnfinalizedBlocksSnapshot,
loopback_attestations: Arc<Mutex<CollectedAttestations>>,
candidate_block_repository: &impl Repository<CandidateBlock = Envelope<GoshBLS, AckiNackiBlock>>,
deadline: Instant,
) -> Instant
Main periodic evaluation method, triggered to process candidate blocks and send attestations.
Parameters:
candidates: Snapshot of unfinalized candidate blocks.loopback_attestations: Shared collection to store attestations sent to self.candidate_block_repository: Repository interface for candidate blocks.deadline: Next scheduled deadline for the evaluation.
Returns: The instant representing the next deadline to run evaluation.
Behavior:
Checks if the block state repository or candidates have changed since the last evaluation.
If no changes and deadline not reached, returns current deadline.
Otherwise:
Updates tracking with new candidates.
Stops tracking finalized or invalidated blocks.
Updates tracking information about nodes that have received blocks.
Calls
pulseto send attestations as necessary.
Usage example:
let next_deadline = attestation_service.evaluate(
&candidates_snapshot,
loopback_attestations.clone(),
&candidate_repo,
current_deadline,
);
try_get_attestation
fn try_get_attestation(&self, state: &TrackedState) -> anyhow::Result<Envelope<GoshBLS, AttestationData>>
Attempts to retrieve or generate the primary attestation for a tracked block.
If the attestation already exists in
block_state, returns it.Otherwise, generates a new attestation using
generate_attestationwithAttestationTargetType::Primary.On failure, logs trace information and returns error.
try_get_fallback_attestation
fn try_get_fallback_attestation(&self, state: &TrackedState) -> anyhow::Result<Envelope<GoshBLS, AttestationData>>
Similar to
try_get_attestation, but generates or retrieves a fallback attestation.Uses
AttestationTargetType::Fallbackwhen generating.
pulse
fn pulse(
&mut self,
loopback_attestations: Arc<Mutex<CollectedAttestations>>,
_candidate_block_repository: &impl Repository<CandidateBlock = Envelope<GoshBLS, AckiNackiBlock>>,
) -> Instant
Core logic that sends attestations to interested nodes based on timing and tracking states.
Parameters:
loopback_attestations: Storage for attestations sent to self._candidate_block_repository: Currently unused parameter for candidate block repository.
Returns: The next instant to schedule sending.
Process:
Iterates over tracked blocks to decide if it's time to send attestations.
Checks timing constraints such as earliest allowed send time.
Determines which nodes still need to receive attestations or fallback attestations.
Uses authority locks to ensure only one attestation per block is sent at a time.
Sends attestations over the network or adds them to loopback collection if destination is self.
Updates tracking timestamps.
Includes detailed handling of block states, parent block states, and related timing computations.
send_block_attestation
fn send_block_attestation(
&self,
destination_node_id: NodeIdentifier,
attestation: AttestationAction,
) -> anyhow::Result<()>
Sends a block attestation to a specific node via the network.
Parameters:
destination_node_id: The node to send the attestation to.attestation: The attestation action to send.
Sends a
NetworkMessage::BlockAttestationmessage vianetwork_direct_tx.Logs sending activity.
If the destination is self, adds to
loopback_attestationsinstead.Handles errors gracefully, especially during shutdown.
generate_attestation
pub fn generate_attestation(
bls_keys_map: Arc<Mutex<HashMap<PubKey, (Secret, RndSeed)>>>,
node_id: &NodeIdentifier,
block_state: &BlockState,
attestation_target_type: AttestationTargetType,
) -> anyhow::Result<Envelope<GoshBLS, AttestationData>>
Generates a new attestation envelope for a given block state.
Parameters:
bls_keys_map: Map of BLS keys to sign attestation.node_id: The node creating the attestation.block_state: Current block state to attest.attestation_target_type: Primary or fallback attestation type.
Returns: Signed attestation envelope or error.
Algorithm:
Retrieves BLS key data specific for the node.
Extracts block sequence number and parent block identifier.
Builds
AttestationDatawith block metadata and target type.Signs data using
GoshBLSsignature scheme.Wraps signature and data into an
Envelope.
Errors if required data is missing or signing fails.
stop_tracking_finalized_and_invalidated_candidates
fn stop_tracking_finalized_and_invalidated_candidates(&mut self)
Removes blocks from tracking if they are finalized or invalidated.
Uses
retainon the tracking map to keep only active candidate blocks.Logs removed block identifiers for traceability.
append_for_tracking
fn append_for_tracking(&mut self, candidates: &UnfinalizedBlocksSnapshot)
Adds new candidate blocks to the tracking map.
Removes any tracked blocks no longer present in the candidate snapshot.
Ensures tracking state is consistent with the latest unfinalized blocks.
update_interested_parties_received_blocks
fn update_interested_parties_received_blocks(&mut self, candidates: &UnfinalizedBlocksSnapshot)
Updates tracking information about which parties have received specific blocks.
Uses
collect_attested_blocks_to_receiverto determine blocks with attestations from producers.Updates the
interested_parties_received_blocksinTrackedState.
collect_attested_blocks_to_receiver
fn collect_attested_blocks_to_receiver(
&mut self,
candidate: &BlockState,
) -> HashMap<BlockIdentifier, (NodeIdentifier, AttestationTargetType)>
For a given candidate block, collects a map of blocks to the node and attestation target type that have attested to it.
Checks if signatures include this node's signer index and if the producer is interested.
Returns a mapping to be used for tracking.
update_tracking
fn update_tracking(
&mut self,
attested_blocks_to_parties: HashMap<BlockIdentifier, (NodeIdentifier, AttestationTargetType)>,
)
Updates the tracking state with new information about which nodes have received attestations.
Inserts interested parties into the
interested_parties_received_blocksset per block.
handle_attestation_metrics
fn handle_attestation_metrics(&self, block_id: &BlockIdentifier)
Wrapper to call the internal metrics handler with error suppression.
handle_attestation_metrics_inner
fn handle_attestation_metrics_inner(&self, block_id: &BlockIdentifier) -> anyhow::Result<()>
Reports and updates various timing metrics related to attestation sending.
Metrics include delays from block reception to attestation sending, verification times, and parent-child attestation timing.
Uses
block_state_repositoryto get and update timestamps.Logs warnings if timestamps are inconsistent.
Struct: AttestationSendServiceHandler
pub struct AttestationSendServiceHandler {
_service_handler: std::thread::JoinHandle<()>,
}
Manages the lifecycle of the attestation send service in a dedicated thread.
Spawns a critical thread named
"Attestation send service"that continuously runs theevaluateloop.Monitors the shutdown flag and waits on block state repository notifications with a timeout.
Ensures proper concurrency and periodic invocation of the service.
Methods of AttestationSendServiceHandler
new
pub fn new(
mut attestation_sender_service: AttestationSendService,
repository: RepositoryImpl,
last_block_attestations: Arc<Mutex<CollectedAttestations>>,
block_state_repository: BlockStateRepository,
unprocessed_blocks_cache: UnfinalizedCandidateBlockCollection,
) -> Self
Constructs and starts the attestation send service handler thread.
Takes ownership of the service, repository, attestation collection, block state repository, and unprocessed blocks cache.
The thread runs the continuous evaluation loop invoking
evaluateand waiting for updates or timeout.
Implementation Details and Algorithms
Attestation Timing: The service uses a
pulse_timeoutthat is dynamically adjusted based on the distance to the block producer and the timing of parent block attestations. This ensures attestations are sent neither too early nor too late, respecting protocol deadlines and mitigating block jamming attacks.Tracking Mechanism: The
trackingmap maintains per-block state including timestamps and which nodes have received attestations, allowing selective retransmission only to nodes that have not yet received attestations or when resend timeouts expire.Authority Locks: Before sending an attestation, the service acquires a lock via
authority.try_lock_send_attestation_actionto avoid duplicated or conflicting attestation sends for the same block.Metrics Collection: The service updates timing metrics at various stages, such as attestation sent delay and parent-child attestation delays, facilitating performance monitoring and analysis.
Loopback Handling: Attestations destined for the local node are added directly to
loopback_attestationsto avoid unnecessary network transmission.
Interaction with Other System Components
BlockStateRepository: Used extensively to retrieve and update block states, including obtaining information about parent blocks, signatures, and attestation status.
Network Layer:
network_direct_txenables sending attestation messages directly to other nodes in the network.Authority: Used to manage concurrency and ensure attestation send actions are mutually exclusive per block.
Candidate Block Repository: Provides access to candidate blocks, though currently used minimally in the
pulsemethod.CollectedAttestations: Shared storage for storing attestations received or sent locally, supporting loopback and further processing.
Metrics System: Optional integration for reporting attestation-related performance metrics.
UnfinalizedBlocksSnapshot / UnfinalizedCandidateBlockCollection: Represents the current set of unfinalized blocks the service must evaluate.
Shutdown Flag: Global flag to gracefully stop the service thread.
Visual Diagram: Class Diagram of AttestationSendService
classDiagram
class AttestationSendService {
+pulse_timeout: Duration
-resend_attestation_timeout: Duration
-node_id: NodeIdentifier
-thread_id: ThreadIdentifier
-bls_keys_map: Arc<Mutex<HashMap>>
-block_state_repository: BlockStateRepository
-tracking: HashMap<BlockIdentifier, TrackedState>
-network_direct_tx: NetDirectSender
-start_time: Instant
-_rng: SmallRng
-metrics: Option<BlockProductionMetrics>
-authority: Arc<Mutex<Authority>>
+evaluate()
-try_get_attestation()
-try_get_fallback_attestation()
-pulse()
-send_block_attestation()
+generate_attestation()
-stop_tracking_finalized_and_invalidated_candidates()
-append_for_tracking()
-update_interested_parties_received_blocks()
-collect_attested_blocks_to_receiver()
-update_tracking()
-handle_attestation_metrics()
}
class TrackedState {
-block_state: BlockState
-interested_parties_received_blocks: Option<HashSet>
-first_send_timestamp: Option<Instant>
-last_send_timestamp: Option<Instant>
-last_send_destinations: Option<HashSet>
+getters()
+setters()
}
AttestationSendService "1" *-- "many" TrackedState : tracking
Usage Example of Service Initialization
let attestation_service = AttestationSendService::builder()
.pulse_timeout(Duration::from_millis(100))
.resend_attestation_timeout(Duration::from_secs(10))
.node_id(my_node_id)
.thread_id(my_thread_id)
.bls_keys_map(arc_bls_keys_map)
.block_state_repository(block_state_repo)
.network_direct_tx(net_sender)
.authority(arc_authority)
.build();
let handler = AttestationSendServiceHandler::new(
attestation_service,
repository_impl,
last_block_attestations,
block_state_repository,
unprocessed_blocks_cache,
);
This starts the service in a dedicated thread that will handle attestations autonomously.
Notes
Some code sections and variants are commented out, indicating ongoing or planned enhancements such as handling attestations for forks.
The service relies heavily on concurrency-safe constructs (
Arc<Mutex<...>>) and thread-safe collections.The file uses extensive tracing for debugging and auditing attestation sending flows.
The design enforces separation of concerns with repository abstractions and authority-based locking.
For deeper understanding of related data structures such as BlockState or Envelope, and cryptographic components like GoshBLS, refer to associated modules and topics like block flow trace and BLS Signature Scheme.