pub struct BlockSync<N: Network> { /* private fields */ }Expand description
A struct that keeps track of synchronizing blocks with other nodes.
It generates requests to send to other peers and processes responses to those requests. The struct also keeps track of block locators, which indicate which peers it can fetch blocks from.
§Notes
-
The actual network communication happens in
snarkos_node::Client(for clients and provers) and insnarkos_node_bft::Sync(for validators). -
Validators only sync from other nodes using this struct if they fall behind, e.g., because they experience a network partition. In the common case, validators will generate blocks from the DAG after an anchor certificate has been approved by a supermajority of the committee.
Implementations§
Source§impl<N: Network> BlockSync<N>
impl<N: Network> BlockSync<N>
Sourcepub fn new(
ledger: Arc<dyn LedgerService<N>>,
connection_mode: ConnectionMode,
) -> Self
pub fn new( ledger: Arc<dyn LedgerService<N>>, connection_mode: ConnectionMode, ) -> Self
Initializes a new block sync module.
Sourcepub async fn wait_for_peer_update(&self)
pub async fn wait_for_peer_update(&self)
Blocks until something about a peer changes, or block request has been fully processed (either successfully or unsuccessfully).
Used by the outgoing task.
§Concurrency
Only one task can wait on this at a time.
Sourcepub async fn wait_for_block_responses(&self)
pub async fn wait_for_block_responses(&self)
Blocks until there is a new response to a block request.
Used by the incoming task.
§Concurrency
Only one task can wait on this at a time.
Sourcepub fn is_block_synced(&self) -> bool
pub fn is_block_synced(&self) -> bool
Returns true if the node is synced up to the latest block (within the given tolerance).
Sourcepub async fn wait_for_synced(&self)
pub async fn wait_for_synced(&self)
This futures blocks until the node is synced.
§Concurrency
Multiple tasks can wait on this at the same time safely.
Sourcepub fn wait_for_synced_if_syncing(&self) -> Option<BoxFuture<'_, ()>>
pub fn wait_for_synced_if_syncing(&self) -> Option<BoxFuture<'_, ()>>
Similar as Self::wait_for_synced but returns None if the node is already synced.
Otherwise, it will return a future that behaves like wait_for_synced.
§Concurrency
- This method is atomic, unlike calling
is_syncedandwait_for_syncedsequentially. - Multiple tasks can wait on this at the same time safely.
Sourcepub fn num_blocks_behind(&self) -> Option<u32>
pub fn num_blocks_behind(&self) -> Option<u32>
Returns the number of blocks the node is behind the greatest peer height,
or None if no peers are connected yet.
Sourcepub fn greatest_peer_block_height(&self) -> Option<u32>
pub fn greatest_peer_block_height(&self) -> Option<u32>
Returns the greatest block height of any connected peer.
Sourcepub fn get_sync_height(&self) -> u32
pub fn get_sync_height(&self) -> u32
Returns the current sync height of this node. The sync height is always greater or equal to the ledger height.
Sourcepub fn get_bft_sync_mode(&self) -> Option<BftSyncMode>
pub fn get_bft_sync_mode(&self) -> Option<BftSyncMode>
Returns the BFT sync mode (fast or DAG), or None if no BFT layer is attached.
Sourcepub fn set_bft_sync_mode(&self, mode: BftSyncMode) -> Option<BftSyncMode>
pub fn set_bft_sync_mode(&self, mode: BftSyncMode) -> Option<BftSyncMode>
Sets the BFT sync mode. Should only be called by the BFT layer.
§Returns
The previous BFT sync mode (if any).
Sourcepub fn num_outstanding_block_requests(&self) -> usize
pub fn num_outstanding_block_requests(&self) -> usize
Returns the number of blocks we requested from peers, but have not received yet.
Sourcepub fn num_total_block_requests(&self) -> usize
pub fn num_total_block_requests(&self) -> usize
The total number of block request, including the ones that have been answered already but not processed yet.
pub fn get_peer_heights(&self) -> HashMap<SocketAddr, u32>
pub fn get_block_requests_info(&self) -> BTreeMap<u32, BlockRequestInfo>
Sourcepub fn get_block_requests_summary(&self) -> BlockRequestsSummary
pub fn get_block_requests_summary(&self) -> BlockRequestsSummary
Returns a summary of all in-flight requests.
pub fn get_sync_speed(&self) -> f64
Source§impl<N: Network> BlockSync<N>
impl<N: Network> BlockSync<N>
Sourcepub fn get_block_locators(&self) -> Result<BlockLocators<N>>
pub fn get_block_locators(&self) -> Result<BlockLocators<N>>
Returns the block locators.
Sourcepub fn has_pending_responses(&self) -> bool
pub fn has_pending_responses(&self) -> bool
Returns true if there are pending responses to block requests that need to be processed.
Sourcepub async fn send_block_requests<C: CommunicationService>(
&self,
communication: &C,
sync_peers: &IndexMap<SocketAddr, BlockLocators<N>>,
requests: &[(u32, PrepareSyncRequest<N>)],
) -> bool
pub async fn send_block_requests<C: CommunicationService>( &self, communication: &C, sync_peers: &IndexMap<SocketAddr, BlockLocators<N>>, requests: &[(u32, PrepareSyncRequest<N>)], ) -> bool
Send a batch of block requests.
Sourcepub async fn try_issuing_block_requests<C: CommunicationService>(
&self,
communication: &C,
)
pub async fn try_issuing_block_requests<C: CommunicationService>( &self, communication: &C, )
Handles timeouts, checks if block sync is possible, prepares block requests,
and sends them via the given CommunicationService.
Callers typically call this in a loop after waiting for peer updates, e.g.
timeout(MAX_SYNC_INTERVAL, self.wait_for_peer_update()).
Sourcepub fn insert_block_responses(
&self,
peer_ip: SocketAddr,
blocks: Vec<Block<N>>,
latest_consensus_version: Option<ConsensusVersion>,
) -> Result<(), InsertBlockResponseError<N>>
pub fn insert_block_responses( &self, peer_ip: SocketAddr, blocks: Vec<Block<N>>, latest_consensus_version: Option<ConsensusVersion>, ) -> Result<(), InsertBlockResponseError<N>>
Inserts a new block response from the given peer IP.
Returns an error if the block was malformed, or we already received a different block for this height. This function also removes all block requests from the given peer IP on failure.
Note, that this only queues the response. After this, you most likely want to call Self::try_advancing_block_synchronization.
Sourcepub fn peek_next_block(&self, next_height: u32) -> Option<Block<N>>
pub fn peek_next_block(&self, next_height: u32) -> Option<Block<N>>
Returns the next block for the given next_height if the request is complete,
or None otherwise. This does not remove the block from the responses map.
Sourcepub async fn try_advancing_block_synchronization(&self) -> Result<bool>
pub async fn try_advancing_block_synchronization(&self) -> Result<bool>
Attempts to advance synchronization by processing completed block responses.
Returns true, if new blocks were added to the ledger.
§Usage
This is only called in [Client::try_block_sync] and should not be called concurrently by multiple tasks.
Validators do not call this function, and instead invoke
[snarkos_node_bft::Sync::try_advancing_block_synchronization] which also updates the BFT state.
Source§impl<N: Network> BlockSync<N>
impl<N: Network> BlockSync<N>
Sourcepub fn find_sync_peers(&self) -> Option<(IndexMap<SocketAddr, u32>, u32)>
pub fn find_sync_peers(&self) -> Option<(IndexMap<SocketAddr, u32>, u32)>
Returns the sync peers with their latest heights, and their minimum common ancestor, if the node can sync. This function returns peers that are consistent with each other, and have a block height that is greater than the ledger height of this node.
§Locking
This will read-lock common_ancestors and sync_state, but not at the same time.
Sourcepub fn update_peer_locators(
&self,
peer_ip: SocketAddr,
locators: &BlockLocators<N>,
) -> Result<()>
pub fn update_peer_locators( &self, peer_ip: SocketAddr, locators: &BlockLocators<N>, ) -> Result<()>
Updates the block locators and common ancestors for the given peer IP.
This function does not need to check that the block locators are well-formed,
because that is already done in BlockLocators::new(), as noted in BlockLocators.
This function does not check that the block locators are consistent with the peer’s previous block locators or other peers’ block locators.
Sourcepub fn remove_peer(&self, peer_ip: &SocketAddr)
pub fn remove_peer(&self, peer_ip: &SocketAddr)
TODO (howardwu): Remove the common_ancestor entry. But check that this is safe
(that we don’t rely upon it for safety when we re-connect with the same peer).
Removes the peer from the sync pool, if they exist.
Source§impl<N: Network> BlockSync<N>
impl<N: Network> BlockSync<N>
Sourcepub fn prepare_block_requests(&self) -> Vec<BlockRequestBatch<N>> ⓘ
pub fn prepare_block_requests(&self) -> Vec<BlockRequestBatch<N>> ⓘ
Returns a list of block requests and the sync peers, if the node needs to sync.
You usually want to call remove_timed_out_block_requests before invoking this function.
§Returns
- An empty vector, if there is no work to be done.
- Otherwise, a vector of block request batches, each with a contiguous range of heights.
§Concurrency
This should be called by at most one task at a time.
§Usage
- For validators, the primary spawns exactly one task that periodically calls
bft::Sync::try_issuing_block_requests. There is no possibility of concurrent calls to it. - For clients,
Client::initialize_syncspawn exactly one task that periodically callsClient::try_issuing_block_requestswhich calls this function. - Provers do not call this function.
Sourcepub fn count_request_completed(&self)
pub fn count_request_completed(&self)
Should only be called by validators when they successfully process a block request. (for other nodes this will be automatically called internally)
TODO(kaimast): remove this public function once the sync logic is fully unified BlockSync.
Sourcepub fn set_sync_height(&self, new_height: u32)
pub fn set_sync_height(&self, new_height: u32)
Set the sync height to a the given value.
This is a no-op if new_height is equal or less to the current sync height.
Sourcepub fn remove_block_response(&self, height: u32)
pub fn remove_block_response(&self, height: u32)
Removes the block request and response for the given height
This may only be called after peek_next_block, which checked if the request for the given height was complete.
Precondition: This may only be called after peek_next_block has returned Some,
which has checked if the request for the given height is complete
and there is a block with the given height in the responses map.
Sourcepub fn handle_block_request_timeouts(&self)
pub fn handle_block_request_timeouts(&self)
Removes block requests that have timed out, i.e, requests we sent that did not receive a response in time.
Timed-out requests will be marked as “failed” and re-issued on the next call to prepare_block_requests.
Auto Trait Implementations§
impl<N> !Freeze for BlockSync<N>
impl<N> !RefUnwindSafe for BlockSync<N>
impl<N> Send for BlockSync<N>
impl<N> Sync for BlockSync<N>
impl<N> Unpin for BlockSync<N>
impl<N> UnsafeUnpin for BlockSync<N>
impl<N> !UnwindSafe for BlockSync<N>
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> 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> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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