diff --git a/README.md b/README.md index ce9053e..b9d69f2 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 a478828..97ca87c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -155,6 +155,14 @@ pub struct BuilderConfig { )] pub max_host_gas_coefficient: Option, + /// Number of milliseconds before the end of the slot to stop querying for new blocks and start the block signing and submission process. + #[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. Quincey will stop accepting signature requests 2000ms before the end of the slot, so this buffer should be no less than 2000ms to match.", + 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 29f1157..3963dc4 100644 --- a/src/tasks/block/sim.rs +++ b/src/tasks/block/sim.rs @@ -127,7 +127,6 @@ 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 block_build = BlockBuild::new( @@ -226,24 +225,30 @@ 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"); - - // 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); - - let deadline = Instant::now() + Duration::from_secs(remaining); + // 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 = 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(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); deadline.max(Instant::now()) } } diff --git a/src/test_utils.rs b/src/test_utils.rs index 1384ea3..cb9d3e7 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) @@ -54,6 +53,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(), }