Skip to content
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

chore(sidecar): update constraint api #240

Merged
merged 3 commits into from
Sep 26, 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
18 changes: 9 additions & 9 deletions bolt-sidecar/src/builder/template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl BlockTemplate {
/// Returns the cloned list of transactions from the constraints.
#[inline]
pub fn transactions(&self) -> Vec<FullTransaction> {
self.signed_constraints_list.iter().flat_map(|sc| sc.message.constraints.clone()).collect()
self.signed_constraints_list.iter().flat_map(|sc| sc.message.transactions.clone()).collect()
}

/// Converts the list of signed constraints into a list of signed transactions. Use this when
Expand All @@ -52,7 +52,7 @@ impl BlockTemplate {
self.signed_constraints_list
.iter()
.flat_map(|sc| {
sc.message.constraints.iter().map(|c| c.clone().into_inner().into_transaction())
sc.message.transactions.iter().map(|c| c.clone().into_inner().into_transaction())
})
.collect()
}
Expand All @@ -64,7 +64,7 @@ impl BlockTemplate {
let (commitments, proofs, blobs) =
self.signed_constraints_list
.iter()
.flat_map(|sc| sc.message.constraints.iter())
.flat_map(|sc| sc.message.transactions.iter())
.filter_map(|c| c.blob_sidecar())
.fold(
(Vec::new(), Vec::new(), Vec::new()),
Expand All @@ -90,22 +90,22 @@ impl BlockTemplate {
/// Returns the length of the transactions in the block template.
#[inline]
pub fn transactions_len(&self) -> usize {
self.signed_constraints_list.iter().fold(0, |acc, sc| acc + sc.message.constraints.len())
self.signed_constraints_list.iter().fold(0, |acc, sc| acc + sc.message.transactions.len())
}

/// Returns the committed gas in the block template.
#[inline]
pub fn committed_gas(&self) -> u64 {
self.signed_constraints_list.iter().fold(0, |acc, sc| {
acc + sc.message.constraints.iter().fold(0, |acc, c| acc + c.gas_limit())
acc + sc.message.transactions.iter().fold(0, |acc, c| acc + c.gas_limit())
})
}

/// Returns the blob count of the block template.
#[inline]
pub fn blob_count(&self) -> usize {
self.signed_constraints_list.iter().fold(0, |mut acc, sc| {
acc += sc.message.constraints.iter().fold(0, |acc, c| {
acc += sc.message.transactions.iter().fold(0, |acc, c| {
acc + c.as_eip4844().map(|tx| tx.blob_versioned_hashes.len()).unwrap_or(0)
});

Expand All @@ -115,7 +115,7 @@ impl BlockTemplate {

/// Adds a list of constraints to the block template and updates the state diff.
pub fn add_constraints(&mut self, constraints: SignedConstraints) {
for constraint in constraints.message.constraints.iter() {
for constraint in constraints.message.transactions.iter() {
let max_cost = max_transaction_cost(constraint);
self.state_diff
.diffs
Expand All @@ -134,7 +134,7 @@ impl BlockTemplate {
fn remove_constraints_at_index(&mut self, index: usize) {
let constraints = self.signed_constraints_list.remove(index);

for constraint in constraints.message.constraints.iter() {
for constraint in constraints.message.transactions.iter() {
self.state_diff
.diffs
.entry(*constraint.sender().expect("recovered sender"))
Expand All @@ -155,7 +155,7 @@ impl BlockTemplate {
.signed_constraints_list
.iter()
.enumerate()
.map(|(idx, c)| (idx, &c.message.constraints))
.map(|(idx, c)| (idx, &c.message.transactions))
.filter(|(_idx, c)| c.iter().any(|c| c.sender().expect("recovered sender") == &address))
.map(|(idx, c)| {
(
Expand Down
2 changes: 1 addition & 1 deletion bolt-sidecar/src/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ impl<C: StateFetcher, BLS: SignerBLS, ECDSA: SignerECDSA> SidecarDriver<C, BLS,
};

// Track the number of transactions preconfirmed considering their type
signed_constraints.message.constraints.iter().for_each(|full_tx| {
signed_constraints.message.transactions.iter().for_each(|full_tx| {
ApiMetrics::increment_transactions_preconfirmed(full_tx.tx_type());
});
self.execution.add_constraint(slot, signed_constraints);
Expand Down
20 changes: 10 additions & 10 deletions bolt-sidecar/src/primitives/constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ impl SignableECDSA for ConstraintsMessage {
data.extend_from_slice(&self.slot.to_le_bytes());

let mut constraint_bytes = Vec::new();
for constraint in &self.constraints {
for constraint in &self.transactions {
constraint_bytes.extend_from_slice(&constraint.envelope_encoded().0);
}
data.extend_from_slice(&constraint_bytes);
Expand Down Expand Up @@ -60,15 +60,15 @@ pub struct ConstraintsMessage {
pub top: bool,
/// The constraints that need to be signed.
#[serde(deserialize_with = "deserialize_txs", serialize_with = "serialize_txs")]
pub constraints: Vec<FullTransaction>,
pub transactions: Vec<FullTransaction>,
}

impl ConstraintsMessage {
/// Builds a constraints message from an inclusion request and metadata
pub fn build(pubkey: BlsPublicKey, request: InclusionRequest) -> Self {
let constraints = request.txs;
let transactions = request.txs;

Self { pubkey, slot: request.slot, top: false, constraints }
Self { pubkey, slot: request.slot, top: false, transactions }
}
}

Expand All @@ -79,8 +79,8 @@ impl SignableBLS for ConstraintsMessage {
hasher.update(self.slot.to_le_bytes());
hasher.update((self.top as u8).to_le_bytes());

for constraint in &self.constraints {
hasher.update(constraint.hash());
for tx in &self.transactions {
hasher.update(tx.hash());
}

hasher.finalize().into()
Expand Down Expand Up @@ -114,10 +114,10 @@ mod tests {
let pubkey = BlsPublicKey::default();
let slot = 0;
let top = false;
let constraints = random_constraints(1); // Generate 'n' random constraints
let transactions = random_constraints(1); // Generate 'n' random constraints

// Create a random `ConstraintsMessage`
let message = ConstraintsMessage { pubkey, slot, top, constraints };
let message = ConstraintsMessage { pubkey, slot, top, transactions };

// Compute tree hash root
let digest = SignableBLS::digest(&message);
Expand All @@ -134,10 +134,10 @@ mod tests {
let pubkey = BlsPublicKey::default();
let slot = random_u64(&mut rng);
let top = false;
let constraints = random_constraints(2); // Generate 'n' random constraints
let transactions = random_constraints(2); // Generate 'n' random constraints

// Create a random `ConstraintsMessage`
let message = ConstraintsMessage { pubkey, slot, top, constraints };
let message = ConstraintsMessage { pubkey, slot, top, transactions };

// Serialize the `ConstraintsMessage` to JSON
let json = serde_json::to_string(&message).unwrap();
Expand Down
27 changes: 26 additions & 1 deletion bolt-sidecar/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use std::{
sync::{atomic::AtomicU64, Arc},
};

use alloy::primitives::{Address, U256};
use alloy::{
primitives::{Address, U256},
signers::k256::sha2::{Digest, Sha256},
};
use ethereum_consensus::{
crypto::KzgCommitment,
deneb::{
Expand Down Expand Up @@ -36,6 +39,8 @@ pub mod constraint;
pub use constraint::{BatchedSignedConstraints, ConstraintsMessage, SignedConstraints};
use tracing::{error, info};

use crate::crypto::SignableBLS;

/// An alias for a Beacon Chain slot number
pub type Slot = u64;

Expand Down Expand Up @@ -430,6 +435,16 @@ pub struct DelegationMessage {
pub delegatee_pubkey: BlsPublicKey,
}

impl SignableBLS for DelegationMessage {
fn digest(&self) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(&self.validator_pubkey.to_vec());
hasher.update(&self.delegatee_pubkey.to_vec());

hasher.finalize().into()
}
}

#[derive(Debug, Clone, Serialize)]
pub struct SignedRevocation {
pub message: RevocationMessage,
Expand All @@ -441,3 +456,13 @@ pub struct RevocationMessage {
pub validator_pubkey: BlsPublicKey,
pub delegatee_pubkey: BlsPublicKey,
}

impl SignableBLS for RevocationMessage {
fn digest(&self) -> [u8; 32] {
let mut hasher = Sha256::new();
hasher.update(&self.validator_pubkey.to_vec());
hasher.update(&self.delegatee_pubkey.to_vec());

hasher.finalize().into()
}
}
109 changes: 107 additions & 2 deletions bolt-sidecar/src/test_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,18 @@ use alloy::{
};
use alloy_node_bindings::{Anvil, AnvilInstance};
use blst::min_pk::SecretKey;
use ethereum_consensus::crypto::{PublicKey, Signature};
use rand::Rng;
use reth_primitives::PooledTransactionsElement;
use secp256k1::Message;
use tracing::warn;

use crate::{
crypto::{ecdsa::SignableECDSA, SignableBLS},
primitives::{CommitmentRequest, FullTransaction, InclusionRequest},
crypto::{bls::Signer as BlsSigner, ecdsa::SignableECDSA, SignableBLS, SignerBLS},
primitives::{
CommitmentRequest, ConstraintsMessage, DelegationMessage, FullTransaction,
InclusionRequest, RevocationMessage, SignedConstraints, SignedDelegation, SignedRevocation,
},
Config,
};

Expand Down Expand Up @@ -170,3 +175,103 @@ pub(crate) async fn create_signed_commitment_request(

Ok(CommitmentRequest::Inclusion(request))
}

fn random_constraints(count: usize) -> Vec<FullTransaction> {
// Random inclusion request
let json_req = r#"{
"slot": 10,
"txs": [
"0x02f86c870c72dd9d5e883e4d0183408f2382520894d2e2adf7177b7a8afddbc12d1634cf23ea1a71020180c001a08556dcfea479b34675db3fe08e29486fe719c2b22f6b0c1741ecbbdce4575cc6a01cd48009ccafd6b9f1290bbe2ceea268f94101d1d322c787018423ebcbc87ab4",
"0x02f9017b8501a2140cff8303dec685012a05f2008512a05f2000830249f094843669e5220036eddbaca89d8c8b5b82268a0fc580b901040cc7326300000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000022006292538e66f0000000000000000000000005ba38f2c245618e39f6fa067bf1dec304e73ff3c00000000000000000000000092f0ee29e6e1bf0f7c668317ada78f5774a6cb7f000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000003fac6482aee49bf58515be2d3fb58378a8497cc9000000000000000000000000c6cc140787b02ae479a10e41169607000c0d44f6c080a00cf74c45dbe9ee1fb923118ec5ce9db8f88cd651196ed3f9d4f8f2a65827e611a04a6bc1d49a7e18b7c92e8f3614cae116b1832ceb311c81d54b2c87de1545f68f",
"0x02f8708501a2140cff82012f800782520894b6c402298fcb88039bbfde70f5ace791f18cfac88707131d70870dc880c080a03aab1b17ecf28f85de43c7733611759b87d25ba885babacb6b4c625d715415eea03fb52cb7744ccb885906e42f6b9cf82e74b47a4b4b4072af2aa52a8dc472236e"
]
}"#;

let req: InclusionRequest = serde_json::from_str(json_req).unwrap();

req.txs.iter().cloned().take(count).collect()
}

#[tokio::test]
async fn generate_test_data() {
let sk = test_bls_secret_key();
let pk = sk.sk_to_pk();
let signer = BlsSigner::new(sk);

println!("Validator Public Key: {}", hex::encode(pk.to_bytes()));

// Generate a delegatee's BLS secret key and public key
let delegatee_ikm: [u8; 32] = rand::thread_rng().gen();
let delegatee_sk =
SecretKey::key_gen(&delegatee_ikm, &[]).expect("Failed to generate delegatee secret key");
let delegatee_pk = delegatee_sk.sk_to_pk();

// Prepare a Delegation message
let delegation_msg = DelegationMessage {
validator_pubkey: PublicKey::try_from(pk.to_bytes().as_slice())
.expect("Failed to convert validator public key"),
delegatee_pubkey: PublicKey::try_from(delegatee_pk.to_bytes().as_slice())
.expect("Failed to convert delegatee public key"),
};

let digest = SignableBLS::digest(&delegation_msg);

// Sign the Delegation message
let delegation_signature = SignerBLS::sign(&signer, &digest).await.unwrap();

// Create SignedDelegation
let signed_delegation = SignedDelegation {
message: delegation_msg,
signature: Signature::try_from(delegation_signature.as_ref())
.expect("Failed to convert delegation signature"),
};

// Output SignedDelegation
println!("{}", serde_json::to_string_pretty(&signed_delegation).unwrap());

// Prepare a revocation message
let revocation_msg = RevocationMessage {
validator_pubkey: PublicKey::try_from(pk.to_bytes().as_slice())
.expect("Failed to convert validator public key"),
delegatee_pubkey: PublicKey::try_from(delegatee_pk.to_bytes().as_slice())
.expect("Failed to convert delegatee public key"),
};

let digest = SignableBLS::digest(&revocation_msg);

// Sign the Revocation message
let revocation_signature = SignerBLS::sign(&signer, &digest).await.unwrap();

// Create SignedRevocation
let signed_revocation = SignedRevocation {
message: revocation_msg,
signature: Signature::try_from(revocation_signature.as_ref())
.expect("Failed to convert revocation signature"),
};

// Output SignedRevocation
println!("{}", serde_json::to_string_pretty(&signed_revocation).unwrap());

let transactions = random_constraints(1);

// Prepare a ConstraintsMessage
let constraints_msg = ConstraintsMessage {
pubkey: PublicKey::try_from(pk.to_bytes().as_slice())
.expect("Failed to convert validator public key"),
slot: 32,
top: true,
transactions,
};

let digest = SignableBLS::digest(&constraints_msg);

// Sign the ConstraintsMessage
let constraints_signature = SignerBLS::sign(&signer, &digest).await.unwrap();

// Create SignedConstraints
let signed_constraints =
SignedConstraints { message: constraints_msg, signature: constraints_signature };

// Output SignedConstraints
println!("{}", serde_json::to_string_pretty(&signed_constraints).unwrap());
}
Loading