From 4fc9a71a204b4c880b39445e1d7bfbea28513cd6 Mon Sep 17 00:00:00 2001 From: dylan Date: Fri, 21 Nov 2025 10:17:58 -0700 Subject: [PATCH 01/10] fix: make block query cutoff properly configurable --- Cargo.lock | 1 + Cargo.toml | 7 ++++--- README.md | 5 +++-- src/config.rs | 8 ++++++++ src/tasks/block/sim.rs | 40 ++++++++++++++++++++++++++-------------- src/tasks/env.rs | 4 ++-- src/test_utils.rs | 1 + 7 files changed, 45 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a71fcaba..698161c9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2454,6 +2454,7 @@ dependencies = [ "serde", "serde_json", "signet-block-processor", + "signet-bundle", "signet-constants", "signet-genesis", "signet-sim", diff --git a/Cargo.toml b/Cargo.toml index eacb8061..e78fa0c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,7 @@ signet-constants = { version = "0.16.0-rc.0" } signet-sim = { version = "0.16.0-rc.0" } signet-tx-cache = { version = "0.16.0-rc.0" } signet-types = { version = "0.16.0-rc.0" } +signet-bundle = { version = "0.16.0-rc.0" } signet-zenith = { version = "0.16.0-rc.0" } signet-block-processor = { git = "https://github.com/init4tech/node-components", tag = "v0.16.0-rc.2" } signet-genesis = { git = "https://github.com/init4tech/node-components", tag = "v0.16.0-rc.2" } @@ -64,12 +65,12 @@ alloy-chains = "0.2" # comment / uncomment for local dev # [patch.crates-io] # signet-constants = { path = "../signet-sdk/crates/constants" } +# signet-sim = { path = "../signet-sdk/crates/sim" } +# signet-tx-cache = { path = "../signet-sdk/crates/tx-cache" } # signet-types = { path = "../signet-sdk/crates/types" } # signet-zenith = { path = "../signet-sdk/crates/zenith" } -# signet-sim = { path = "../signet-sdk/crates/sim" } + # signet-evm = { path = "../signet-sdk/crates/evm" } # signet-extract = { path = "../signet-sdk/crates/extract" } # signet-journal = { path = "../signet-sdk/crates/journal" } -# signet-tx-cache = { path = "../signet-sdk/crates/tx-cache" } # signet-bundle = { path = "../signet-sdk/crates/bundle" } -# init4-bin-base = { path = "../bin-base" } diff --git a/README.md b/README.md index ce9053ea..b9d69f25 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Finally, if it's non-empty, the submit task attempts to get a signature for the The Builder is configured via environment variables. The following values are supported for configuration. Key | Required | Description ------------------------------ | -------- | ------------------------------------------------------------------------------ +----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------ `RUST_LOG` | No | The log level of the builder `CHAIN_NAME` | No | The chain name ("pecorino", or the corresponding name) `HOST_RPC_URL` | Yes | RPC endpoint for the host chain @@ -97,7 +97,8 @@ Key | Required | Description `FLASHBOTS_ENDPOINT` | No | Flashbots API to submit blocks to `ROLLUP_BLOCK_GAS_LIMIT` | No | Override for rollup block gas limit `MAX_HOST_GAS_COEFFICIENT` | No | Optional maximum host gas coefficient, as a percentage, to use when building blocks -`BUILDER_KEY` | Yes | AWS KMS key ID _or_ local private key for builder signing +`BUILDER_KEY` | Yes | AWS KMS key ID _or_ local private key for builder signin +`BLOCK_QUERY_CUTOFF_BUFFER` | Yes | Number of milliseconds before the end of the slot to stop querying for new transactions and start the block signing and submission process `AWS_ACCESS_KEY_ID` | No | AWS secret access key ID (required if not using `BUILDER_KEY`) `AWS_SECRET_ACCESS_KEY` | No | AWS secret access key (required if not using `BUILDER_KEY`) `AWS_DEFAULT_REGION` | No | AWS region for the KMS key in question (required if not using `BUILDER_KEY`) diff --git a/src/config.rs b/src/config.rs index b33d9f1e..051078c7 100644 --- a/src/config.rs +++ b/src/config.rs @@ -155,6 +155,14 @@ pub struct BuilderConfig { )] pub max_host_gas_coefficient: Option, + /// Number of seconds before the end of the slot to stop querying for new blocks + #[from_env( + var = "BLOCK_QUERY_CUTOFF_BUFFER", + desc = "Number of milliseconds before the end of the slot to stop querying for new transactions and start the block signing and submission process", + default = 3000 + )] + pub block_query_cutoff_buffer: u64, + /// The slot calculator for the builder. pub slot_calculator: SlotCalculator, diff --git a/src/tasks/block/sim.rs b/src/tasks/block/sim.rs index 97f434b6..21e39cc9 100644 --- a/src/tasks/block/sim.rs +++ b/src/tasks/block/sim.rs @@ -117,7 +117,9 @@ impl SimulatorTask { /// A `Result` containing the built block or an error. #[instrument(skip_all, fields( tx_count = sim_items.len(), - millis_to_deadline = finish_by.duration_since(Instant::now()).as_millis() + millis_to_deadline = finish_by.duration_since(Instant::now()).as_millis(), + host_block_number = sim_env.rollup_block_number(), + rollup_block_number = sim_env.host_block_number(), ))] pub async fn handle_build( &self, @@ -128,9 +130,12 @@ impl SimulatorTask { let concurrency_limit = self.config.concurrency_limit(); let rollup_env = sim_env.sim_rollup_env(self.constants(), self.ru_provider.clone()); - let host_env = sim_env.sim_host_env(self.constants(), self.host_provider.clone()); + let ru_number = rollup_env.block().number; + let host_number = host_env.block().number; + debug!(?ru_number, ?host_number, "starting block simulation"); + let block_build = BlockBuild::new( rollup_env, host_env, @@ -227,24 +232,31 @@ impl SimulatorTask { } } - /// Calculates the deadline for the current block simulation. + /// Calculates the deadline for the current block simulation in milliseconds. /// /// # Returns /// - /// An `Instant` representing the simulation deadline, as calculated by - /// determining the time left in the current slot and adding that to the - /// current timestamp in UNIX seconds. + /// An `Instant` representing the simulation deadline as calculated by determining + /// the milliseconds left in the current slot and adding that to the current + /// timestamp in UNIX seconds. pub fn calculate_deadline(&self) -> Instant { - // Get the current timepoint within the slot. - let timepoint = - self.slot_calculator().current_point_within_slot().expect("host chain has started"); + // Get the current number of milliseconds into the slot. + let timepoint_ms = + self.slot_calculator().current_point_within_slot_ms().expect("host chain has started"); + let slot_duration = Duration::from_secs(self.slot_calculator().slot_duration()).as_millis(); + let elapsed_in_slot = Duration::from_millis(timepoint_ms); + let query_cutoff_buffer = Duration::from_millis(self.config.block_query_cutoff_buffer); - // We have the timepoint in seconds into the slot. To find out what's - // remaining, we need to subtract it from the slot duration - // we also subtract 3 seconds to account for the sequencer stopping signing. - let remaining = (self.slot_calculator().slot_duration() - timepoint).saturating_sub(3); + // To find the remaining slot time, subtract the timepoint from the slot duration. + // Then subtract the block query cutoff buffer from the slot duration to account for + // the sequencer stopping signing. + let remaining = slot_duration + .saturating_sub(elapsed_in_slot.as_millis()) + .saturating_sub(query_cutoff_buffer.as_millis()); - let deadline = Instant::now() + Duration::from_secs(remaining); + // The deadline is then calculated by adding the remaining time from this instant. + // NB: Downcast is okay because u64 will work for 500 million+ years. + let deadline = Instant::now() + Duration::from_millis(remaining as u64); deadline.max(Instant::now()) } } diff --git a/src/tasks/env.rs b/src/tasks/env.rs index 164d8769..c3a96ecd 100644 --- a/src/tasks/env.rs +++ b/src/tasks/env.rs @@ -5,7 +5,7 @@ use crate::{ }; use alloy::{ consensus::Header, - eips::eip1559::BaseFeeParams, + eips::{BlockId, eip1559::BaseFeeParams}, network::Ethereum, primitives::{B256, U256}, providers::{Provider, network::Network}, @@ -64,7 +64,7 @@ impl Environment { /// Create a new [`AlloyDB`] for this environment using the given provider. pub fn alloy_db>(&self, provider: P) -> AlloyDB { - AlloyDB::new(provider, self.prev_header.number.into()) + AlloyDB::new(provider, BlockId::latest()) } } diff --git a/src/test_utils.rs b/src/test_utils.rs index 1384ea38..e35fab13 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -54,6 +54,7 @@ pub fn setup_test_config() -> &'static BuilderConfig { 1740681556, // pecorino start timestamp as sane default 0, 1, ), + block_query_cutoff_buffer: 3000, max_host_gas_coefficient: Some(80), constants: SignetSystemConstants::parmigiana(), } From 1e57e8ac64f15e8fc438101ac2bee3c75c31b231 Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 24 Nov 2025 21:57:33 -0700 Subject: [PATCH 02/10] put alloy db back --- src/tasks/env.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tasks/env.rs b/src/tasks/env.rs index c3a96ecd..7d20340e 100644 --- a/src/tasks/env.rs +++ b/src/tasks/env.rs @@ -64,7 +64,7 @@ impl Environment { /// Create a new [`AlloyDB`] for this environment using the given provider. pub fn alloy_db>(&self, provider: P) -> AlloyDB { - AlloyDB::new(provider, BlockId::latest()) + AlloyDB::new(provider, self.prev_header.number.into()) } } From 6cdc02d83bc94f708c8e6c14c5bda1d92497ba5f Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 24 Nov 2025 22:01:13 -0700 Subject: [PATCH 03/10] fmt --- src/tasks/block/sim.rs | 10 ++-------- src/tasks/env.rs | 2 +- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/tasks/block/sim.rs b/src/tasks/block/sim.rs index 21e39cc9..595821b3 100644 --- a/src/tasks/block/sim.rs +++ b/src/tasks/block/sim.rs @@ -117,9 +117,7 @@ impl SimulatorTask { /// A `Result` containing the built block or an error. #[instrument(skip_all, fields( tx_count = sim_items.len(), - millis_to_deadline = finish_by.duration_since(Instant::now()).as_millis(), - host_block_number = sim_env.rollup_block_number(), - rollup_block_number = sim_env.host_block_number(), + millis_to_deadline = finish_by.duration_since(Instant::now()).as_millis() ))] pub async fn handle_build( &self, @@ -131,11 +129,7 @@ impl SimulatorTask { let rollup_env = sim_env.sim_rollup_env(self.constants(), self.ru_provider.clone()); let host_env = sim_env.sim_host_env(self.constants(), self.host_provider.clone()); - - let ru_number = rollup_env.block().number; - let host_number = host_env.block().number; - debug!(?ru_number, ?host_number, "starting block simulation"); - + let block_build = BlockBuild::new( rollup_env, host_env, diff --git a/src/tasks/env.rs b/src/tasks/env.rs index 7d20340e..13c2d93d 100644 --- a/src/tasks/env.rs +++ b/src/tasks/env.rs @@ -5,7 +5,7 @@ use crate::{ }; use alloy::{ consensus::Header, - eips::{BlockId, eip1559::BaseFeeParams}, + eips::{eip1559::BaseFeeParams}, network::Ethereum, primitives::{B256, U256}, providers::{Provider, network::Network}, From 861e46fe6ec92a6c372c060db4f58fe2e56ce70b Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 24 Nov 2025 22:20:22 -0700 Subject: [PATCH 04/10] fmt --- src/tasks/block/sim.rs | 2 +- src/tasks/env.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tasks/block/sim.rs b/src/tasks/block/sim.rs index 595821b3..6b080251 100644 --- a/src/tasks/block/sim.rs +++ b/src/tasks/block/sim.rs @@ -129,7 +129,7 @@ impl SimulatorTask { let rollup_env = sim_env.sim_rollup_env(self.constants(), self.ru_provider.clone()); let host_env = sim_env.sim_host_env(self.constants(), self.host_provider.clone()); - + let block_build = BlockBuild::new( rollup_env, host_env, diff --git a/src/tasks/env.rs b/src/tasks/env.rs index 13c2d93d..164d8769 100644 --- a/src/tasks/env.rs +++ b/src/tasks/env.rs @@ -5,7 +5,7 @@ use crate::{ }; use alloy::{ consensus::Header, - eips::{eip1559::BaseFeeParams}, + eips::eip1559::BaseFeeParams, network::Ethereum, primitives::{B256, U256}, providers::{Provider, network::Network}, From 23906e4ae5add52e86907a57d79772b4a20438da Mon Sep 17 00:00:00 2001 From: dylan Date: Tue, 25 Nov 2025 19:49:21 -0700 Subject: [PATCH 05/10] refactor: avoid using Duration --- src/tasks/block/sim.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/tasks/block/sim.rs b/src/tasks/block/sim.rs index 6b080251..1674de42 100644 --- a/src/tasks/block/sim.rs +++ b/src/tasks/block/sim.rs @@ -237,20 +237,19 @@ impl SimulatorTask { // Get the current number of milliseconds into the slot. let timepoint_ms = self.slot_calculator().current_point_within_slot_ms().expect("host chain has started"); - let slot_duration = Duration::from_secs(self.slot_calculator().slot_duration()).as_millis(); - let elapsed_in_slot = Duration::from_millis(timepoint_ms); - let query_cutoff_buffer = Duration::from_millis(self.config.block_query_cutoff_buffer); + + let slot_duration = self.slot_calculator().slot_duration() * 1000; // convert to milliseconds + let query_cutoff_buffer = self.config.block_query_cutoff_buffer; // To find the remaining slot time, subtract the timepoint from the slot duration. // Then subtract the block query cutoff buffer from the slot duration to account for // the sequencer stopping signing. - let remaining = slot_duration - .saturating_sub(elapsed_in_slot.as_millis()) - .saturating_sub(query_cutoff_buffer.as_millis()); + let remaining = + slot_duration.saturating_sub(timepoint_ms).saturating_sub(query_cutoff_buffer); // The deadline is then calculated by adding the remaining time from this instant. // NB: Downcast is okay because u64 will work for 500 million+ years. - let deadline = Instant::now() + Duration::from_millis(remaining as u64); + let deadline = Instant::now() + Duration::from_millis(remaining); deadline.max(Instant::now()) } } From 6c4e7a6838fe6d511e3c78a27c3494b6a120b4d6 Mon Sep 17 00:00:00 2001 From: dylan Date: Mon, 8 Dec 2025 20:11:34 -0700 Subject: [PATCH 06/10] cleanup --- src/test_utils.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/test_utils.rs b/src/test_utils.rs index e35fab13..cb9d3e75 100644 --- a/src/test_utils.rs +++ b/src/test_utils.rs @@ -23,7 +23,6 @@ use trevm::revm::{context::BlockEnv, context_interface::block::BlobExcessGasAndP pub fn setup_test_config() -> &'static BuilderConfig { crate::CONFIG.get_or_init(|| { BuilderConfig { - // host_chain_id: signet_constants::pecorino::HOST_CHAIN_ID, host_rpc: "ws://host-rpc.pecorino.signet.sh" .parse::() .map(ProviderConfig::new) From 308f1382a546086a1d05861c224586a957baa40c Mon Sep 17 00:00:00 2001 From: dylan Date: Tue, 9 Dec 2025 15:35:27 -0700 Subject: [PATCH 07/10] deps: update to signet-sdk@0.16.0-rc.0 to align bin-base version --- Cargo.toml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index e78fa0c1..6460cb9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,13 +19,17 @@ path = "bin/builder.rs" [dependencies] init4-bin-base = { version = "0.18.0-rc.0", features = ["perms", "aws"] } +# init4-bin-base = { git = "https://github.com/init4tech/bin-base.git", branch = "main", features = [ +# "perms", +# "aws", +# ] } -signet-constants = { version = "0.16.0-rc.0" } -signet-sim = { version = "0.16.0-rc.0" } -signet-tx-cache = { version = "0.16.0-rc.0" } -signet-types = { version = "0.16.0-rc.0" } -signet-bundle = { version = "0.16.0-rc.0" } -signet-zenith = { version = "0.16.0-rc.0" } +signet-constants = { version = "0.16.0-rc.1" } +signet-sim = { version = "0.16.0-rc.1" } +signet-tx-cache = { version = "0.16.0-rc.1" } +signet-types = { version = "0.16.0-rc.1" } +signet-bundle = { version = "0.16.0-rc.1" } +signet-zenith = { version = "0.16.0-rc.1" } signet-block-processor = { git = "https://github.com/init4tech/node-components", tag = "v0.16.0-rc.2" } signet-genesis = { git = "https://github.com/init4tech/node-components", tag = "v0.16.0-rc.2" } From e0f0a0e84a04a6827b16094798b8abc980da4cde Mon Sep 17 00:00:00 2001 From: dylan Date: Fri, 12 Dec 2025 15:54:50 -0700 Subject: [PATCH 08/10] clippy --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index b727a412..55cc8332 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -37,6 +37,7 @@ use init4_bin_base::utils::from_env::FromEnv; // Anonymous import suppresses warnings about unused imports. use openssl as _; use signet_constants::SignetSystemConstants; +use signet_bundle as _; use std::sync::OnceLock; /// Global static configuration for the Builder binary. From 64992b2b09fd5f2d4ee8a5fd8fcfdc99bdf50a7f Mon Sep 17 00:00:00 2001 From: dylan Date: Fri, 12 Dec 2025 15:56:07 -0700 Subject: [PATCH 09/10] cleanup --- Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6460cb9a..34c0f3ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,10 +19,6 @@ path = "bin/builder.rs" [dependencies] init4-bin-base = { version = "0.18.0-rc.0", features = ["perms", "aws"] } -# init4-bin-base = { git = "https://github.com/init4tech/bin-base.git", branch = "main", features = [ -# "perms", -# "aws", -# ] } signet-constants = { version = "0.16.0-rc.1" } signet-sim = { version = "0.16.0-rc.1" } From 8f22d65eef7cb5b966278da385a605d04c1dbb4a Mon Sep 17 00:00:00 2001 From: dylan Date: Fri, 12 Dec 2025 16:20:08 -0700 Subject: [PATCH 10/10] fmt --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 55cc8332..11667859 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,8 +36,8 @@ pub mod test_utils; use init4_bin_base::utils::from_env::FromEnv; // Anonymous import suppresses warnings about unused imports. use openssl as _; -use signet_constants::SignetSystemConstants; use signet_bundle as _; +use signet_constants::SignetSystemConstants; use std::sync::OnceLock; /// Global static configuration for the Builder binary.