Skip to main content

ab_client_block_authoring/
beacon_chain.rs

1use crate::{BlockProducer, ClaimedSlot};
2use ab_client_api::{BlockOrigin, ChainInfo};
3use ab_client_block_builder::{BlockBuilder, BlockBuilderResult};
4use ab_client_block_import::BlockImport;
5use ab_core_primitives::block::header::{BeaconChainHeader, OwnedBlockHeaderSeal};
6use ab_core_primitives::block::owned::{GenericOwnedBlock, OwnedBeaconChainBlock};
7use ab_core_primitives::hashes::Blake3Hash;
8use tracing::{error, info};
9
10/// Beacon chain block producer
11#[derive(Debug)]
12pub struct BeaconChainBlockProducer<BB, BI, CI> {
13    block_builder: BB,
14    block_import: BI,
15    chain_info: CI,
16}
17
18impl<BB, BI, CI> BlockProducer for BeaconChainBlockProducer<BB, BI, CI>
19where
20    BB: BlockBuilder<OwnedBeaconChainBlock>,
21    BI: BlockImport<OwnedBeaconChainBlock>,
22    CI: ChainInfo<OwnedBeaconChainBlock>,
23{
24    async fn produce_block<SealBlock>(
25        &mut self,
26        claimed_slot: ClaimedSlot,
27        best_beacon_chain_header: &BeaconChainHeader<'_>,
28        seal_block: SealBlock,
29    ) where
30        SealBlock: AsyncFnOnce<(Blake3Hash,), Output = Option<OwnedBlockHeaderSeal>, CallOnceFuture: Send>
31            + Send,
32    {
33        let slot = claimed_slot.consensus_info.slot;
34
35        let best_header = best_beacon_chain_header;
36        let parent_block_root = &*best_header.root();
37        let (_, best_block_details) = self
38            .chain_info
39            .header_with_details(parent_block_root)
40            .expect("Best beacon chain block is never missing during block production; qed");
41
42        let BlockBuilderResult {
43            block,
44            block_details,
45            extra: (),
46        } = match self
47            .block_builder
48            .build(
49                parent_block_root,
50                best_header,
51                &best_block_details,
52                &claimed_slot.consensus_info,
53                &claimed_slot.checkpoints,
54                seal_block,
55            )
56            .await
57        {
58            Ok(block_builder_result) => block_builder_result,
59            Err(error) => {
60                error!(%slot, %parent_block_root, %error, "Failed to build a block");
61                return;
62            }
63        };
64
65        let header = block.header().header();
66        info!(
67            slot = %header.consensus_info.slot,
68            number = %header.prefix.number,
69            root = %&*header.root(),
70            pre_seal_hash = %header.pre_seal_hash(),
71            "🔖 Built new block",
72        );
73
74        let block_import_fut = match self
75            .block_import
76            .import(block, BlockOrigin::LocalBlockBuilder { block_details })
77        {
78            Ok(block_import_fut) => block_import_fut,
79            Err(error) => {
80                error!(
81                    best_root = %*best_header.root(),
82                    %error,
83                    "Failed to queue a newly produced block for import"
84                );
85                return;
86            }
87        };
88
89        match block_import_fut.await {
90            Ok(()) => {
91                // Nothing else to do
92            }
93            Err(error) => {
94                error!(
95                    best_root = %*best_header.root(),
96                    %error,
97                    "Failed to import a newly produced block"
98                );
99            }
100        }
101    }
102}
103
104impl<BB, BI, CI> BeaconChainBlockProducer<BB, BI, CI>
105where
106    BB: BlockBuilder<OwnedBeaconChainBlock>,
107    BI: BlockImport<OwnedBeaconChainBlock>,
108    CI: ChainInfo<OwnedBeaconChainBlock>,
109{
110    /// Create a new instance
111    pub fn new(block_builder: BB, block_import: BI, chain_info: CI) -> Self {
112        Self {
113            block_builder,
114            block_import,
115            chain_info,
116        }
117    }
118}