Skip to content

Commit

Permalink
feat: added devnet preconf support
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Oct 25, 2024
1 parent ed30e67 commit 4f02c6e
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 20 deletions.
19 changes: 18 additions & 1 deletion bolt-cli/src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum Cmd {
Pubkeys(PubkeysCommand),

/// Send a preconfirmation request to a Bolt proposer.
Send(SendCommand),
Send(Box<SendCommand>),
}

impl Cmd {
Expand Down Expand Up @@ -100,6 +100,23 @@ pub struct SendCommand {
/// If set, the transaction will be blob-carrying (type 3)
#[clap(long, env = "BLOB", default_value = "false")]
pub blob: bool,

/// If set, the transaction will target the devnet environment.
/// This is only used in Kurtosis for internal testing purposes
#[clap(long, hide = true, env = "DEVNET", default_value = "false")]
pub devnet: bool,

/// The URL of the devnet execution client for filling transactions
#[clap(long = "devnet.execution_url", hide = true)]
pub devnet_execution_url: Option<Url>,

/// The URL of the devnet beacon node for fetching slot numbers
#[clap(long = "devnet.beacon_url", hide = true)]
pub devnet_beacon_url: Option<Url>,

/// The URL of the devnet sidecar for sending transactions
#[clap(long = "devnet.sidecar_url", hide = true)]
pub devnet_sidecar_url: Option<Url>,
}

/// The action to perform.
Expand Down
61 changes: 57 additions & 4 deletions bolt-cli/src/commands/send.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use alloy::{
rpc::types::TransactionRequest,
signers::{local::PrivateKeySigner, Signer},
};
use eyre::{bail, Context, Result};
use eyre::{bail, Context, ContextCompat, Result};
use rand::Rng;
use reqwest::Url;
use serde::{Deserialize, Serialize};
Expand All @@ -23,8 +23,17 @@ impl SendCommand {
/// Run the `send` command.
pub async fn run(self) -> Result<()> {
let wallet: PrivateKeySigner = self.private_key.parse().wrap_err("invalid private key")?;
let transaction_signer = EthereumWallet::from(wallet.clone());

if self.devnet {
self.send_devnet_transaction(&wallet).await
} else {
self.send_transaction(&wallet).await
}
}

/// Send a transaction.
async fn send_transaction(self, wallet: &PrivateKeySigner) -> Result<()> {
let transaction_signer = EthereumWallet::from(wallet.clone());
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(transaction_signer)
Expand All @@ -36,7 +45,7 @@ impl SendCommand {
// Note: it's possible for users to override the target sidecar URL
// for testing and development purposes. In most cases, the sidecar will
// reject a request for a slot that it is not responsible for.
let target_url = if let Some(sidecar_url) = self.override_bolt_sidecar_url {
let target_url = if let Some(sidecar_url) = &self.override_bolt_sidecar_url {
// If using the override URL, we don't need to fetch the active proposers only.
// we will set the next slot as the target slot.
sidecar_url.clone()
Expand Down Expand Up @@ -72,13 +81,57 @@ impl SendCommand {
vec![tx_hash],
target_slot,
target_url.clone(),
&wallet,
wallet,
)
.await?;
}

Ok(())
}

/// Send a transaction on the Kurtosis devnet.
async fn send_devnet_transaction(self, wallet: &PrivateKeySigner) -> Result<()> {
let transaction_signer = EthereumWallet::from(wallet.clone());
let el_url = self.devnet_execution_url.clone().wrap_err("missing devnet execution URL")?;
let cl_url = self.devnet_beacon_url.clone().wrap_err("missing devnet beacon URL")?;
let sidecar_url = self.devnet_sidecar_url.clone().wrap_err("missing devnet sidecar URL")?;

let provider = ProviderBuilder::new()
.with_recommended_fillers()
.wallet(transaction_signer)
.on_http(el_url);

// Fetch the current slot from the devnet beacon node
let slot = request_current_slot_number(&cl_url).await?;

// Send the transaction to the devnet sidecar
for _ in 0..self.count {
let req = create_tx_request(wallet.address(), self.blob);
let raw_tx = match provider.fill(req).await.wrap_err("failed to fill transaction")? {
SendableTx::Builder(_) => bail!("expected a raw transaction"),
SendableTx::Envelope(raw) => raw.encoded_2718(),
};
let tx_hash = B256::from(keccak256(&raw_tx));

send_rpc_request(
vec![hex::encode(&raw_tx)],
vec![tx_hash],
slot + 2,
sidecar_url.clone(),
wallet,
)
.await?;
}

Ok(())
}
}

async fn request_current_slot_number(beacon_url: &Url) -> Result<u64> {
let res = reqwest::get(beacon_url.join("eth/v1/beacon/headers/head")?).await?;
let res = res.json::<Value>().await?;
let slot = res.pointer("/header/message/slot").wrap_err("missing slot")?;
slot.as_u64().wrap_err("slot is not a number")
}

fn create_tx_request(to: Address, with_blob: bool) -> TransactionRequest {
Expand Down
30 changes: 15 additions & 15 deletions justfile
Original file line number Diff line number Diff line change
Expand Up @@ -124,24 +124,24 @@ grafana:

# manually send a preconfirmation to the bolt devnet
send-preconf count='1':
cd bolt-kurtosis-client && RUST_LOG=info cargo run -- \
--provider-url $(kurtosis port print bolt-devnet el-1-geth-lighthouse rpc) \
--beacon-client-url $(kurtosis port print bolt-devnet cl-1-lighthouse-geth http) \
--bolt-sidecar-url http://$(kurtosis port print bolt-devnet bolt-sidecar-1-lighthouse-geth api) \
--private-key 53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710 \
--slot head \
--count {{count}}
cd bolt-cli && RUST_LOG=info cargo run -- \
--devnet \
--devnet.execution_url $(kurtosis port print bolt-devnet el-1-geth-lighthouse rpc) \
--devnet.beacon_url $(kurtosis port print bolt-devnet cl-1-lighthouse-geth http) \
--devnet.sidecar_url http://$(kurtosis port print bolt-devnet bolt-sidecar-1-lighthouse-geth api) \
--private_key 53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710 \
--count {{count}}

# manually send a blob preconfirmation to the bolt devnet
send-blob-preconf count='1':
cd bolt-kurtosis-client && RUST_LOG=info cargo run -- \
--provider-url $(kurtosis port print bolt-devnet el-1-geth-lighthouse rpc) \
--beacon-client-url $(kurtosis port print bolt-devnet cl-1-lighthouse-geth http) \
--bolt-sidecar-url http://$(kurtosis port print bolt-devnet bolt-sidecar-1-lighthouse-geth api) \
--private-key 53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710 \
--slot head \
--blob \
--count {{count}} \
cd bolt-cli && RUST_LOG=info cargo run -- \
--devnet \
--devnet.execution_url $(kurtosis port print bolt-devnet el-1-geth-lighthouse rpc) \
--devnet.beacon_url $(kurtosis port print bolt-devnet cl-1-lighthouse-geth http) \
--devnet.sidecar_url http://$(kurtosis port print bolt-devnet bolt-sidecar-1-lighthouse-geth api) \
--private_key 53321db7c1e331d93a11a41d16f004d7ff63972ec8ec7c25db329728ceeb1710 \
--blob \
--count {{count}}

# build all the docker images locally
build-images:
Expand Down

0 comments on commit 4f02c6e

Please sign in to comment.