ab_client_block_authoring/
beacon_chain.rs

1use crate::{BlockProducer, ClaimedSlot};
2use ab_client_api::{BlockOrigin, ChainInfo};
3use ab_client_block_builder::BlockBuilder;
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 block_builder_result = match self
43            .block_builder
44            .build(
45                parent_block_root,
46                best_header,
47                &best_block_details,
48                &claimed_slot.consensus_info,
49                &claimed_slot.checkpoints,
50                seal_block,
51            )
52            .await
53        {
54            Ok(block_builder_result) => block_builder_result,
55            Err(error) => {
56                error!(%slot, %parent_block_root, %error, "Failed to build a block");
57                return;
58            }
59        };
60
61        let header = block_builder_result.block.header().header();
62        info!(
63            slot = %header.consensus_info.slot,
64            number = %header.prefix.number,
65            root = %&*header.root(),
66            pre_seal_hash = %header.pre_seal_hash(),
67            "🔖 Built new block",
68        );
69
70        let block_import_fut = match self.block_import.import(
71            block_builder_result.block,
72            BlockOrigin::LocalBlockBuilder {
73                block_details: block_builder_result.block_details,
74            },
75        ) {
76            Ok(block_import_fut) => block_import_fut,
77            Err(error) => {
78                error!(
79                    best_root = %*best_header.root(),
80                    %error,
81                    "Failed to queue a newly produced block for import"
82                );
83                return;
84            }
85        };
86
87        match block_import_fut.await {
88            Ok(()) => {
89                // Nothing else to do
90            }
91            Err(error) => {
92                error!(
93                    best_root = %*best_header.root(),
94                    %error,
95                    "Failed to import a newly produced block"
96                );
97            }
98        }
99    }
100}
101
102impl<BB, BI, CI> BeaconChainBlockProducer<BB, BI, CI>
103where
104    BB: BlockBuilder<OwnedBeaconChainBlock>,
105    BI: BlockImport<OwnedBeaconChainBlock>,
106    CI: ChainInfo<OwnedBeaconChainBlock>,
107{
108    /// Create a new instance
109    pub fn new(block_builder: BB, block_import: BI, chain_info: CI) -> Self {
110        Self {
111            block_builder,
112            block_import,
113            chain_info,
114        }
115    }
116}