Skip to content

Commit 55b2193

Browse files
committed
adds slot calculator to block builder
1 parent bf75913 commit 55b2193

File tree

3 files changed

+98
-66
lines changed

3 files changed

+98
-66
lines changed

bin/builder.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ use builder::{
77
},
88
};
99
use signet_sim::SimCache;
10+
use signet_types::SlotCalculator;
11+
use std::sync::Arc;
1012
use tokio::select;
1113

1214
#[tokio::main]
@@ -29,7 +31,6 @@ async fn main() -> eyre::Result<()> {
2931
let metrics = MetricsTask { host_provider: host_provider.clone() };
3032
let (tx_channel, metrics_jh) = metrics.spawn();
3133

32-
let builder = BlockBuilder::new(&config, authenticator.clone(), ru_provider.clone());
3334
let submit = SubmitTask {
3435
authenticator: authenticator.clone(),
3536
host_provider,
@@ -48,12 +49,17 @@ async fn main() -> eyre::Result<()> {
4849

4950
let authenticator_jh = authenticator.spawn();
5051

51-
let (_submit_channel, submit_jh) = submit.spawn();
52+
let (submit_channel, submit_jh) = submit.spawn();
5253

5354
let sim_items = SimCache::new();
54-
let sim_cache_jh = builder.spawn_cache_task(tx_receiver, bundle_receiver, sim_items.clone());
5555

56-
let build_jh = builder.handle_build(constants, ru_provider, sim_items.clone());
56+
let slot_calculator = SlotCalculator::pecorino();
57+
let builder = Arc::new(BlockBuilder::new(&config, ru_provider.clone(), slot_calculator));
58+
59+
let sim_cache_jh =
60+
builder.clone().spawn_cache_handler(tx_receiver, bundle_receiver, sim_items.clone());
61+
62+
let build_jh = builder.clone().spawn_builder_task(constants, sim_items.clone(), submit_channel);
5763

5864
let port = config.builder_port;
5965
let server = serve_builder_with_span(([0, 0, 0, 0], port), span);

src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const OAUTH_CLIENT_SECRET: &str = "OAUTH_CLIENT_SECRET";
4040
const OAUTH_AUTHENTICATE_URL: &str = "OAUTH_AUTHENTICATE_URL";
4141
const OAUTH_TOKEN_URL: &str = "OAUTH_TOKEN_URL";
4242
const CONCURRENCY_LIMIT: &str = "CONCURRENCY_LIMIT";
43+
const START_TIMESTAMP: &str = "START_TIMESTAMP";
4344

4445
/// Configuration for a builder running a specific rollup on a specific host
4546
/// chain.
@@ -97,6 +98,8 @@ pub struct BuilderConfig {
9798
pub oauth_token_refresh_interval: u64,
9899
/// The max number of simultaneous block simulations to run.
99100
pub concurrency_limit: usize,
101+
/// The anchor for slot time and number calculations before adjusting for chain offset.
102+
pub start_timestamp: u64,
100103
}
101104

102105
/// Error loading the configuration.
@@ -193,6 +196,7 @@ impl BuilderConfig {
193196
oauth_token_url: load_string(OAUTH_TOKEN_URL)?,
194197
oauth_token_refresh_interval: load_u64(AUTH_TOKEN_REFRESH_INTERVAL)?,
195198
concurrency_limit: load_u64(CONCURRENCY_LIMIT).map(|v| v as usize).unwrap_or(1000),
199+
start_timestamp: load_u64(START_TIMESTAMP)?,
196200
})
197201
}
198202

src/tasks/block.rs

Lines changed: 84 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
use crate::{
22
config::{BuilderConfig, WalletlessProvider},
3-
tasks::{
4-
bundler::{Bundle, BundlePoller},
5-
oauth::Authenticator,
6-
tx_poller::TxPoller,
7-
},
3+
tasks::bundler::Bundle,
84
};
95
use alloy::{consensus::TxEnvelope, eips::BlockId, providers::Provider};
106
use signet_sim::{BlockBuild, BuiltBlock, SimCache, SimItem};
11-
use signet_types::config::SignetSystemConstants;
7+
use signet_types::{SlotCalculator, config::SignetSystemConstants};
8+
use std::{
9+
sync::Arc,
10+
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
11+
};
1212
use tokio::{
1313
select,
1414
sync::mpsc::{self},
15+
task::JoinHandle,
1516
};
1617
use trevm::{
1718
NoopBlock,
@@ -23,9 +24,6 @@ use trevm::{
2324
},
2425
};
2526

26-
/// Ethereum's slot time in seconds.
27-
pub const ETHEREUM_SLOT_TIME: u64 = 12;
28-
2927
/// Pecorino Chain ID
3028
pub const PECORINO_CHAIN_ID: u64 = 14174;
3129

@@ -37,42 +35,28 @@ pub struct BlockBuilder {
3735
pub config: BuilderConfig,
3836
/// A provider that cannot sign transactions.
3937
pub ru_provider: WalletlessProvider,
40-
/// A poller for fetching transactions.
41-
pub tx_poller: TxPoller,
42-
/// A poller for fetching bundles.
43-
pub bundle_poller: BundlePoller,
38+
/// The slot calculator for waking up and sleeping the builder correctly
39+
pub slot_calculator: SlotCalculator,
4440
}
4541

4642
impl BlockBuilder {
47-
/// Create a new block builder with the given config.
43+
/// Creates a new block builder that builds blocks based on the given provider.
4844
pub fn new(
4945
config: &BuilderConfig,
50-
authenticator: Authenticator,
5146
ru_provider: WalletlessProvider,
47+
slot_calculator: SlotCalculator,
5248
) -> Self {
53-
Self {
54-
config: config.clone(),
55-
ru_provider,
56-
tx_poller: TxPoller::new(config),
57-
bundle_poller: BundlePoller::new(config, authenticator),
58-
}
49+
Self { config: config.clone(), ru_provider, slot_calculator }
5950
}
6051

61-
/// Spawn the block builder task, returning the inbound channel to it, and
62-
/// a handle to the running task.
52+
/// Handles building a single block.
6353
pub async fn handle_build(
6454
&self,
6555
constants: SignetSystemConstants,
66-
ru_provider: WalletlessProvider,
6756
sim_items: SimCache,
57+
finish_by: Instant,
6858
) -> Result<BuiltBlock, mpsc::error::SendError<BuiltBlock>> {
69-
let db = create_db(ru_provider).await.unwrap();
70-
71-
// TODO: add real slot calculator
72-
let finish_by = std::time::Instant::now() + std::time::Duration::from_millis(200);
73-
74-
dbg!(sim_items.read_best(2));
75-
dbg!(sim_items.len());
59+
let db = self.create_db().await.unwrap();
7660

7761
let block_build: BlockBuild<_, NoOpInspector> = BlockBuild::new(
7862
db,
@@ -90,47 +74,85 @@ impl BlockBuilder {
9074
Ok(block)
9175
}
9276

93-
/// Spawns a task that receives transactions and bundles from the pollers and
94-
/// adds them to the shared cache.
95-
pub async fn spawn_cache_task(
96-
&self,
77+
/// Scans the tx and bundle receivers for new items and adds them to the cache.
78+
pub fn spawn_cache_handler(
79+
self: Arc<Self>,
9780
mut tx_receiver: mpsc::UnboundedReceiver<TxEnvelope>,
9881
mut bundle_receiver: mpsc::UnboundedReceiver<Bundle>,
9982
cache: SimCache,
100-
) {
101-
loop {
102-
select! {
103-
maybe_tx = tx_receiver.recv() => {
104-
if let Some(tx) = maybe_tx {
105-
cache.add_item(SimItem::Tx(tx));
83+
) -> JoinHandle<()> {
84+
let jh = tokio::spawn(async move {
85+
loop {
86+
select! {
87+
maybe_tx = tx_receiver.recv() => {
88+
if let Some(tx) = maybe_tx {
89+
cache.add_item(SimItem::Tx(tx));
90+
}
91+
}
92+
maybe_bundle = bundle_receiver.recv() => {
93+
if let Some(bundle) = maybe_bundle {
94+
cache.add_item(SimItem::Bundle(bundle.bundle));
95+
}
10696
}
10797
}
108-
maybe_bundle = bundle_receiver.recv() => {
109-
if let Some(bundle) = maybe_bundle {
110-
cache.add_item(SimItem::Bundle(bundle.bundle));
98+
}
99+
});
100+
jh
101+
}
102+
103+
/// Spawns the block building task.
104+
pub fn spawn_builder_task(
105+
self: Arc<Self>,
106+
constants: SignetSystemConstants,
107+
cache: SimCache,
108+
submit_sender: mpsc::UnboundedSender<BuiltBlock>,
109+
) -> JoinHandle<()> {
110+
let jh = tokio::spawn(async move {
111+
loop {
112+
let sim_cache = cache.clone();
113+
114+
let finish_by = self.calculate_deadline();
115+
tracing::info!("simulating until target slot deadline");
116+
117+
// sleep until next wake period
118+
tracing::info!("starting block build");
119+
match self.handle_build(constants, sim_cache, finish_by).await {
120+
Ok(block) => {
121+
let _ = submit_sender.send(block);
122+
}
123+
Err(e) => {
124+
tracing::error!(err = %e, "failed to send block");
125+
continue;
111126
}
112127
}
113128
}
114-
}
129+
});
130+
jh
115131
}
116-
}
117132

118-
/// Creates an AlloyDB from a rollup provider
119-
async fn create_db(ru_provider: WalletlessProvider) -> Option<WrapAlloyDatabaseAsync> {
120-
let latest = match ru_provider.get_block_number().await {
121-
Ok(block_number) => block_number,
122-
Err(e) => {
123-
tracing::error!(error = %e, "failed to get latest block number");
124-
println!("failed to get latest block number");
125-
// Should this do anything else?
126-
return None;
127-
}
128-
};
129-
let alloy_db = AlloyDB::new(ru_provider.clone(), BlockId::from(latest));
130-
let wrapped_db = WrapDatabaseAsync::new(alloy_db).unwrap_or_else(|| {
131-
panic!("failed to acquire async alloy_db; check which runtime you're using")
132-
});
133-
Some(wrapped_db)
133+
/// Returns the instant at which simulation must stop.
134+
pub fn calculate_deadline(&self) -> Instant {
135+
let now = SystemTime::now();
136+
let unix_seconds = now.duration_since(UNIX_EPOCH).expect("Time went backwards").as_secs();
137+
138+
Instant::now().checked_add(Duration::from_secs(unix_seconds)).unwrap()
139+
}
140+
141+
/// Creates an AlloyDB from a rollup provider
142+
async fn create_db(&self) -> Option<WrapAlloyDatabaseAsync> {
143+
let latest = match self.ru_provider.get_block_number().await {
144+
Ok(block_number) => block_number,
145+
Err(e) => {
146+
tracing::error!(error = %e, "failed to get latest block number");
147+
return None;
148+
}
149+
};
150+
let alloy_db = AlloyDB::new(self.ru_provider.clone(), BlockId::from(latest));
151+
let wrapped_db = WrapDatabaseAsync::new(alloy_db).unwrap_or_else(|| {
152+
panic!("failed to acquire async alloy_db; check which runtime you're using")
153+
});
154+
Some(wrapped_db)
155+
}
134156
}
135157

136158
/// The wrapped alloy database type that is compatible with Db + DatabaseRef

0 commit comments

Comments
 (0)