1use crate::{env::SimEnv, BuiltBlock, SharedSimEnv, SimCache, SimDb};
2use signet_types::constants::SignetSystemConstants;
3use tokio::select;
4use tracing::{debug, info_span, trace, Instrument};
5use trevm::{
6 helpers::Ctx,
7 revm::{inspector::NoOpInspector, DatabaseRef, Inspector},
8 Block, Cfg,
9};
10
11#[derive(Debug)]
13pub struct BlockBuild<Db, Insp = NoOpInspector> {
14 env: SharedSimEnv<Db, Insp>,
16
17 block: BuiltBlock,
19
20 finish_by: std::time::Instant,
22
23 max_gas: u64,
25}
26
27impl<Db, Insp> BlockBuild<Db, Insp>
28where
29 Db: DatabaseRef + Send + Sync + 'static,
30 Insp: Inspector<Ctx<SimDb<Db>>> + Default + Sync + 'static,
31{
32 #[allow(clippy::too_many_arguments)] pub fn new<C, B>(
35 db: Db,
36 constants: SignetSystemConstants,
37 cfg: C,
38 block: B,
39 finish_by: std::time::Instant,
40 concurrency_limit: usize,
41 sim_items: SimCache,
42 max_gas: u64,
43 ) -> Self
44 where
45 C: Cfg,
46 B: Block,
47 {
48 let env = SimEnv::<Db, Insp>::new(
49 db,
50 constants,
51 cfg,
52 block,
53 finish_by,
54 concurrency_limit,
55 sim_items,
56 );
57 let finish_by = env.finish_by();
58 let number = env.block().number;
59 Self { env: env.into(), block: BuiltBlock::new(number), finish_by, max_gas }
60 }
61
62 async fn round(&mut self) {
64 let gas_allowed = self.max_gas - self.block.gas_used();
65
66 if let Some(simulated) = self.env.sim_round(gas_allowed).await {
67 tracing::debug!(score = %simulated.score, gas_used = simulated.gas_used, "Adding item to block");
68 self.block.ingest(simulated);
69 }
70 }
71
72 pub async fn build(mut self) -> BuiltBlock {
74 let mut i = 1;
75 loop {
77 let span = info_span!("build", round = i);
78 let finish_by = self.finish_by.into();
79 let fut = self.round().instrument(span);
80
81 select! {
82 _ = tokio::time::sleep_until(finish_by) => {
83 debug!("Deadline reached, stopping sim loop");
84 break;
85 },
86 _ = fut => {
87 i+= 1;
88 let remaining = self.env.sim_items().len();
89 trace!(%remaining, round = i, "Round completed");
90 if remaining == 0 {
91 debug!("No more items to simulate, stopping sim loop");
92 break;
93 }
94 }
95 }
96 }
97
98 debug!(rounds = i, transactions = self.block.transactions.len(), "Building completed",);
99
100 self.block
101 }
102}
103
104#[cfg(test)]
105mod test {
106 use std::future::Future;
107
108 use super::*;
109
110 fn _build_fut_is_send<Db, Insp>(b: BlockBuild<Db, Insp>)
113 where
114 Db: DatabaseRef + Send + Sync + 'static,
115 Insp: Inspector<Ctx<SimDb<Db>>> + Default + Sync + 'static,
116 {
117 let _: Box<dyn Future<Output = BuiltBlock> + Send> = Box::new(b.build());
118 }
119}