// Request a block from a remote sync peer and attempt to add it to the local blockchain.
Request a block from a remote sync peer and attempt to add it to the local blockchain.
Request a block from a remote sync peer and attempt to add it to the local blockchain .
async fn request_and_add_blocks<B: BlockchainBackend + 'static>(
    shared: &mut BaseNodeStateMachine<B>,
    sync_peers: &mut SyncPeers,
    mut block_nums: Vec<u64>,
) -> Result<(), BlockSyncError>
{
    if block_nums.is_empty() {
        return Ok(());
    }
    let config = shared.config.block_sync_config;
    for attempt in 0..config.max_add_block_retry_attempts {
        let (blocks, sync_peer) = request_blocks(shared, sync_peers, &block_nums).await?;
        if let StateInfo::BlockSync(ref mut info) = shared.info {
            // assuming the numbers are ordered
            info.tip_height = block_nums[block_nums.len() - 1];
        }
        shared.publish_event_info();
        for block in blocks {
            let block_height = block.header.height;
            let block_hash_hex = block.hash().to_hex();
            if let StateInfo::BlockSync(ref mut info) = shared.info {
                info.local_height = block_height;
            }
            shared.publish_event_info();
            info!(
                target: LOG_TARGET,
                "Adding block #{} ({}) to DB.", block_height, block_hash_hex
            );
            trace!(target: LOG_TARGET, "{}", block);
            match async_db::add_block(shared.db.clone(), block.clone()).await {
                Ok(BlockAddResult::Ok) => {
                    info!(
                        target: LOG_TARGET,
                        "Block #{} ({}) successfully added to database", block_height, block_hash_hex
                    );
                    block_nums.remove(0);
                },
                Ok(BlockAddResult::OrphanBlock) => {
                    warn!(
                        target: LOG_TARGET,
                        "Received orphan block #{} ({}) from peer `{}`",
                        block_height,
                        block_hash_hex,
                        sync_peer.node_id
                    );
                    block_nums.remove(0);
                },
                Ok(BlockAddResult::ChainReorg(removed, added)) => {
                    warn!(
                        target: LOG_TARGET,
                        "Block #{} ({}) caused a reorg during block sync. (#removed = {}, #added = {})",
                        block_height,
                        block_hash_hex,
                        removed.len(),
                        added.len()
                    );
                    block_nums.remove(0);
                },
                Ok(BlockAddResult::BlockExists) => {
                    warn!(
                        target: LOG_TARGET,
                        "Block #{} ({}) already exists.", block_height, block_hash_hex
                    );
                    block_nums.remove(0);
                },
                Err(ChainStorageError::InvalidBlock) => {
                    warn!(
                        target: LOG_TARGET,
                        "Invalid block {} received from peer.", block_hash_hex,
                    );
                    debug!(
                        target: LOG_TARGET,
                        "Banning peer {} from local node, because they supplied invalid block", sync_peer
                    );
                    ban_sync_peer(
                        LOG_TARGET,
                        &mut shared.connectivity,
                        sync_peers,
                        &sync_peer,
                        shared.config.sync_peer_config.peer_ban_duration,
                        "Peer supplied an invalid block".to_string(),
                    )
                    .await?;
                    break;
                },
                Err(ChainStorageError::ValidationError { source }) => {
                    warn!(
                        target: LOG_TARGET,
                        "Validation on block {} from peer failed due to: {:?}.", block_hash_hex, source,
                    );
                    debug!(
                        target: LOG_TARGET,
                        "Banning peer {} from local node, because they supplied invalid block", sync_peer
                    );
                    ban_sync_peer(
                        LOG_TARGET,
                        &mut shared.connectivity,
                        sync_peers,
                        &sync_peer,
                        shared.config.sync_peer_config.peer_ban_duration,
                        format!("Peer supplied an invalid block that failed validation: {}", source),
                    )
                    .await?;
                    break;
                },
                Err(ChainStorageError::ProofOfWorkError { source }) => {
                    warn!(
                        target: LOG_TARGET,
                        "Validation on block {} from peer failed due to: {:?}.", block_hash_hex, source,
                    );
                    debug!(
                        target: LOG_TARGET,
                        "Banning peer {} from local node, because they supplied invalid block", sync_peer
                    );
                    ban_sync_peer(
                        LOG_TARGET,
                        &mut shared.connectivity,
                        sync_peers,
                        &sync_peer,
                        shared.config.sync_peer_config.peer_ban_duration,
                        format!("Peer supplied an invalid block that failed validation: {}", source),
                    )
                    .await?;
                    break;
                },
                Err(e) => return Err(e.into()),
            }
        }
        if block_nums.is_empty() {
            return Ok(());
        }
        debug!(target: LOG_TARGET, "Retrying block add. Attempt {}", attempt);
    }
    Err(BlockSyncError::MaxAddBlockAttemptsReached)
}
async fn request_and_add_blocks < B : BlockchainBackend + ' static > ( shared : & mut BaseNodeStateMachine < B > , sync_peers : & mut SyncPeers , mut block_nums : Vec < u64 > , ) -> Result < ( ) , BlockSyncError > { if block_nums . is_empty ( ) { return Ok ( ( ) ) ; } let config = shared . config . block_sync_config ; for attempt in 0 .. config . max_add_block_retry_attempts { let ( blocks , sync_peer ) = request_blocks ( shared , sync_peers , & block_nums ) . await ? ; if let StateInfo :: BlockSync ( ref mut info ) = shared . info { // assuming the numbers are ordered info . tip_height = block_nums [ block_nums . len ( ) - 1 ] ; } shared . publish_event_info ( ) ; for block in blocks { let block_height = block . header . height ; let block_hash_hex = block . hash ( ) . to_hex ( ) ; if let StateInfo :: BlockSync ( ref mut info ) = shared . info { info . local_height = block_height ; } shared . publish_event_info ( ) ; info ! ( target LOG_TARGET " " block_height block_hash_hex ) ; trace ! ( target LOG_TARGET " " block ) ; match async_db :: add_block ( shared . db . clone ( ) , block . clone ( ) ) . await { Ok ( BlockAddResult :: Ok ) => { info ! ( target LOG_TARGET " " block_height block_hash_hex ) ; block_nums . remove ( 0 ) ; } , Ok ( BlockAddResult :: OrphanBlock ) => { warn ! ( target LOG_TARGET " " block_height block_hash_hex sync_peer node_id ) ; block_nums . remove ( 0 ) ; } , Ok ( BlockAddResult :: ChainReorg ( removed , added ) ) => { warn ! ( target LOG_TARGET " " block_height block_hash_hex removed len ( ) added len ( ) ) ; block_nums . remove ( 0 ) ; } , Ok ( BlockAddResult :: BlockExists ) => { warn ! ( target LOG_TARGET " " block_height block_hash_hex ) ; block_nums . remove ( 0 ) ; } , Err ( ChainStorageError :: InvalidBlock ) => { warn ! ( target LOG_TARGET " " block_hash_hex ) ; debug ! ( target LOG_TARGET " " sync_peer ) ; ban_sync_peer ( LOG_TARGET , & mut shared . connectivity , sync_peers , & sync_peer , shared . config . sync_peer_config . peer_ban_duration , " " . to_string ( ) , ) . await ? ; break ; } , Err ( ChainStorageError :: ValidationError { source } ) => { warn ! ( target LOG_TARGET " " block_hash_hex source ) ; debug ! ( target LOG_TARGET " " sync_peer ) ; ban_sync_peer ( LOG_TARGET , & mut shared . connectivity , sync_peers , & sync_peer , shared . config . sync_peer_config . peer_ban_duration , format ! ( " " source ) , ) . await ? ; break ; } , Err ( ChainStorageError :: ProofOfWorkError { source } ) => { warn ! ( target LOG_TARGET " " block_hash_hex source ) ; debug ! ( target LOG_TARGET " " sync_peer ) ; ban_sync_peer ( LOG_TARGET , & mut shared . connectivity , sync_peers , & sync_peer , shared . config . sync_peer_config . peer_ban_duration , format ! ( " " source ) , ) . await ? ; break ; } , Err ( e ) => return Err ( e . into ( ) ) , } } if block_nums . is_empty ( ) { return Ok ( ( ) ) ; } debug ! ( target LOG_TARGET " " attempt ) ; } Err ( BlockSyncError :: MaxAddBlockAttemptsReached ) }
Request a block from a remote sync peer and attempt to add it to the local blockchain.
Request a block from a remote sync peer and attempt to add it to the local blockchain .
shared
&mut BaseNodeStateMachine<B>
sync_peers
&mut SyncPeers
block_nums
Vec<u64>