Skip to content

fix: update builder loop to wake up at target block time #23

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ const QUINCEY_URL: &str = "QUINCEY_URL";
const BUILDER_PORT: &str = "BUILDER_PORT";
const SEQUENCER_KEY: &str = "SEQUENCER_KEY"; // empty (to use Quincey) OR AWS key ID (to use AWS signer) OR raw private key (to use local signer)
const BUILDER_KEY: &str = "BUILDER_KEY"; // AWS key ID (to use AWS signer) OR raw private key (to use local signer)
const INCOMING_TRANSACTIONS_BUFFER: &str = "INCOMING_TRANSACTIONS_BUFFER";
const BLOCK_CONFIRMATION_BUFFER: &str = "BLOCK_CONFIRMATION_BUFFER";
const CHAIN_OFFSET: &str = "CHAIN_OFFSET";
const TARGET_SLOT_TIME: &str = "TARGET_SLOT_TIME";
const BUILDER_REWARDS_ADDRESS: &str = "BUILDER_REWARDS_ADDRESS";
const ROLLUP_BLOCK_GAS_LIMIT: &str = "ROLLUP_BLOCK_GAS_LIMIT";
const TX_POOL_URL: &str = "TX_POOL_URL";
Expand Down Expand Up @@ -57,10 +58,12 @@ pub struct BuilderConfig {
pub sequencer_key: Option<String>,
/// Key to access Builder transaction submission wallet - AWS Key ID _OR_ local private key.
pub builder_key: String,
/// Buffer in seconds that Builder will wait & accept incoming transactions before bundling them and submitting as a block.
pub incoming_transactions_buffer: u64,
/// Buffer in seconds in which the `submitBlock` transaction must confirm on the Host chain.
pub block_confirmation_buffer: u64,
/// The offset between Unix time and the chain's block times. For Holesky, this is 0; for Ethereum, 11.
pub chain_offset: u64,
/// The slot time at which the Builder should begin building a block. 0 to begin at the very start of the slot; 6 to begin in the middle; etc.
pub target_slot_time: u64,
/// Address on Rollup to which Builder will receive user transaction fees.
pub builder_rewards_address: Address,
/// Gas limit for RU block.
Expand Down Expand Up @@ -147,8 +150,9 @@ impl BuilderConfig {
builder_port: load_u16(BUILDER_PORT)?,
sequencer_key: load_string_option(SEQUENCER_KEY),
builder_key: load_string(BUILDER_KEY)?,
incoming_transactions_buffer: load_u64(INCOMING_TRANSACTIONS_BUFFER)?,
block_confirmation_buffer: load_u64(BLOCK_CONFIRMATION_BUFFER)?,
chain_offset: load_u64(CHAIN_OFFSET)?,
target_slot_time: load_u64(TARGET_SLOT_TIME)?,
builder_rewards_address: load_address(BUILDER_REWARDS_ADDRESS)?,
rollup_block_gas_limit: load_u64(ROLLUP_BLOCK_GAS_LIMIT)?,
tx_pool_url: load_url(TX_POOL_URL)?,
Expand Down
24 changes: 20 additions & 4 deletions src/tasks/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use alloy::{
};
use alloy_primitives::{keccak256, Bytes, B256};
use alloy_rlp::Buf;
use std::time::{SystemTime, UNIX_EPOCH};
use std::{sync::OnceLock, time::Duration};
use tokio::{sync::mpsc, task::JoinHandle};
use tracing::Instrument;
Expand All @@ -14,6 +15,9 @@ use super::oauth::Authenticator;
use super::tx_poller::TxPoller;
use crate::config::BuilderConfig;

/// Ethereum's slot time in seconds.
pub const ETHEREUM_SLOT_TIME: u64 = 12;

#[derive(Debug, Default, Clone)]
/// A block in progress.
pub struct InProgressBlock {
Expand Down Expand Up @@ -108,7 +112,6 @@ impl InProgressBlock {

/// BlockBuilder is a task that periodically builds a block then sends it for signing and submission.
pub struct BlockBuilder {
pub incoming_transactions_buffer: u64,
pub config: BuilderConfig,
pub tx_poller: TxPoller,
pub bundle_poller: BundlePoller,
Expand All @@ -119,7 +122,6 @@ impl BlockBuilder {
pub fn new(config: &BuilderConfig, authenticator: Authenticator) -> Self {
Self {
config: config.clone(),
incoming_transactions_buffer: config.incoming_transactions_buffer,
tx_poller: TxPoller::new(config),
bundle_poller: BundlePoller::new(config, authenticator),
}
Expand Down Expand Up @@ -155,15 +157,27 @@ impl BlockBuilder {
self.bundle_poller.evict();
}

// calculate the duration in seconds until the beginning of the next block slot.
fn secs_to_next_slot(&mut self) -> u64 {
let curr_timestamp: u64 = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
let current_slot_time = (curr_timestamp - self.config.chain_offset) % ETHEREUM_SLOT_TIME;
(ETHEREUM_SLOT_TIME - current_slot_time) % ETHEREUM_SLOT_TIME
}

// add a buffer to the beginning of the block slot.
fn secs_to_next_target(&mut self) -> u64 {
self.secs_to_next_slot() + self.config.target_slot_time
}

/// Spawn the block builder task, returning the inbound channel to it, and
/// a handle to the running task.
pub fn spawn(mut self, outbound: mpsc::UnboundedSender<InProgressBlock>) -> JoinHandle<()> {
tokio::spawn(
async move {
loop {
// sleep the buffer time
tokio::time::sleep(Duration::from_secs(self.incoming_transactions_buffer))
.await;
tokio::time::sleep(Duration::from_secs(self.secs_to_next_target())).await;
tracing::trace!("beginning block build cycle");

// Build a block
let mut in_progress = InProgressBlock::default();
Expand All @@ -178,6 +192,8 @@ impl BlockBuilder {
tracing::debug!("downstream task gone");
break;
}
} else {
tracing::debug!("no transactions, skipping block submission");
}
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/tasks/oauth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,9 @@ mod tests {
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
incoming_transactions_buffer: 1,
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000,
tx_pool_url: "http://localhost:9000/".into(),
Expand Down
3 changes: 2 additions & 1 deletion tests/bundle_poller_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ mod tests {
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
incoming_transactions_buffer: 1,
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000,
tx_pool_url: "http://localhost:9000/".into(),
Expand Down
3 changes: 2 additions & 1 deletion tests/tx_poller_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ mod tests {
builder_port: 8080,
sequencer_key: None,
builder_key: "0000000000000000000000000000000000000000000000000000000000000000".into(),
incoming_transactions_buffer: 1,
block_confirmation_buffer: 1,
chain_offset: 0,
target_slot_time: 1,
builder_rewards_address: Address::default(),
rollup_block_gas_limit: 100_000,
tx_pool_url: "http://localhost:9000/".into(),
Expand Down
Loading