From 45926c096b290772cdf220adbbf2e58e9d6ce0e3 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 13 Nov 2024 12:46:34 +0100 Subject: [PATCH 1/6] feat(sidecar): add flag to disable consensus checks for testing purposes --- bolt-sidecar/src/config/mod.rs | 6 ++++- bolt-sidecar/src/driver.rs | 39 ++++++++++++++++------------- bolt-sidecar/src/state/consensus.rs | 29 +++++++++++++++------ bolt-sidecar/src/state/execution.rs | 2 +- 4 files changed, 49 insertions(+), 27 deletions(-) diff --git a/bolt-sidecar/src/config/mod.rs b/bolt-sidecar/src/config/mod.rs index f55c00a8..4f54e279 100644 --- a/bolt-sidecar/src/config/mod.rs +++ b/bolt-sidecar/src/config/mod.rs @@ -81,9 +81,13 @@ pub struct Opts { /// then used when registering the operator in the `BoltManager` contract. #[clap(long, env = "BOLT_SIDECAR_COMMITMENT_PRIVATE_KEY")] pub commitment_private_key: EcdsaSecretKeyWrapper, + /// Unsafely disables consensus checks when validating commitments. + /// If enabled, the sidecar will sign every incoming commitment with the first private key + /// available + #[clap(long, env = "BOLT_SIDECAR_UNSAFE_DISABLE_CONSENSUS_CHECKS", default_value_t = false)] + pub unsafe_disable_consensus_checks: bool, /// Operating limits for the sidecar #[clap(flatten)] - #[serde(default)] pub limits: LimitsOpts, /// Chain config for the chain on which the sidecar is running #[clap(flatten)] diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs index 802ba23a..46fd2c52 100644 --- a/bolt-sidecar/src/driver.rs +++ b/bolt-sidecar/src/driver.rs @@ -203,6 +203,7 @@ impl SidecarDriver { beacon_client, opts.chain.commitment_deadline(), opts.chain.enable_unsafe_lookahead, + opts.unsafe_disable_consensus_checks, ); let (payload_requests_tx, payload_requests_rx) = mpsc::channel(16); @@ -274,6 +275,11 @@ impl SidecarDriver { let start = Instant::now(); + // When we'll add more commitment types, we'll need to match on the request type here. + // For now, we only support inclusion requests so the flow is straightforward. + let CommitmentRequest::Inclusion(inclusion_request) = request.clone(); + let target_slot = inclusion_request.slot; + let validator_pubkey = match self.consensus.validate_request(&request) { Ok(pubkey) => pubkey, Err(err) => { @@ -283,6 +289,22 @@ impl SidecarDriver { } }; + let available_pubkeys = self.constraint_signer.available_pubkeys(); + + // Find a public key to sign new constraints with for this slot. + // This can either be the validator pubkey or a delegatee (if one is available). + let signing_pubkey = if self.consensus.unsafe_disable_consensus_checks { + // Take the first one available + available_pubkeys.iter().take(1).next().cloned() + } else { + self.constraints_client.find_signing_key(validator_pubkey, available_pubkeys) + }; + let Some(signing_pubkey) = signing_pubkey else { + error!(%target_slot, "No available public key to sign constraints with"); + let _ = response.send(Err(CommitmentError::Internal)); + return; + }; + if let Err(err) = self.execution.validate_request(&mut request).await { warn!(?err, "Execution: failed to validate request"); ApiMetrics::increment_validation_errors(err.to_tag_str().to_owned()); @@ -290,29 +312,12 @@ impl SidecarDriver { return; } - // When we'll add more commitment types, we'll need to match on the request type here. - // For now, we only support inclusion requests so the flow is straightforward. - let CommitmentRequest::Inclusion(inclusion_request) = request.clone(); - let target_slot = inclusion_request.slot; - info!( target_slot, elapsed = ?start.elapsed(), "Validation against execution state passed" ); - let available_pubkeys = self.constraint_signer.available_pubkeys(); - - // Find a public key to sign new constraints with for this slot. - // This can either be the validator pubkey or a delegatee (if one is available). - let Some(signing_pubkey) = - self.constraints_client.find_signing_key(validator_pubkey, available_pubkeys) - else { - error!(%target_slot, "No available public key to sign constraints with"); - let _ = response.send(Err(CommitmentError::Internal)); - return; - }; - // NOTE: we iterate over the transactions in the request and generate a signed constraint // for each one. This is because the transactions in the commitment request are not supposed // to be treated as a relative-ordering bundle, but a batch with no ordering guarantees. diff --git a/bolt-sidecar/src/state/consensus.rs b/bolt-sidecar/src/state/consensus.rs index 25fcd2ac..7d76d30c 100644 --- a/bolt-sidecar/src/state/consensus.rs +++ b/bolt-sidecar/src/state/consensus.rs @@ -11,7 +11,7 @@ use tracing::debug; use super::CommitmentDeadline; use crate::{ client::BeaconClient, - primitives::{CommitmentRequest, Slot}, + primitives::{CommitmentRequest, InclusionRequest, Slot}, telemetry::ApiMetrics, }; @@ -72,6 +72,11 @@ pub struct ConsensusState { /// It is considered unsafe because it is possible for the next epoch's duties to /// change if there are beacon chain deposits or withdrawals in the current epoch. unsafe_lookahead_enabled: bool, + /// If consensus checks should be disabled when accepting commitments. For testing purposes only. + /// + /// If enabled, the sidecar will sign every incoming commitment with the first private key + /// available. + pub unsafe_disable_consensus_checks: bool, } impl fmt::Debug for ConsensusState { @@ -93,6 +98,7 @@ impl ConsensusState { beacon_api_client: BeaconClient, commitment_deadline_duration: Duration, unsafe_lookahead_enabled: bool, + unsafe_disable_consensus_checks: bool, ) -> Self { ConsensusState { beacon_api_client, @@ -102,6 +108,7 @@ impl ConsensusState { commitment_deadline: CommitmentDeadline::new(0, commitment_deadline_duration), commitment_deadline_duration, unsafe_lookahead_enabled, + unsafe_disable_consensus_checks, } } @@ -116,6 +123,10 @@ impl ConsensusState { &self, request: &CommitmentRequest, ) -> Result { + if self.unsafe_disable_consensus_checks { + return Ok(BlsPublicKey::default()); + } + let CommitmentRequest::Inclusion(req) = request; // Check if the slot is in the current epoch or next epoch (if unsafe lookahead is enabled) @@ -124,8 +135,8 @@ impl ConsensusState { } // If the request is for the next slot, check if it's within the commitment deadline - if req.slot == self.latest_slot + 1 && - self.latest_slot_timestamp + self.commitment_deadline_duration < Instant::now() + if req.slot == self.latest_slot + 1 + && self.latest_slot_timestamp + self.commitment_deadline_duration < Instant::now() { return Err(ConsensusError::DeadlineExceeded); } @@ -209,9 +220,9 @@ impl ConsensusState { /// Returns the furthest slot for which a commitment request is considered valid, whether in /// the current epoch or next epoch (if unsafe lookahead is enabled) fn furthest_slot(&self) -> u64 { - self.epoch.start_slot + - SLOTS_PER_EPOCH + - if self.unsafe_lookahead_enabled { SLOTS_PER_EPOCH } else { 0 } + self.epoch.start_slot + + SLOTS_PER_EPOCH + + if self.unsafe_lookahead_enabled { SLOTS_PER_EPOCH } else { 0 } } } @@ -246,6 +257,7 @@ mod tests { commitment_deadline: CommitmentDeadline::new(0, commitment_deadline_duration), commitment_deadline_duration, unsafe_lookahead_enabled: false, + unsafe_disable_consensus_checks: false, }; // Update the slot to 32 @@ -292,11 +304,12 @@ mod tests { commitment_deadline_duration, // We test for both epochs unsafe_lookahead_enabled: true, + unsafe_disable_consensus_checks: false, }; let epoch = - state.beacon_api_client.get_beacon_header(BlockId::Head).await?.header.message.slot / - SLOTS_PER_EPOCH; + state.beacon_api_client.get_beacon_header(BlockId::Head).await?.header.message.slot + / SLOTS_PER_EPOCH; state.fetch_proposer_duties(epoch).await?; assert_eq!(state.epoch.proposer_duties.len(), SLOTS_PER_EPOCH as usize * 2); diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 00d363d0..5b9df3c1 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -13,7 +13,7 @@ use crate::{ builder::BlockTemplate, common::{calculate_max_basefee, max_transaction_cost, validate_transaction}, config::limits::LimitsOpts, - primitives::{AccountState, CommitmentRequest, SignedConstraints, Slot}, + primitives::{AccountState, CommitmentRequest, InclusionRequest, SignedConstraints, Slot}, telemetry::ApiMetrics, }; From a389904f3f7c9358004aaf00e6dbbe5561567b01 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 13 Nov 2024 13:42:08 +0100 Subject: [PATCH 2/6] refactor(sidecar): work more explicitly with underlying inclusion request type --- bolt-sidecar/src/api/commitments/server.rs | 8 +-- bolt-sidecar/src/driver.rs | 18 +++--- bolt-sidecar/src/primitives/commitment.rs | 24 +++++++- bolt-sidecar/src/state/consensus.rs | 9 +-- bolt-sidecar/src/state/execution.rs | 66 ++++++++++------------ bolt-sidecar/src/test_util.rs | 10 ++-- 6 files changed, 72 insertions(+), 63 deletions(-) diff --git a/bolt-sidecar/src/api/commitments/server.rs b/bolt-sidecar/src/api/commitments/server.rs index db37656b..42c4a427 100644 --- a/bolt-sidecar/src/api/commitments/server.rs +++ b/bolt-sidecar/src/api/commitments/server.rs @@ -175,7 +175,7 @@ mod test { use crate::{ primitives::commitment::ECDSASignatureExt, - test_util::{create_signed_commitment_request, default_test_transaction}, + test_util::{create_signed_inclusion_request, default_test_transaction}, }; use super::*; @@ -194,7 +194,7 @@ mod test { let sk = SecretKey::random(&mut rand::thread_rng()); let signer = PrivateKeySigner::from(sk.clone()); let tx = default_test_transaction(signer.address(), None); - let req = create_signed_commitment_request(&[tx], &sk, 12).await.unwrap(); + let req = create_signed_inclusion_request(&[tx], &sk, 12).await.unwrap(); let payload = json!({ "jsonrpc": "2.0", @@ -236,9 +236,9 @@ mod test { let sk = SecretKey::random(&mut rand::thread_rng()); let signer = PrivateKeySigner::from(sk.clone()); let tx = default_test_transaction(signer.address(), None); - let req = create_signed_commitment_request(&[tx], &sk, 12).await.unwrap(); + let req = create_signed_inclusion_request(&[tx], &sk, 12).await.unwrap(); - let sig = req.signature().unwrap().to_hex(); + let sig = req.signature.unwrap().to_hex(); let payload = json!({ "jsonrpc": "2.0", diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs index 46fd2c52..abbe8dcd 100644 --- a/bolt-sidecar/src/driver.rs +++ b/bolt-sidecar/src/driver.rs @@ -27,6 +27,7 @@ use crate::{ config::Opts, crypto::{SignableBLS, SignerECDSA}, primitives::{ + commitment::{CommittableRequest, SignedCommitment}, read_signed_delegations_from_file, CommitmentRequest, ConstraintsMessage, FetchPayloadRequest, SignedConstraints, TransactionExt, }, @@ -269,7 +270,7 @@ impl SidecarDriver { /// Handle an incoming API event, validating the request and responding with a commitment. async fn handle_incoming_api_event(&mut self, event: CommitmentEvent) { - let CommitmentEvent { mut request, response } = event; + let CommitmentEvent { request, response } = event; info!("Received new commitment request: {:?}", request); ApiMetrics::increment_inclusion_commitments_received(); @@ -277,10 +278,10 @@ impl SidecarDriver { // When we'll add more commitment types, we'll need to match on the request type here. // For now, we only support inclusion requests so the flow is straightforward. - let CommitmentRequest::Inclusion(inclusion_request) = request.clone(); + let CommitmentRequest::Inclusion(mut inclusion_request) = request; let target_slot = inclusion_request.slot; - let validator_pubkey = match self.consensus.validate_request(&request) { + let validator_pubkey = match self.consensus.validate_request(&inclusion_request) { Ok(pubkey) => pubkey, Err(err) => { warn!(?err, "Consensus: failed to validate request"); @@ -305,7 +306,7 @@ impl SidecarDriver { return; }; - if let Err(err) = self.execution.validate_request(&mut request).await { + if let Err(err) = self.execution.validate_request(&mut inclusion_request).await { warn!(?err, "Execution: failed to validate request"); ApiMetrics::increment_validation_errors(err.to_tag_str().to_owned()); let _ = response.send(Err(CommitmentError::Validation(err))); @@ -324,9 +325,10 @@ impl SidecarDriver { // // For more information, check out the constraints API docs: // https://docs.boltprotocol.xyz/technical-docs/api/builder#constraints - for tx in inclusion_request.txs { + for tx in inclusion_request.txs.iter() { let tx_type = tx.tx_type(); - let message = ConstraintsMessage::from_tx(signing_pubkey.clone(), target_slot, tx); + let message = + ConstraintsMessage::from_tx(signing_pubkey.clone(), target_slot, tx.clone()); let digest = message.digest(); let signature_result = match &self.constraint_signer { @@ -351,10 +353,10 @@ impl SidecarDriver { } // Create a commitment by signing the request - match request.commit_and_sign(&self.commitment_signer).await { + match inclusion_request.commit_and_sign(&self.commitment_signer).await { Ok(commitment) => { debug!(target_slot, elapsed = ?start.elapsed(), "Commitment signed and sent"); - response.send(Ok(commitment)).ok() + response.send(Ok(SignedCommitment::Inclusion(commitment))).ok() } Err(err) => { error!(?err, "Failed to sign commitment"); diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index 7e4a18e7..0e9326f0 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -63,9 +63,7 @@ impl CommitmentRequest { ) -> eyre::Result { match self { CommitmentRequest::Inclusion(req) => { - let digest = req.digest(); - let signature = signer.sign_hash(&digest).await?; - Ok(SignedCommitment::Inclusion(InclusionCommitment { request: req, signature })) + Ok(SignedCommitment::Inclusion(req.commit_and_sign(signer).await?)) } } } @@ -78,6 +76,12 @@ impl CommitmentRequest { } } +pub trait CommittableRequest { + type Target; + + async fn commit_and_sign(self, signer: &S) -> eyre::Result; +} + /// Request to include a transaction at a specific slot. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct InclusionRequest { @@ -96,6 +100,20 @@ pub struct InclusionRequest { pub signer: Option
, } +impl CommittableRequest for InclusionRequest { + type Target = InclusionCommitment; + + /// Commits and signs the request with the provided signer. Returns a [SignedCommitment]. + async fn commit_and_sign( + self, + signer: &S, + ) -> eyre::Result { + let digest = self.digest(); + let signature = signer.sign_hash(&digest).await?; + Ok(InclusionCommitment { request: self, signature }) + } +} + impl InclusionRequest { /// Validates the transaction fees against a minimum basefee. /// Returns true if the fee is greater than or equal to the min, false otherwise. diff --git a/bolt-sidecar/src/state/consensus.rs b/bolt-sidecar/src/state/consensus.rs index 7d76d30c..965661b5 100644 --- a/bolt-sidecar/src/state/consensus.rs +++ b/bolt-sidecar/src/state/consensus.rs @@ -11,7 +11,7 @@ use tracing::debug; use super::CommitmentDeadline; use crate::{ client::BeaconClient, - primitives::{CommitmentRequest, InclusionRequest, Slot}, + primitives::{InclusionRequest, Slot}, telemetry::ApiMetrics, }; @@ -119,16 +119,11 @@ impl ConsensusState { /// 2. The request hasn't passed the slot deadline. /// /// If the request is valid, return the validator public key for the target slot. - pub fn validate_request( - &self, - request: &CommitmentRequest, - ) -> Result { + pub fn validate_request(&self, req: &InclusionRequest) -> Result { if self.unsafe_disable_consensus_checks { return Ok(BlsPublicKey::default()); } - let CommitmentRequest::Inclusion(req) = request; - // Check if the slot is in the current epoch or next epoch (if unsafe lookahead is enabled) if req.slot < self.epoch.start_slot || req.slot >= self.furthest_slot() { return Err(ConsensusError::InvalidSlot(req.slot)); diff --git a/bolt-sidecar/src/state/execution.rs b/bolt-sidecar/src/state/execution.rs index 5b9df3c1..858311d4 100644 --- a/bolt-sidecar/src/state/execution.rs +++ b/bolt-sidecar/src/state/execution.rs @@ -13,7 +13,7 @@ use crate::{ builder::BlockTemplate, common::{calculate_max_basefee, max_transaction_cost, validate_transaction}, config::limits::LimitsOpts, - primitives::{AccountState, CommitmentRequest, InclusionRequest, SignedConstraints, Slot}, + primitives::{AccountState, InclusionRequest, SignedConstraints, Slot}, telemetry::ApiMetrics, }; @@ -227,10 +227,8 @@ impl ExecutionState { /// TODO: should also validate everything in https://github.com/paradigmxyz/reth/blob/9aa44e1a90b262c472b14cd4df53264c649befc2/crates/transaction-pool/src/validate/eth.rs#L153 pub async fn validate_request( &mut self, - request: &mut CommitmentRequest, + req: &mut InclusionRequest, ) -> Result<(), ValidationError> { - let CommitmentRequest::Inclusion(req) = request; - req.recover_signers()?; let target_slot = req.slot; @@ -595,7 +593,7 @@ mod tests { crypto::SignableBLS, primitives::{ConstraintsMessage, SignedConstraints}, state::fetcher, - test_util::{create_signed_commitment_request, default_test_transaction, launch_anvil}, + test_util::{create_signed_inclusion_request, default_test_transaction, launch_anvil}, }; use super::*; @@ -618,7 +616,7 @@ mod tests { let tx = default_test_transaction(*sender, None); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(state.validate_request(&mut request).await.is_ok()); @@ -644,7 +642,7 @@ mod tests { // Create a transaction with a nonce that is too high let tx = default_test_transaction(*sender, Some(1)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; // Insert a constraint diff for slot 11 let mut diffs = HashMap::new(); @@ -690,7 +688,7 @@ mod tests { // Create a transaction with a nonce that is too low let tx = default_test_transaction(*sender, Some(0)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -702,7 +700,7 @@ mod tests { // Create a transaction with a nonce that is too high let tx = default_test_transaction(*sender, Some(2)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -732,7 +730,7 @@ mod tests { let tx = default_test_transaction(*sender, None) .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -766,8 +764,8 @@ mod tests { // burn the balance let tx = default_test_transaction(*sender, Some(0)).with_value(uint!(balance_to_burn)); - let request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; - let tx_bytes = request.as_inclusion_request().unwrap().txs.first().unwrap().encoded_2718(); + let request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; + let tx_bytes = request.txs.first().unwrap().encoded_2718(); let _ = client.inner().send_raw_transaction(tx_bytes.into()).await?; // wait for the transaction to be included to update the sender balance @@ -777,21 +775,18 @@ mod tests { // create a new transaction and request a preconfirmation for it let tx = default_test_transaction(*sender, Some(1)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(state.validate_request(&mut request).await.is_ok()); - let message = ConstraintsMessage::build( - Default::default(), - request.as_inclusion_request().unwrap().clone(), - ); + let message = ConstraintsMessage::build(Default::default(), request.clone()); let signature = signer.sign_commit_boost_root(message.digest())?; let signed_constraints = SignedConstraints { message, signature }; state.add_constraint(10, signed_constraints); // create a new transaction and request a preconfirmation for it let tx = default_test_transaction(*sender, Some(2)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; // this should fail because the balance is insufficient as we spent // all of it on the previous preconfirmation @@ -832,7 +827,7 @@ mod tests { .with_max_fee_per_gas(basefee - 1) .with_max_priority_fee_per_gas(basefee / 2); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -865,7 +860,7 @@ mod tests { let tx = default_test_transaction(*sender, None).with_gas_limit(6_000_000); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -899,7 +894,7 @@ mod tests { let tx = default_test_transaction(*sender, None) .with_max_priority_fee_per_gas(GWEI_TO_WEI as u128); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -910,7 +905,7 @@ mod tests { let tx = default_test_transaction(*sender, None) .with_max_priority_fee_per_gas(3 * GWEI_TO_WEI as u128); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(state.validate_request(&mut request).await.is_ok()); @@ -946,7 +941,7 @@ mod tests { let tx = default_test_transaction(*sender, None) .with_gas_price(max_base_fee + GWEI_TO_WEI as u128); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -957,7 +952,7 @@ mod tests { let tx = default_test_transaction(*sender, None) .with_gas_price(max_base_fee + 3 * GWEI_TO_WEI as u128); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(state.validate_request(&mut request).await.is_ok()); @@ -993,8 +988,7 @@ mod tests { let tx = default_test_transaction(*sender, None) .with_gas_price(max_base_fee + 3 * GWEI_TO_WEI as u128); - let mut request = - create_signed_commitment_request(&[tx.clone(), tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx.clone(), tx], sender_pk, 10).await?; let response = state.validate_request(&mut request).await; println!("{response:?}"); @@ -1029,8 +1023,8 @@ mod tests { let signed = tx.clone().build(&signer).await?; let target_slot = 10; - let mut request = create_signed_commitment_request(&[tx], sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); + let mut request = create_signed_inclusion_request(&[tx], sender_pk, target_slot).await?; + let inclusion_request = request.clone(); assert!(state.validate_request(&mut request).await.is_ok()); @@ -1077,8 +1071,8 @@ mod tests { let tx = default_test_transaction(*sender, None); let target_slot = 10; - let mut request = create_signed_commitment_request(&[tx], sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); + let mut request = create_signed_inclusion_request(&[tx], sender_pk, target_slot).await?; + let inclusion_request = request.clone(); assert!(state.validate_request(&mut request).await.is_ok()); @@ -1124,8 +1118,8 @@ mod tests { let tx = default_test_transaction(*sender, None).with_gas_limit(4_999_999); let target_slot = 10; - let mut request = create_signed_commitment_request(&[tx], sender_pk, target_slot).await?; - let inclusion_request = request.as_inclusion_request().unwrap().clone(); + let mut request = create_signed_inclusion_request(&[tx], sender_pk, target_slot).await?; + let inclusion_request = request.clone(); assert!(state.validate_request(&mut request).await.is_ok()); @@ -1141,7 +1135,7 @@ mod tests { // This tx will exceed the committed gas limit let tx = default_test_transaction(*sender, Some(1)); - let mut request = create_signed_commitment_request(&[tx], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -1171,7 +1165,7 @@ mod tests { let tx2 = default_test_transaction(*sender, Some(1)); let tx3 = default_test_transaction(*sender, Some(2)); - let mut request = create_signed_commitment_request(&[tx1, tx2, tx3], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx1, tx2, tx3], sender_pk, 10).await?; assert!(state.validate_request(&mut request).await.is_ok()); @@ -1198,7 +1192,7 @@ mod tests { let tx2 = default_test_transaction(*sender, Some(1)); let tx3 = default_test_transaction(*sender, Some(3)); // wrong nonce, should be 2 - let mut request = create_signed_commitment_request(&[tx1, tx2, tx3], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx1, tx2, tx3], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, @@ -1229,7 +1223,7 @@ mod tests { let tx3 = default_test_transaction(*sender, Some(2)) .with_value(uint!(11_000_U256 * Uint::from(ETH_TO_WEI))); - let mut request = create_signed_commitment_request(&[tx1, tx2, tx3], sender_pk, 10).await?; + let mut request = create_signed_inclusion_request(&[tx1, tx2, tx3], sender_pk, 10).await?; assert!(matches!( state.validate_request(&mut request).await, diff --git a/bolt-sidecar/src/test_util.rs b/bolt-sidecar/src/test_util.rs index 3004452a..45d76af6 100644 --- a/bolt-sidecar/src/test_util.rs +++ b/bolt-sidecar/src/test_util.rs @@ -24,8 +24,8 @@ use crate::{ config::{ChainConfig, Opts}, crypto::{ecdsa::SignableECDSA, SignableBLS}, primitives::{ - CommitmentRequest, ConstraintsMessage, DelegationMessage, FullTransaction, - InclusionRequest, RevocationMessage, SignedConstraints, SignedDelegation, SignedRevocation, + ConstraintsMessage, DelegationMessage, FullTransaction, InclusionRequest, + RevocationMessage, SignedConstraints, SignedDelegation, SignedRevocation, }, signer::local::LocalSigner, }; @@ -161,11 +161,11 @@ impl SignableECDSA for TestSignableData { /// Create a valid signed commitment request for testing purposes /// from the given transaction, private key of the sender, and slot. -pub(crate) async fn create_signed_commitment_request( +pub(crate) async fn create_signed_inclusion_request( txs: &[TransactionRequest], sk: &K256SecretKey, slot: u64, -) -> eyre::Result { +) -> eyre::Result { let sk = K256SigningKey::from_slice(sk.to_bytes().as_slice())?; let signer = PrivateKeySigner::from_signing_key(sk.clone()); let wallet = EthereumWallet::from(signer.clone()); @@ -185,7 +185,7 @@ pub(crate) async fn create_signed_commitment_request( request.set_signature(Signature::try_from(signature.as_bytes().as_ref()).unwrap()); request.set_signer(signer.address()); - Ok(CommitmentRequest::Inclusion(request)) + Ok(request) } fn random_constraints(count: usize) -> Vec { From 6645094f9f101be7240bcfbb654d2f999d005070 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 13 Nov 2024 13:44:36 +0100 Subject: [PATCH 3/6] chore(sidecar): fmt --- bolt-sidecar/src/state/consensus.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/bolt-sidecar/src/state/consensus.rs b/bolt-sidecar/src/state/consensus.rs index 965661b5..ee97188f 100644 --- a/bolt-sidecar/src/state/consensus.rs +++ b/bolt-sidecar/src/state/consensus.rs @@ -72,7 +72,8 @@ pub struct ConsensusState { /// It is considered unsafe because it is possible for the next epoch's duties to /// change if there are beacon chain deposits or withdrawals in the current epoch. unsafe_lookahead_enabled: bool, - /// If consensus checks should be disabled when accepting commitments. For testing purposes only. + /// If consensus checks should be disabled when accepting commitments. For testing purposes + /// only. /// /// If enabled, the sidecar will sign every incoming commitment with the first private key /// available. @@ -130,8 +131,8 @@ impl ConsensusState { } // If the request is for the next slot, check if it's within the commitment deadline - if req.slot == self.latest_slot + 1 - && self.latest_slot_timestamp + self.commitment_deadline_duration < Instant::now() + if req.slot == self.latest_slot + 1 && + self.latest_slot_timestamp + self.commitment_deadline_duration < Instant::now() { return Err(ConsensusError::DeadlineExceeded); } @@ -215,9 +216,9 @@ impl ConsensusState { /// Returns the furthest slot for which a commitment request is considered valid, whether in /// the current epoch or next epoch (if unsafe lookahead is enabled) fn furthest_slot(&self) -> u64 { - self.epoch.start_slot - + SLOTS_PER_EPOCH - + if self.unsafe_lookahead_enabled { SLOTS_PER_EPOCH } else { 0 } + self.epoch.start_slot + + SLOTS_PER_EPOCH + + if self.unsafe_lookahead_enabled { SLOTS_PER_EPOCH } else { 0 } } } @@ -303,8 +304,8 @@ mod tests { }; let epoch = - state.beacon_api_client.get_beacon_header(BlockId::Head).await?.header.message.slot - / SLOTS_PER_EPOCH; + state.beacon_api_client.get_beacon_header(BlockId::Head).await?.header.message.slot / + SLOTS_PER_EPOCH; state.fetch_proposer_duties(epoch).await?; assert_eq!(state.epoch.proposer_duties.len(), SLOTS_PER_EPOCH as usize * 2); From d9326b795dc20d06d3b60c8e27597de42ebda486 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:46:24 +0100 Subject: [PATCH 4/6] fix: handle api event logic to skip consensus checks --- bolt-sidecar/Cargo.lock | 560 +++++++++++++--------- bolt-sidecar/src/crypto/bls.rs | 4 +- bolt-sidecar/src/driver.rs | 61 ++- bolt-sidecar/src/primitives/commitment.rs | 18 +- bolt-sidecar/src/signer/keystore.rs | 16 +- bolt-sidecar/src/state/consensus.rs | 14 - 6 files changed, 377 insertions(+), 296 deletions(-) diff --git a/bolt-sidecar/Cargo.lock b/bolt-sidecar/Cargo.lock index fe723d17..8ab4476b 100644 --- a/bolt-sidecar/Cargo.lock +++ b/bolt-sidecar/Cargo.lock @@ -118,6 +118,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "alloc-no-stdlib" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" + +[[package]] +name = "alloc-stdlib" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" +dependencies = [ + "alloc-no-stdlib", +] + [[package]] name = "allocator-api2" version = "0.2.18" @@ -143,25 +158,25 @@ dependencies = [ [[package]] name = "alloy" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f809b26b346ce2f8ebd70cc6b2c432fc63336321b2046464ecaded3c0a43a93" +checksum = "b5b524b8c28a7145d1fe4950f84360b5de3e307601679ff0558ddc20ea229399" dependencies = [ - "alloy-consensus 0.6.3", + "alloy-consensus 0.6.4", "alloy-contract", - "alloy-core 0.8.11", - "alloy-eips 0.6.3", - "alloy-genesis 0.6.3", - "alloy-network 0.6.3", - "alloy-provider 0.6.3", + "alloy-core 0.8.12", + "alloy-eips 0.6.4", + "alloy-genesis 0.6.4", + "alloy-network 0.6.4", + "alloy-provider 0.6.4", "alloy-pubsub", - "alloy-rpc-client 0.6.3", - "alloy-rpc-types 0.6.3", - "alloy-serde 0.6.3", - "alloy-signer 0.6.3", + "alloy-rpc-client 0.6.4", + "alloy-rpc-types 0.6.4", + "alloy-serde 0.6.4", + "alloy-signer 0.6.4", "alloy-signer-local", - "alloy-transport 0.6.3", - "alloy-transport-http 0.6.3", + "alloy-transport 0.6.4", + "alloy-transport-http 0.6.4", "alloy-transport-ipc", "alloy-transport-ws", ] @@ -172,7 +187,7 @@ version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18c5c520273946ecf715c0010b4e3503d7eba9893cd9ce6b7fff5654c4a3c470" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "num_enum", "serde", "strum", @@ -208,14 +223,14 @@ dependencies = [ [[package]] name = "alloy-consensus" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef11c6b2dfbf77dca7bafc6759860391395f07c04d5486f2a2e2563d2961639b" +checksum = "ae09ffd7c29062431dd86061deefe4e3c6f07fa0d674930095f8dcedb0baf02c" dependencies = [ - "alloy-eips 0.6.3", - "alloy-primitives 0.8.11", + "alloy-eips 0.6.4", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-serde 0.6.3", + "alloy-serde 0.6.4", "auto_impl", "c-kzg", "derive_more 1.0.0", @@ -225,20 +240,20 @@ dependencies = [ [[package]] name = "alloy-contract" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8faa407ef916bfe0677c52c9b2258ce0698c53e9e15a837d1501e3ae9e57421a" +checksum = "66430a72d5bf5edead101c8c2f0a24bada5ec9f3cf9909b3e08b6d6899b4803e" dependencies = [ - "alloy-dyn-abi 0.8.11", - "alloy-json-abi 0.8.11", - "alloy-network 0.6.3", - "alloy-network-primitives 0.6.3", - "alloy-primitives 0.8.11", - "alloy-provider 0.6.3", + "alloy-dyn-abi 0.8.12", + "alloy-json-abi 0.8.12", + "alloy-network 0.6.4", + "alloy-network-primitives 0.6.4", + "alloy-primitives 0.8.12", + "alloy-provider 0.6.4", "alloy-pubsub", - "alloy-rpc-types-eth 0.6.3", - "alloy-sol-types 0.8.11", - "alloy-transport 0.6.3", + "alloy-rpc-types-eth 0.6.4", + "alloy-sol-types 0.8.12", + "alloy-transport 0.6.4", "futures", "futures-util", "thiserror", @@ -258,15 +273,15 @@ dependencies = [ [[package]] name = "alloy-core" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47ef9e96462d0b9fee9008c53c1f3d017b9498fcdef3ad8d728db98afef47955" +checksum = "9c8316d83e590f4163b221b8180008f302bda5cf5451202855cdd323e588849c" dependencies = [ - "alloy-dyn-abi 0.8.11", - "alloy-json-abi 0.8.11", - "alloy-primitives 0.8.11", + "alloy-dyn-abi 0.8.12", + "alloy-json-abi 0.8.12", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-sol-types 0.8.11", + "alloy-sol-types 0.8.12", ] [[package]] @@ -288,14 +303,14 @@ dependencies = [ [[package]] name = "alloy-dyn-abi" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85132f2698b520fab3f54beed55a44389f7006a7b557a0261e1e69439dcc1572" +checksum = "ef2364c782a245cf8725ea6dbfca5f530162702b5d685992ea03ce64529136cc" dependencies = [ - "alloy-json-abi 0.8.11", - "alloy-primitives 0.8.11", - "alloy-sol-type-parser 0.8.11", - "alloy-sol-types 0.8.11", + "alloy-json-abi 0.8.12", + "alloy-primitives 0.8.12", + "alloy-sol-type-parser 0.8.12", + "alloy-sol-types 0.8.12", "const-hex", "itoa", "serde", @@ -309,7 +324,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0069cf0642457f87a01a014f6dc29d5d893cd4fd8fddf0c3cdfad1bb3ebafc41" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "alloy-rlp", "serde", ] @@ -320,7 +335,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69fb9fd842fdf10a524bbf2c4de6942ad869c1c8c3d128a1b09e67ed5f7cedbd" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "alloy-rlp", "derive_more 1.0.0", "k256 0.13.3", @@ -361,15 +376,15 @@ dependencies = [ [[package]] name = "alloy-eips" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d6c0c1744a7af7d325dca6b5c5bb431a6307c0961088f7a236ca2694c4a87e" +checksum = "5b6aa3961694b30ba53d41006131a2fca3bdab22e4c344e46db2c639e7c2dfdd" dependencies = [ "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-serde 0.6.3", + "alloy-serde 0.6.4", "c-kzg", "derive_more 1.0.0", "once_cell", @@ -390,12 +405,12 @@ dependencies = [ [[package]] name = "alloy-genesis" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a5a0a01ef6ec3cd3ebd52a7b3bc7f8a92b23e478e69c07abd94abf05e6b48e" +checksum = "e53f7877ded3921d18a0a9556d55bedf84535567198c9edab2aa23106da91855" dependencies = [ - "alloy-primitives 0.8.11", - "alloy-serde 0.6.3", + "alloy-primitives 0.8.12", + "alloy-serde 0.6.4", "serde", ] @@ -413,12 +428,12 @@ dependencies = [ [[package]] name = "alloy-json-abi" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded610181f3dad5810f6ff12d1a99994cf9b42d2fcb7709029352398a5da5ae6" +checksum = "b84c506bf264110fa7e90d9924f742f40ef53c6572ea56a0b0bd714a567ed389" dependencies = [ - "alloy-primitives 0.8.11", - "alloy-sol-type-parser 0.8.11", + "alloy-primitives 0.8.12", + "alloy-sol-type-parser 0.8.12", "serde", "serde_json", ] @@ -452,12 +467,12 @@ dependencies = [ [[package]] name = "alloy-json-rpc" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fd0e2cff5ab68defc5050ff9e81cb053c5b52cf4809fc8786664898e29ae75" +checksum = "3694b7e480728c0b3e228384f223937f14c10caef5a4c766021190fc8f283d35" dependencies = [ - "alloy-primitives 0.8.11", - "alloy-sol-types 0.8.11", + "alloy-primitives 0.8.12", + "alloy-sol-types 0.8.12", "serde", "serde_json", "thiserror", @@ -507,19 +522,19 @@ dependencies = [ [[package]] name = "alloy-network" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c9eca0c04ca8a663966ce7f5b19c03927f2b4d82910cb76cb4008490cfa838" -dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-json-rpc 0.6.3", - "alloy-network-primitives 0.6.3", - "alloy-primitives 0.8.11", - "alloy-rpc-types-eth 0.6.3", - "alloy-serde 0.6.3", - "alloy-signer 0.6.3", - "alloy-sol-types 0.8.11", +checksum = "ea94b8ceb5c75d7df0a93ba0acc53b55a22b47b532b600a800a87ef04eb5b0b4" +dependencies = [ + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-json-rpc 0.6.4", + "alloy-network-primitives 0.6.4", + "alloy-primitives 0.8.12", + "alloy-rpc-types-eth 0.6.4", + "alloy-serde 0.6.4", + "alloy-signer 0.6.4", + "alloy-sol-types 0.8.12", "async-trait", "auto_impl", "futures-utils-wasm", @@ -541,25 +556,25 @@ dependencies = [ [[package]] name = "alloy-network-primitives" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4c3050f19dc93a7f09fef670c8db04a15e7e2901494ca40decbce323be69643" +checksum = "df9f3e281005943944d15ee8491534a1c7b3cbf7a7de26f8c433b842b93eb5f9" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-primitives 0.8.11", - "alloy-serde 0.6.3", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-primitives 0.8.12", + "alloy-serde 0.6.4", "serde", ] [[package]] name = "alloy-node-bindings" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5ebd44d0ab30f1018dc1ff01686ea1a3ae732601841a4fb277c9d0b3a34bf50" +checksum = "c9805d126f24be459b958973c0569c73e1aadd27d4535eee82b2b6764aa03616" dependencies = [ - "alloy-genesis 0.6.3", - "alloy-primitives 0.8.11", + "alloy-genesis 0.6.4", + "alloy-primitives 0.8.12", "k256 0.13.3", "rand 0.8.5", "serde_json", @@ -594,9 +609,9 @@ dependencies = [ [[package]] name = "alloy-primitives" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd58d377699e6cfeab52c4a9d28bdc4ef37e2bd235ff2db525071fe37a2e9af5" +checksum = "9fce5dbd6a4f118eecc4719eaa9c7ffc31c315e6c5ccde3642db927802312425" dependencies = [ "alloy-rlp", "bytes", @@ -688,24 +703,24 @@ dependencies = [ [[package]] name = "alloy-provider" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8e5a28e7c4c04afc0f20b2aecf6f9214d6cfd5009187c0b8616a8f8918739c" +checksum = "40c1f9eede27bf4c13c099e8e64d54efd7ce80ef6ea47478aa75d5d74e2dba3b" dependencies = [ "alloy-chains", - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-json-rpc 0.6.3", - "alloy-network 0.6.3", - "alloy-network-primitives 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-json-rpc 0.6.4", + "alloy-network 0.6.4", + "alloy-network-primitives 0.6.4", + "alloy-primitives 0.8.12", "alloy-pubsub", - "alloy-rpc-client 0.6.3", - "alloy-rpc-types-engine 0.6.3", - "alloy-rpc-types-eth 0.6.3", + "alloy-rpc-client 0.6.4", + "alloy-rpc-types-engine 0.6.4", + "alloy-rpc-types-eth 0.6.4", "alloy-rpc-types-trace", - "alloy-transport 0.6.3", - "alloy-transport-http 0.6.3", + "alloy-transport 0.6.4", + "alloy-transport-http 0.6.4", "alloy-transport-ipc", "alloy-transport-ws", "async-stream", @@ -730,13 +745,13 @@ dependencies = [ [[package]] name = "alloy-pubsub" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "365dd813ec271a14febc31ea8ed64185856534f5644511f0c7a2961db060d878" +checksum = "90f1f34232f77341076541c405482e4ae12f0ee7153d8f9969fc1691201b2247" dependencies = [ - "alloy-json-rpc 0.6.3", - "alloy-primitives 0.8.11", - "alloy-transport 0.6.3", + "alloy-json-rpc 0.6.4", + "alloy-primitives 0.8.12", + "alloy-transport 0.6.4", "bimap", "futures", "serde", @@ -813,15 +828,15 @@ dependencies = [ [[package]] name = "alloy-rpc-client" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336362936bb9fef88f27d51f2ede8c15cdfdb7f81b042e74257770052547101" +checksum = "374dbe0dc3abdc2c964f36b3d3edf9cdb3db29d16bda34aa123f03d810bec1dd" dependencies = [ - "alloy-json-rpc 0.6.3", - "alloy-primitives 0.8.11", + "alloy-json-rpc 0.6.4", + "alloy-primitives 0.8.12", "alloy-pubsub", - "alloy-transport 0.6.3", - "alloy-transport-http 0.6.3", + "alloy-transport 0.6.4", + "alloy-transport-http 0.6.4", "alloy-transport-ipc", "alloy-transport-ws", "futures", @@ -862,16 +877,16 @@ dependencies = [ [[package]] name = "alloy-rpc-types" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac9a46bc01bc27dbf4dd27d46986eda661ffe99e78aea3078a77b8c064072b01" +checksum = "c74832aa474b670309c20fffc2a869fa141edab7c79ff7963fad0a08de60bae1" dependencies = [ - "alloy-primitives 0.8.11", - "alloy-rpc-types-beacon 0.6.3", - "alloy-rpc-types-engine 0.6.3", - "alloy-rpc-types-eth 0.6.3", + "alloy-primitives 0.8.12", + "alloy-rpc-types-beacon 0.6.4", + "alloy-rpc-types-engine 0.6.4", + "alloy-rpc-types-eth 0.6.4", "alloy-rpc-types-trace", - "alloy-serde 0.6.3", + "alloy-serde 0.6.4", "serde", ] @@ -893,13 +908,13 @@ dependencies = [ [[package]] name = "alloy-rpc-types-beacon" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f9f6f071674c62424b62e22307aa83a35a0b1b84820649cc82034a50389ddc6" +checksum = "922fa76678d2f9f07ea1b19309b5cfbf244c6029dcba3515227b515fdd6ed4a7" dependencies = [ - "alloy-eips 0.6.3", - "alloy-primitives 0.8.11", - "alloy-rpc-types-engine 0.6.3", + "alloy-eips 0.6.4", + "alloy-primitives 0.8.12", + "alloy-rpc-types-engine 0.6.4", "serde", "serde_with", "thiserror", @@ -927,15 +942,15 @@ dependencies = [ [[package]] name = "alloy-rpc-types-engine" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ee44332315ef1adde384e44db3b5724d74d0cd0e0856a681c4db2b4da3a423e" +checksum = "3f56294dce86af23ad6ee8df46cf8b0d292eb5d1ff67dc88a0886051e32b1faf" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-serde 0.6.3", + "alloy-serde 0.6.4", "derive_more 1.0.0", "jsonwebtoken", "rand 0.8.5", @@ -982,17 +997,17 @@ dependencies = [ [[package]] name = "alloy-rpc-types-eth" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d58fa055e02d04bc70443ecce984951fb5be02d2c843c640ca48237cdec66af1" +checksum = "a8a477281940d82d29315846c7216db45b15e90bcd52309da9f54bcf7ad94a11" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-network-primitives 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-network-primitives 0.6.4", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-serde 0.6.3", - "alloy-sol-types 0.8.11", + "alloy-serde 0.6.4", + "alloy-sol-types 0.8.12", "derive_more 1.0.0", "itertools 0.13.0", "serde", @@ -1001,13 +1016,13 @@ dependencies = [ [[package]] name = "alloy-rpc-types-trace" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1319edeae0e5f453424d658f8f450a5b1090b9ee6c0c014dc216b42f11c9dc57" +checksum = "ecd8b4877ef520c138af702097477cdd19504a8e1e4675ba37e92ba40f2d3c6f" dependencies = [ - "alloy-primitives 0.8.11", - "alloy-rpc-types-eth 0.6.3", - "alloy-serde 0.6.3", + "alloy-primitives 0.8.12", + "alloy-rpc-types-eth 0.6.4", + "alloy-serde 0.6.4", "serde", "serde_json", "thiserror", @@ -1037,11 +1052,11 @@ dependencies = [ [[package]] name = "alloy-serde" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "feafd71e0e252b063fe4b07962beedf0445e66b07b4b44af178863d21e75b0fa" +checksum = "4dfa4a7ccf15b2492bb68088692481fd6b2604ccbee1d0d6c44c21427ae4df83" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "serde", "serde_json", ] @@ -1076,11 +1091,11 @@ dependencies = [ [[package]] name = "alloy-signer" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebad84d52550351438ec7f151dbc551f870c31eecf23b473df5b779a91eee8ca" +checksum = "2e10aec39d60dc27edcac447302c7803d2371946fb737245320a05b78eb2fafd" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "async-trait", "auto_impl", "elliptic-curve 0.13.8", @@ -1090,14 +1105,14 @@ dependencies = [ [[package]] name = "alloy-signer-local" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed742d76943b5ebaabfdf3d0d8b69a4377fc2981c7955a807e33a3469aed0cdc" +checksum = "d8396f6dff60700bc1d215ee03d86ff56de268af96e2bf833a14d0bafcab9882" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-network 0.6.3", - "alloy-primitives 0.8.11", - "alloy-signer 0.6.3", + "alloy-consensus 0.6.4", + "alloy-network 0.6.4", + "alloy-primitives 0.8.12", + "alloy-signer 0.6.4", "async-trait", "k256 0.13.3", "rand 0.8.5", @@ -1120,12 +1135,12 @@ dependencies = [ [[package]] name = "alloy-sol-macro" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a1b42ac8f45e2f49f4bcdd72cbfde0bb148f5481d403774ffa546e48b83efc1" +checksum = "9343289b4a7461ed8bab8618504c995c049c082b70c7332efd7b32125633dc05" dependencies = [ - "alloy-sol-macro-expander 0.8.11", - "alloy-sol-macro-input 0.8.11", + "alloy-sol-macro-expander 0.8.12", + "alloy-sol-macro-input 0.8.12", "proc-macro-error2", "proc-macro2", "quote", @@ -1152,12 +1167,12 @@ dependencies = [ [[package]] name = "alloy-sol-macro-expander" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06318f1778e57f36333e850aa71bd1bb5e560c10279e236622faae0470c50412" +checksum = "4222d70bec485ceccc5d8fd4f2909edd65b5d5e43d4aca0b5dcee65d519ae98f" dependencies = [ - "alloy-json-abi 0.8.11", - "alloy-sol-macro-input 0.8.11", + "alloy-json-abi 0.8.12", + "alloy-sol-macro-input 0.8.12", "const-hex", "heck 0.5.0", "indexmap 2.6.0", @@ -1165,7 +1180,7 @@ dependencies = [ "proc-macro2", "quote", "syn 2.0.76", - "syn-solidity 0.8.11", + "syn-solidity 0.8.12", "tiny-keccak", ] @@ -1186,11 +1201,11 @@ dependencies = [ [[package]] name = "alloy-sol-macro-input" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eaebb9b0ad61a41345a22c9279975c0cdd231b97947b10d7aad1cf0a7181e4a5" +checksum = "2e17f2677369571b976e51ea1430eb41c3690d344fef567b840bfc0b01b6f83a" dependencies = [ - "alloy-json-abi 0.8.11", + "alloy-json-abi 0.8.12", "const-hex", "dunce", "heck 0.5.0", @@ -1198,7 +1213,7 @@ dependencies = [ "quote", "serde_json", "syn 2.0.76", - "syn-solidity 0.8.11", + "syn-solidity 0.8.12", ] [[package]] @@ -1213,9 +1228,9 @@ dependencies = [ [[package]] name = "alloy-sol-type-parser" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12c71028bfbfec210e24106a542aad3def7caf1a70e2c05710e92a98481980d3" +checksum = "aa64d80ae58ffaafdff9d5d84f58d03775f66c84433916dc9a64ed16af5755da" dependencies = [ "serde", "winnow", @@ -1235,13 +1250,13 @@ dependencies = [ [[package]] name = "alloy-sol-types" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d7fb042d68ddfe79ccb23359de3007f6d4d53c13f703b64fb0db422132111" +checksum = "6520d427d4a8eb7aa803d852d7a52ceb0c519e784c292f64bb339e636918cf27" dependencies = [ - "alloy-json-abi 0.8.11", - "alloy-primitives 0.8.11", - "alloy-sol-macro 0.8.11", + "alloy-json-abi 0.8.12", + "alloy-primitives 0.8.12", + "alloy-sol-macro 0.8.12", "const-hex", "serde", ] @@ -1286,11 +1301,11 @@ dependencies = [ [[package]] name = "alloy-transport" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da63700a2b3176b3009a6d3672d0c657280a517dcec7659c991c55e863a83165" +checksum = "f99acddb34000d104961897dbb0240298e8b775a7efffb9fda2a1a3efedd65b3" dependencies = [ - "alloy-json-rpc 0.6.3", + "alloy-json-rpc 0.6.4", "base64 0.22.1", "futures-util", "futures-utils-wasm", @@ -1336,12 +1351,12 @@ dependencies = [ [[package]] name = "alloy-transport-http" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6613c3abc567b710217d241650ef73cfb8df9bcdc2ef23fdedabf363637e2a00" +checksum = "5dc013132e34eeadaa0add7e74164c1503988bfba8bae885b32e0918ba85a8a6" dependencies = [ - "alloy-json-rpc 0.6.3", - "alloy-transport 0.6.3", + "alloy-json-rpc 0.6.4", + "alloy-transport 0.6.4", "reqwest 0.12.7", "serde_json", "tower 0.5.1", @@ -1351,13 +1366,13 @@ dependencies = [ [[package]] name = "alloy-transport-ipc" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7087a28734aac88a606884cdde8c89ad053bd1c0580c787e31f917a8e4a7cbdd" +checksum = "063edc0660e81260653cc6a95777c29d54c2543a668aa5da2359fb450d25a1ba" dependencies = [ - "alloy-json-rpc 0.6.3", + "alloy-json-rpc 0.6.4", "alloy-pubsub", - "alloy-transport 0.6.3", + "alloy-transport 0.6.4", "bytes", "futures", "interprocess", @@ -1370,12 +1385,12 @@ dependencies = [ [[package]] name = "alloy-transport-ws" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "672797b3f7bcbe67f712f9e8e5703b22f24594bd2b248a90916bdb58811b8b6e" +checksum = "abd170e600801116d5efe64f74a4fc073dbbb35c807013a7d0a388742aeebba0" dependencies = [ "alloy-pubsub", - "alloy-transport 0.6.3", + "alloy-transport 0.6.4", "futures", "http 1.1.0", "rustls 0.23.12", @@ -1392,7 +1407,7 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40d8e28db02c006f7abb20f345ffb3cc99c465e36f676ba262534e654ae76042" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "alloy-rlp", "arrayvec", "derive_more 1.0.0", @@ -1652,6 +1667,22 @@ dependencies = [ "futures-core", ] +[[package]] +name = "async-compression" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" +dependencies = [ + "brotli", + "flate2", + "futures-core", + "memchr", + "pin-project-lite", + "tokio", + "zstd 0.13.2", + "zstd-safe 7.2.1", +] + [[package]] name = "async-sse" version = "5.1.0" @@ -2092,7 +2123,7 @@ name = "bolt-sidecar" version = "0.2.1-alpha" dependencies = [ "account_utils", - "alloy 0.6.3", + "alloy 0.6.4", "alloy-node-bindings", "async-trait", "axum", @@ -2130,7 +2161,7 @@ dependencies = [ "tokio", "tokio-retry", "toml 0.5.11", - "tower-http", + "tower-http 0.5.2", "tracing", "tracing-subscriber", "tree_hash 0.5.2", @@ -2138,6 +2169,27 @@ dependencies = [ "warp", ] +[[package]] +name = "brotli" +version = "7.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc97b8f16f944bba54f0433f07e30be199b6dc2bd25937444bbad560bcea29bd" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", +] + +[[package]] +name = "brotli-decompressor" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" +dependencies = [ + "alloc-no-stdlib", + "alloc-stdlib", +] + [[package]] name = "bs58" version = "0.4.0" @@ -4411,6 +4463,12 @@ dependencies = [ "pin-project-lite", ] +[[package]] +name = "http-range-header" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" + [[package]] name = "http-types" version = "2.12.0" @@ -4755,6 +4813,16 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +[[package]] +name = "iri-string" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc0f0a572e8ffe56e2ff4f769f32ffe919282c3916799f8b68688b6030063bea" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "is-terminal" version = "0.4.13" @@ -5817,15 +5885,15 @@ dependencies = [ [[package]] name = "op-alloy-consensus" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b5745eca869a0b476fbd34025ac40c06a15c46ffc10d6b1c40d21475b05f835" +checksum = "bff54d1d790eca1f3aedbd666162e9c42eceff90b9f9d24b352ed9c2df1e901a" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-serde 0.6.3", + "alloy-serde 0.6.4", "derive_more 1.0.0", "serde", "spin 0.9.8", @@ -5833,16 +5901,16 @@ dependencies = [ [[package]] name = "op-alloy-rpc-types" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b75a52c8659756cfe1119f7711e94749c8dec6ad82408f3c55641ae413fb83" +checksum = "981b7f8ab11fe85ba3c1723702f000429b8d0c16b5883c93d577895f262cbac6" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-network-primitives 0.6.3", - "alloy-primitives 0.8.11", - "alloy-rpc-types-eth 0.6.3", - "alloy-serde 0.6.3", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-network-primitives 0.6.4", + "alloy-primitives 0.8.12", + "alloy-rpc-types-eth 0.6.4", + "alloy-serde 0.6.4", "derive_more 1.0.0", "op-alloy-consensus", "serde", @@ -6727,12 +6795,12 @@ dependencies = [ [[package]] name = "reth-codecs" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-genesis 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-genesis 0.6.4", + "alloy-primitives 0.8.12", "alloy-trie", "bytes", "modular-bitfield", @@ -6743,7 +6811,7 @@ dependencies = [ [[package]] name = "reth-codecs-derive" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ "convert_case 0.6.0", "proc-macro2", @@ -6754,10 +6822,10 @@ dependencies = [ [[package]] name = "reth-ethereum-forks" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ "alloy-chains", - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "alloy-rlp", "auto_impl", "crc", @@ -6771,15 +6839,15 @@ dependencies = [ [[package]] name = "reth-primitives" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-network 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-network 0.6.4", + "alloy-primitives 0.8.12", "alloy-rlp", - "alloy-rpc-types 0.6.3", - "alloy-serde 0.6.3", + "alloy-rpc-types 0.6.4", + "alloy-serde 0.6.4", "alloy-trie", "bytes", "c-kzg", @@ -6802,12 +6870,12 @@ dependencies = [ [[package]] name = "reth-primitives-traits" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ - "alloy-consensus 0.6.3", - "alloy-eips 0.6.3", - "alloy-genesis 0.6.3", - "alloy-primitives 0.8.11", + "alloy-consensus 0.6.4", + "alloy-eips 0.6.4", + "alloy-genesis 0.6.4", + "alloy-primitives 0.8.12", "alloy-rlp", "byteorder", "bytes", @@ -6822,22 +6890,23 @@ dependencies = [ [[package]] name = "reth-rpc-layer" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ - "alloy-rpc-types-engine 0.6.3", + "alloy-rpc-types-engine 0.6.4", "http 1.1.0", "jsonrpsee-http-client", "pin-project", "tower 0.4.13", + "tower-http 0.6.1", "tracing", ] [[package]] name = "reth-static-file-types" version = "1.1.1" -source = "git+https://github.com/paradigmxyz/reth#aece53ae88990bb8d0849b60e9649f68781dd03e" +source = "git+https://github.com/paradigmxyz/reth#03f3646355529554e2a38f2a821881425bc04531" dependencies = [ - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "derive_more 1.0.0", "serde", "strum", @@ -6851,7 +6920,7 @@ checksum = "3702f132bb484f4f0d0ca4f6fbde3c82cfd745041abbedd6eda67730e1868ef0" dependencies = [ "alloy-eip2930", "alloy-eip7702", - "alloy-primitives 0.8.11", + "alloy-primitives 0.8.12", "auto_impl", "bitflags 2.6.0", "bitvec 1.0.1", @@ -8069,9 +8138,9 @@ dependencies = [ [[package]] name = "syn-solidity" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edf42e81491fb8871b74df3d222c64ae8cbc1269ea509fa768a3ed3e1b0ac8cb" +checksum = "f76fe0a3e1476bdaa0775b9aec5b869ed9520c2b2fedfe9c6df3618f8ea6290b" dependencies = [ "paste", "proc-macro2", @@ -8551,6 +8620,37 @@ dependencies = [ "tower-service", ] +[[package]] +name = "tower-http" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437150ab6bbc8c5f0f519e3d5ed4aa883a83dd4cdd3d1b21f9482936046cb97" +dependencies = [ + "async-compression", + "base64 0.22.1", + "bitflags 2.6.0", + "bytes", + "futures-core", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "http-range-header", + "httpdate", + "iri-string", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower 0.5.1", + "tower-layer", + "tower-service", + "tracing", + "uuid 1.10.0", +] + [[package]] name = "tower-layer" version = "0.3.3" diff --git a/bolt-sidecar/src/crypto/bls.rs b/bolt-sidecar/src/crypto/bls.rs index 2f5687b1..534da32a 100644 --- a/bolt-sidecar/src/crypto/bls.rs +++ b/bolt-sidecar/src/crypto/bls.rs @@ -18,6 +18,6 @@ pub trait SignableBLS { } /// Convert a BLS public key from Consensus Types to a byte array. -pub fn cl_public_key_to_arr(pubkey: BlsPublicKey) -> [u8; BLS_PUBLIC_KEY_BYTES_LEN] { - pubkey.as_ref().try_into().expect("BLS keys are 48 bytes") +pub fn cl_public_key_to_arr(pubkey: impl AsRef) -> [u8; BLS_PUBLIC_KEY_BYTES_LEN] { + pubkey.as_ref().as_ref().try_into().expect("BLS keys are 48 bytes") } diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs index abbe8dcd..4ff69d1b 100644 --- a/bolt-sidecar/src/driver.rs +++ b/bolt-sidecar/src/driver.rs @@ -27,9 +27,8 @@ use crate::{ config::Opts, crypto::{SignableBLS, SignerECDSA}, primitives::{ - commitment::{CommittableRequest, SignedCommitment}, - read_signed_delegations_from_file, CommitmentRequest, ConstraintsMessage, - FetchPayloadRequest, SignedConstraints, TransactionExt, + commitment::SignedCommitment, read_signed_delegations_from_file, CommitmentRequest, + ConstraintsMessage, FetchPayloadRequest, SignedConstraints, TransactionExt, }, signer::{keystore::KeystoreSigner, local::LocalSigner, CommitBoostSigner, SignerBLS}, state::{fetcher::StateFetcher, ConsensusState, ExecutionState, HeadTracker, StateClient}, @@ -67,6 +66,8 @@ pub struct SidecarDriver { payload_requests_rx: mpsc::Receiver, /// Stream of slots made from the consensus clock slot_stream: SlotStream, + /// Whether to skip consensus checks (should only be used for testing) + unsafe_skip_consensus_checks: bool, } impl SidecarDriver { @@ -204,7 +205,6 @@ impl SidecarDriver { beacon_client, opts.chain.commitment_deadline(), opts.chain.enable_unsafe_lookahead, - opts.unsafe_disable_consensus_checks, ); let (payload_requests_tx, payload_requests_rx) = mpsc::channel(16); @@ -226,7 +226,10 @@ impl SidecarDriver { let (api_events_tx, api_events_rx) = mpsc::channel(1024); CommitmentsApiServer::new(api_addr).run(api_events_tx).await; + let unsafe_skip_consensus_checks = opts.unsafe_disable_consensus_checks; + Ok(SidecarDriver { + unsafe_skip_consensus_checks, head_tracker, execution, consensus, @@ -271,6 +274,7 @@ impl SidecarDriver { /// Handle an incoming API event, validating the request and responding with a commitment. async fn handle_incoming_api_event(&mut self, event: CommitmentEvent) { let CommitmentEvent { request, response } = event; + info!("Received new commitment request: {:?}", request); ApiMetrics::increment_inclusion_commitments_received(); @@ -281,29 +285,36 @@ impl SidecarDriver { let CommitmentRequest::Inclusion(mut inclusion_request) = request; let target_slot = inclusion_request.slot; - let validator_pubkey = match self.consensus.validate_request(&inclusion_request) { - Ok(pubkey) => pubkey, - Err(err) => { - warn!(?err, "Consensus: failed to validate request"); - let _ = response.send(Err(CommitmentError::Consensus(err))); - return; - } - }; - let available_pubkeys = self.constraint_signer.available_pubkeys(); - // Find a public key to sign new constraints with for this slot. - // This can either be the validator pubkey or a delegatee (if one is available). - let signing_pubkey = if self.consensus.unsafe_disable_consensus_checks { - // Take the first one available - available_pubkeys.iter().take(1).next().cloned() + // Determine the constraint signing public key for this request. Rationale: + // - If we're skipping consensus checks, we can use any available pubkey in the keystore. + // - On regular operation, we need to validate the request against the consensus state to + // determine if the sidecar is the proposer for the given slot. If so, we use the + // validator pubkey or any of its active delegatees to sign constraints. + let signing_pubkey = if self.unsafe_skip_consensus_checks { + available_pubkeys.iter().take(1).next().cloned().expect("at least one available pubkey") } else { - self.constraints_client.find_signing_key(validator_pubkey, available_pubkeys) - }; - let Some(signing_pubkey) = signing_pubkey else { - error!(%target_slot, "No available public key to sign constraints with"); - let _ = response.send(Err(CommitmentError::Internal)); - return; + let validator_pubkey = match self.consensus.validate_request(&inclusion_request) { + Ok(pubkey) => pubkey, + Err(err) => { + warn!(?err, "Consensus: failed to validate request"); + let _ = response.send(Err(CommitmentError::Consensus(err))); + return; + } + }; + + // Find a public key to sign new constraints with for this slot. + // This can either be the validator pubkey or a delegatee (if one is available). + let Some(signing_key) = + self.constraints_client.find_signing_key(validator_pubkey, available_pubkeys) + else { + error!(%target_slot, "No available public key to sign constraints with"); + let _ = response.send(Err(CommitmentError::Internal)); + return; + }; + + signing_key }; if let Err(err) = self.execution.validate_request(&mut inclusion_request).await { @@ -335,7 +346,7 @@ impl SidecarDriver { SignerBLS::Local(signer) => signer.sign_commit_boost_root(digest), SignerBLS::CommitBoost(signer) => signer.sign_commit_boost_root(digest).await, SignerBLS::Keystore(signer) => { - signer.sign_commit_boost_root(digest, signing_pubkey.clone()) + signer.sign_commit_boost_root(digest, &signing_pubkey) } }; diff --git a/bolt-sidecar/src/primitives/commitment.rs b/bolt-sidecar/src/primitives/commitment.rs index 0e9326f0..96c4a48d 100644 --- a/bolt-sidecar/src/primitives/commitment.rs +++ b/bolt-sidecar/src/primitives/commitment.rs @@ -63,7 +63,7 @@ impl CommitmentRequest { ) -> eyre::Result { match self { CommitmentRequest::Inclusion(req) => { - Ok(SignedCommitment::Inclusion(req.commit_and_sign(signer).await?)) + req.commit_and_sign(signer).await.map(SignedCommitment::Inclusion) } } } @@ -76,12 +76,6 @@ impl CommitmentRequest { } } -pub trait CommittableRequest { - type Target; - - async fn commit_and_sign(self, signer: &S) -> eyre::Result; -} - /// Request to include a transaction at a specific slot. #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)] pub struct InclusionRequest { @@ -100,11 +94,9 @@ pub struct InclusionRequest { pub signer: Option
, } -impl CommittableRequest for InclusionRequest { - type Target = InclusionCommitment; - - /// Commits and signs the request with the provided signer. Returns a [SignedCommitment]. - async fn commit_and_sign( +impl InclusionRequest { + /// Commits and signs the request with the provided signer. Returns an [InclusionCommitment]. + pub async fn commit_and_sign( self, signer: &S, ) -> eyre::Result { @@ -112,9 +104,7 @@ impl CommittableRequest for InclusionRequest { let signature = signer.sign_hash(&digest).await?; Ok(InclusionCommitment { request: self, signature }) } -} -impl InclusionRequest { /// Validates the transaction fees against a minimum basefee. /// Returns true if the fee is greater than or equal to the min, false otherwise. pub fn validate_basefee(&self, min: u128) -> bool { diff --git a/bolt-sidecar/src/signer/keystore.rs b/bolt-sidecar/src/signer/keystore.rs index 274c4fa1..5a6240dd 100644 --- a/bolt-sidecar/src/signer/keystore.rs +++ b/bolt-sidecar/src/signer/keystore.rs @@ -12,11 +12,7 @@ use lighthouse_bls::Keypair; use lighthouse_eth2_keystore::Keystore; use ssz::Encode; -use crate::{ - builder::signature::compute_signing_root, - config::ChainConfig, - crypto::bls::{cl_public_key_to_arr, BLSSig}, -}; +use crate::{builder::signature::compute_signing_root, config::ChainConfig, crypto::bls::BLSSig}; use super::SignerResult; @@ -116,7 +112,7 @@ impl KeystoreSigner { pub fn sign_commit_boost_root( &self, root: [u8; 32], - public_key: BlsPublicKey, + public_key: &BlsPublicKey, ) -> SignerResult { self.sign_root(root, public_key, self.chain.commit_boost_domain()) } @@ -125,7 +121,7 @@ impl KeystoreSigner { fn sign_root( &self, root: [u8; 32], - public_key: BlsPublicKey, + public_key: &BlsPublicKey, domain: [u8; 32], ) -> SignerResult { let sk = self @@ -133,9 +129,7 @@ impl KeystoreSigner { .iter() // `as_ssz_bytes` returns the raw bytes we need .find(|kp| kp.pk.as_ssz_bytes() == public_key.as_ref()) - .ok_or(KeystoreError::UnknownPublicKey(hex::encode(cl_public_key_to_arr( - public_key, - ))))?; + .ok_or(KeystoreError::UnknownPublicKey(public_key.to_string()))?; let signing_root = compute_signing_root(root, domain); @@ -377,7 +371,7 @@ mod tests { let sig_keystore = keystore_signer_from_password .sign_commit_boost_root( [0; 32], - BlsPublicKey::try_from(public_key_bytes.as_ref()).unwrap(), + &BlsPublicKey::try_from(public_key_bytes.as_ref()).unwrap(), ) .expect("to sign message"); assert_eq!(sig_local, sig_keystore); diff --git a/bolt-sidecar/src/state/consensus.rs b/bolt-sidecar/src/state/consensus.rs index ee97188f..e2d21516 100644 --- a/bolt-sidecar/src/state/consensus.rs +++ b/bolt-sidecar/src/state/consensus.rs @@ -72,12 +72,6 @@ pub struct ConsensusState { /// It is considered unsafe because it is possible for the next epoch's duties to /// change if there are beacon chain deposits or withdrawals in the current epoch. unsafe_lookahead_enabled: bool, - /// If consensus checks should be disabled when accepting commitments. For testing purposes - /// only. - /// - /// If enabled, the sidecar will sign every incoming commitment with the first private key - /// available. - pub unsafe_disable_consensus_checks: bool, } impl fmt::Debug for ConsensusState { @@ -99,7 +93,6 @@ impl ConsensusState { beacon_api_client: BeaconClient, commitment_deadline_duration: Duration, unsafe_lookahead_enabled: bool, - unsafe_disable_consensus_checks: bool, ) -> Self { ConsensusState { beacon_api_client, @@ -109,7 +102,6 @@ impl ConsensusState { commitment_deadline: CommitmentDeadline::new(0, commitment_deadline_duration), commitment_deadline_duration, unsafe_lookahead_enabled, - unsafe_disable_consensus_checks, } } @@ -121,10 +113,6 @@ impl ConsensusState { /// /// If the request is valid, return the validator public key for the target slot. pub fn validate_request(&self, req: &InclusionRequest) -> Result { - if self.unsafe_disable_consensus_checks { - return Ok(BlsPublicKey::default()); - } - // Check if the slot is in the current epoch or next epoch (if unsafe lookahead is enabled) if req.slot < self.epoch.start_slot || req.slot >= self.furthest_slot() { return Err(ConsensusError::InvalidSlot(req.slot)); @@ -253,7 +241,6 @@ mod tests { commitment_deadline: CommitmentDeadline::new(0, commitment_deadline_duration), commitment_deadline_duration, unsafe_lookahead_enabled: false, - unsafe_disable_consensus_checks: false, }; // Update the slot to 32 @@ -300,7 +287,6 @@ mod tests { commitment_deadline_duration, // We test for both epochs unsafe_lookahead_enabled: true, - unsafe_disable_consensus_checks: false, }; let epoch = From 7bcd5ed408c70f4cb7e45f04df83214238ba9459 Mon Sep 17 00:00:00 2001 From: nicolas <48695862+merklefruit@users.noreply.github.com> Date: Wed, 13 Nov 2024 14:49:04 +0100 Subject: [PATCH 5/6] chore: docs --- bolt-sidecar/src/config/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/config/mod.rs b/bolt-sidecar/src/config/mod.rs index 4f54e279..ba435161 100644 --- a/bolt-sidecar/src/config/mod.rs +++ b/bolt-sidecar/src/config/mod.rs @@ -82,8 +82,9 @@ pub struct Opts { #[clap(long, env = "BOLT_SIDECAR_COMMITMENT_PRIVATE_KEY")] pub commitment_private_key: EcdsaSecretKeyWrapper, /// Unsafely disables consensus checks when validating commitments. - /// If enabled, the sidecar will sign every incoming commitment with the first private key - /// available + /// + /// If enabled, the sidecar will sign every commitment request with the first private key + /// available without checking if connected validators are scheduled to propose a block. #[clap(long, env = "BOLT_SIDECAR_UNSAFE_DISABLE_CONSENSUS_CHECKS", default_value_t = false)] pub unsafe_disable_consensus_checks: bool, /// Operating limits for the sidecar From 9656b68b037a0ea686e1b631b7f8e419b62eee59 Mon Sep 17 00:00:00 2001 From: thedevbirb Date: Wed, 13 Nov 2024 15:41:28 +0100 Subject: [PATCH 6/6] fix(sidecar): choose first available pubkey deterministically --- bolt-sidecar/src/driver.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/bolt-sidecar/src/driver.rs b/bolt-sidecar/src/driver.rs index 4ff69d1b..9c71d786 100644 --- a/bolt-sidecar/src/driver.rs +++ b/bolt-sidecar/src/driver.rs @@ -4,7 +4,7 @@ use alloy::{rpc::types::beacon::events::HeadEvent, signers::local::PrivateKeySig use beacon_api_client::mainnet::Client as BeaconClient; use ethereum_consensus::{ clock::{self, SlotStream, SystemTimeProvider}, - phase0::mainnet::SLOTS_PER_EPOCH, + phase0::mainnet::{BlsPublicKey, SLOTS_PER_EPOCH}, }; use eyre::Context; use futures::StreamExt; @@ -293,7 +293,10 @@ impl SidecarDriver { // determine if the sidecar is the proposer for the given slot. If so, we use the // validator pubkey or any of its active delegatees to sign constraints. let signing_pubkey = if self.unsafe_skip_consensus_checks { - available_pubkeys.iter().take(1).next().cloned().expect("at least one available pubkey") + // PERF: this is inefficient, but it's only used for testing purposes. + let mut ap = available_pubkeys.iter().collect::>(); + ap.sort(); + ap.first().cloned().cloned().expect("at least one available pubkey") } else { let validator_pubkey = match self.consensus.validate_request(&inclusion_request) { Ok(pubkey) => pubkey,