ckb_chain/
chain_controller.rs1#![allow(missing_docs)]
3#![allow(mismatched_lifetime_syntaxes)]
4
5use crate::utils::orphan_block_pool::OrphanBlockPool;
6use crate::{LonelyBlock, ProcessBlockRequest, RemoteBlock, TruncateRequest, VerifyResult};
7use ckb_channel::{Request, Sender};
8use ckb_error::{Error, InternalErrorKind};
9use ckb_logger::{self, error};
10use ckb_store::ChainDB;
11use ckb_types::{core::BlockView, packed::Byte32};
12use ckb_verification_traits::Switch;
13use std::sync::Arc;
14use std::sync::atomic::AtomicBool;
15
16#[cfg_attr(feature = "mock", faux::create)]
22#[derive(Clone)]
23pub struct ChainController {
24 process_block_sender: Sender<ProcessBlockRequest>,
25 truncate_sender: Sender<TruncateRequest>,
26 orphan_block_broker: Arc<OrphanBlockPool>,
27
28 is_verifying_unverified_blocks_on_startup: Arc<AtomicBool>,
29}
30
31#[cfg_attr(feature = "mock", faux::methods)]
32impl ChainController {
33 pub(crate) fn new(
34 process_block_sender: Sender<ProcessBlockRequest>,
35 truncate_sender: Sender<TruncateRequest>,
36 orphan_block_broker: Arc<OrphanBlockPool>,
37 is_verifying_unverified_blocks_on_startup: Arc<AtomicBool>,
38 ) -> Self {
39 ChainController {
40 process_block_sender,
41 truncate_sender,
42 orphan_block_broker,
43 is_verifying_unverified_blocks_on_startup,
44 }
45 }
46
47 pub fn is_verifying_unverified_blocks_on_startup(&self) -> bool {
48 self.is_verifying_unverified_blocks_on_startup
49 .load(std::sync::atomic::Ordering::Acquire)
50 }
51
52 pub fn asynchronous_process_remote_block(&self, remote_block: RemoteBlock) {
53 let lonely_block = LonelyBlock {
54 block: remote_block.block,
55 verify_callback: Some(remote_block.verify_callback),
56 switch: None,
57 };
58 self.asynchronous_process_lonely_block(lonely_block);
59 }
60
61 pub fn asynchronous_process_lonely_block(&self, lonely_block: LonelyBlock) {
62 Request::call_without_response(&self.process_block_sender, lonely_block);
63 }
64
65 pub fn blocking_process_block(&self, block: Arc<BlockView>) -> VerifyResult {
67 self.blocking_process_block_internal(block, None)
68 }
69
70 pub fn blocking_process_block_with_switch(
72 &self,
73 block: Arc<BlockView>,
74 switch: Switch,
75 ) -> VerifyResult {
76 self.blocking_process_block_internal(block, Some(switch))
77 }
78
79 fn blocking_process_block_internal(
80 &self,
81 block: Arc<BlockView>,
82 switch: Option<Switch>,
83 ) -> VerifyResult {
84 let (verify_result_tx, verify_result_rx) = ckb_channel::oneshot::channel::<VerifyResult>();
85
86 let verify_callback = {
87 move |result: VerifyResult| {
88 if let Err(err) = verify_result_tx.send(result) {
89 error!(
90 "blocking send verify_result failed: {}, this shouldn't happen",
91 err
92 )
93 }
94 }
95 };
96
97 let lonely_block = LonelyBlock {
98 block,
99 switch,
100 verify_callback: Some(Box::new(verify_callback)),
101 };
102
103 self.asynchronous_process_lonely_block(lonely_block);
104 verify_result_rx.recv().unwrap_or_else(|err| {
105 Err(InternalErrorKind::System
106 .other(format!("blocking recv verify_result failed: {}", err))
107 .into())
108 })
109 }
110
111 pub fn truncate(&self, target_tip_hash: Byte32) -> Result<(), Error> {
115 Request::call(&self.truncate_sender, target_tip_hash).unwrap_or_else(|| {
116 Err(InternalErrorKind::System
117 .other("Chain service has gone")
118 .into())
119 })
120 }
121
122 pub fn get_orphan_block(&self, store: &ChainDB, hash: &Byte32) -> Option<Arc<BlockView>> {
124 self.orphan_block_broker.get_block(store, hash)
125 }
126
127 pub fn orphan_blocks_len(&self) -> usize {
129 self.orphan_block_broker.len()
130 }
131}