ckb_chain/
chain_controller.rs1#![allow(missing_docs)]
3#![allow(elided_named_lifetimes)]
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 if Request::call(&self.process_block_sender, lonely_block).is_none() {
63 error!("Chain service has gone")
64 }
65 }
66
67 pub fn blocking_process_block(&self, block: Arc<BlockView>) -> VerifyResult {
69 self.blocking_process_block_internal(block, None)
70 }
71
72 pub fn blocking_process_block_with_switch(
74 &self,
75 block: Arc<BlockView>,
76 switch: Switch,
77 ) -> VerifyResult {
78 self.blocking_process_block_internal(block, Some(switch))
79 }
80
81 fn blocking_process_block_internal(
82 &self,
83 block: Arc<BlockView>,
84 switch: Option<Switch>,
85 ) -> VerifyResult {
86 let (verify_result_tx, verify_result_rx) = ckb_channel::oneshot::channel::<VerifyResult>();
87
88 let verify_callback = {
89 move |result: VerifyResult| {
90 if let Err(err) = verify_result_tx.send(result) {
91 error!(
92 "blocking send verify_result failed: {}, this shouldn't happen",
93 err
94 )
95 }
96 }
97 };
98
99 let lonely_block = LonelyBlock {
100 block,
101 switch,
102 verify_callback: Some(Box::new(verify_callback)),
103 };
104
105 self.asynchronous_process_lonely_block(lonely_block);
106 verify_result_rx.recv().unwrap_or_else(|err| {
107 Err(InternalErrorKind::System
108 .other(format!("blocking recv verify_result failed: {}", err))
109 .into())
110 })
111 }
112
113 pub fn truncate(&self, target_tip_hash: Byte32) -> Result<(), Error> {
117 Request::call(&self.truncate_sender, target_tip_hash).unwrap_or_else(|| {
118 Err(InternalErrorKind::System
119 .other("Chain service has gone")
120 .into())
121 })
122 }
123
124 pub fn get_orphan_block(&self, store: &ChainDB, hash: &Byte32) -> Option<Arc<BlockView>> {
126 self.orphan_block_broker.get_block(store, hash)
127 }
128
129 pub fn orphan_blocks_len(&self) -> usize {
131 self.orphan_block_broker.len()
132 }
133}