ckb-sync 0.116.1

The ckb sync/relayer protocols implementation
Documentation
use crate::SyncShared;
use ckb_chain::chain::{ChainController, ChainService};
use ckb_dao::DaoCalculator;
use ckb_reward_calculator::RewardCalculator;
use ckb_shared::{Shared, SharedBuilder, Snapshot};
use ckb_store::ChainStore;
use ckb_test_chain_utils::{always_success_cellbase, always_success_consensus};
use ckb_types::prelude::*;
use ckb_types::{
    core::{cell::resolve_transaction, BlockBuilder, BlockNumber, TransactionView},
    packed::Byte32,
};
use ckb_verification_traits::Switch;
use std::collections::HashSet;
use std::sync::Arc;

pub fn build_chain(tip: BlockNumber) -> (SyncShared, ChainController) {
    let (shared, mut pack) = SharedBuilder::with_temp_db()
        .consensus(always_success_consensus())
        .build()
        .unwrap();
    let chain_controller = {
        let chain_service = ChainService::new(shared.clone(), pack.take_proposal_table());
        chain_service.start::<&str>(None)
    };
    generate_blocks(&shared, &chain_controller, tip);
    let sync_shared = SyncShared::new(shared, Default::default(), pack.take_relay_tx_receiver());
    (sync_shared, chain_controller)
}

pub fn generate_blocks(
    shared: &Shared,
    chain_controller: &ChainController,
    target_tip: BlockNumber,
) {
    let snapshot = shared.snapshot();
    let parent_number = snapshot.tip_number();
    let mut parent_hash = snapshot.tip_header().hash();
    for _ in parent_number..target_tip {
        let block = inherit_block(shared, &parent_hash).build();
        parent_hash = block.header().hash();
        chain_controller
            .internal_process_block(Arc::new(block), Switch::DISABLE_ALL)
            .expect("processing block should be ok");
    }
}

pub fn inherit_block(shared: &Shared, parent_hash: &Byte32) -> BlockBuilder {
    let snapshot = shared.snapshot();
    let parent = snapshot.get_block(parent_hash).unwrap();
    let parent_number = parent.header().number();
    let epoch = snapshot
        .consensus()
        .next_epoch_ext(&parent.header(), &snapshot.borrow_as_data_loader())
        .unwrap()
        .epoch();
    let cellbase = inherit_cellbase(&snapshot, parent_number);
    let dao = {
        let resolved_cellbase = resolve_transaction(
            cellbase.clone(),
            &mut HashSet::new(),
            snapshot.as_ref(),
            snapshot.as_ref(),
        )
        .unwrap();
        let data_loader = snapshot.borrow_as_data_loader();
        DaoCalculator::new(shared.consensus(), &data_loader)
            .dao_field([resolved_cellbase].iter(), &parent.header())
            .unwrap()
    };

    let chain_root = shared
        .snapshot()
        .chain_root_mmr(parent_number)
        .get_root()
        .expect("chain root_mmr");
    let bytes = chain_root.calc_mmr_hash().as_bytes().pack();

    BlockBuilder::default()
        .parent_hash(parent_hash.to_owned())
        .number((parent.header().number() + 1).pack())
        .timestamp((parent.header().timestamp() + 1).pack())
        .epoch(epoch.number_with_fraction(parent_number + 1).pack())
        .compact_target(epoch.compact_target().pack())
        .dao(dao)
        .transaction(cellbase)
        .extension(Some(bytes))
}

pub fn inherit_cellbase(snapshot: &Snapshot, parent_number: BlockNumber) -> TransactionView {
    let parent_header = {
        let parent_hash = snapshot
            .get_block_hash(parent_number)
            .expect("parent exist");
        snapshot
            .get_block_header(&parent_hash)
            .expect("parent exist")
    };
    let (_, reward) = RewardCalculator::new(snapshot.consensus(), snapshot)
        .block_reward_to_finalize(&parent_header)
        .unwrap();
    always_success_cellbase(parent_number + 1, reward.total, snapshot.consensus())
}