Skip to content

Commit

Permalink
feat: signed message actions (with runtime check)
Browse files Browse the repository at this point in the history
  • Loading branch information
merklefruit committed Oct 10, 2024
1 parent ac83904 commit 601f8d6
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 23 deletions.
4 changes: 2 additions & 2 deletions bolt-sidecar/src/primitives/constraint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub type BatchedSignedConstraints = Vec<SignedConstraints>;
/// A container for a list of constraints and the signature of the proposer sidecar.
///
/// Reference: https://chainbound.github.io/bolt-docs/api/builder#constraints
#[derive(Serialize, Default, Debug, Clone, PartialEq)]
#[derive(Serialize, Default, Debug, Clone, PartialEq, Eq)]
pub struct SignedConstraints {
/// The constraints that need to be signed.
pub message: ConstraintsMessage,
Expand All @@ -27,7 +27,7 @@ pub struct SignedConstraints {
/// A message that contains the constraints that need to be signed by the proposer sidecar.
///
/// Reference: https://chainbound.github.io/bolt-docs/api/builder#constraints
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default)]
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Default, Eq)]
pub struct ConstraintsMessage {
/// The validator pubkey of the proposer sidecar.
pub pubkey: BlsPublicKey,
Expand Down
37 changes: 33 additions & 4 deletions bolt-sidecar/src/primitives/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -452,43 +452,72 @@ where
#[error("Invalid signature")]
pub struct SignatureError;

#[derive(Debug, Clone, Serialize)]
/// Event types that can be emitted by the validator pubkey to
/// signal some action on the Bolt protocol.
#[derive(Debug, Clone, Copy)]
#[repr(u8)]
enum SignedMessageAction {
/// Signal delegation of a validator pubkey to a delegatee pubkey.
Delegation,
/// Signal revocation of a previously delegated pubkey.
Revocation,
}

#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct SignedDelegation {
pub message: DelegationMessage,
pub signature: BlsSignature,
}

#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct DelegationMessage {
action: u8,
pub validator_pubkey: BlsPublicKey,
pub delegatee_pubkey: BlsPublicKey,
}

impl DelegationMessage {
/// Create a new delegation message.
pub fn new(validator_pubkey: BlsPublicKey, delegatee_pubkey: BlsPublicKey) -> Self {
Self { action: SignedMessageAction::Delegation as u8, validator_pubkey, delegatee_pubkey }
}
}

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

hasher.finalize().into()
}
}

#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct SignedRevocation {
pub message: RevocationMessage,
pub signature: BlsSignature,
}

#[derive(Debug, Clone, Serialize)]
#[derive(Debug, Clone, Serialize, PartialEq, Eq)]
pub struct RevocationMessage {
action: u8,
pub validator_pubkey: BlsPublicKey,
pub delegatee_pubkey: BlsPublicKey,
}

impl RevocationMessage {
/// Create a new revocation message.
pub fn new(validator_pubkey: BlsPublicKey, delegatee_pubkey: BlsPublicKey) -> Self {
Self { action: SignedMessageAction::Revocation as u8, validator_pubkey, delegatee_pubkey }
}
}

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

Expand Down
41 changes: 24 additions & 17 deletions bolt-sidecar/src/test_util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,16 @@ use secp256k1::Message;
use tracing::warn;

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

/// The URL of the test execution client HTTP API.
Expand Down Expand Up @@ -187,8 +191,8 @@ fn random_constraints(count: usize) -> Vec<FullTransaction> {
}

#[tokio::test]
async fn generate_test_data() {
let signer = BlsSigner::random();
async fn generate_test_data_kurtosis() {
let signer = BlsSigner::new(random_bls_secret(), ChainConfig::kurtosis(0, 0));
let pk = signer.pubkey();

println!("Validator Public Key: {}", hex::encode(pk.as_ref()));
Expand All @@ -200,33 +204,36 @@ async fn generate_test_data() {
let delegatee_pk = delegatee_sk.sk_to_pk();

// Prepare a Delegation message
let delegation_msg = DelegationMessage {
validator_pubkey: pk.clone(),
delegatee_pubkey: PublicKey::try_from(delegatee_pk.to_bytes().as_slice())
let delegation_msg = DelegationMessage::new(
pk.clone(),
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 = signer.sign_commit_boost_root(digest).unwrap();
let blst_sig = blst::min_pk::Signature::from_bytes(delegation_signature.as_ref())
.expect("Failed to convert delegation signature");
let consensus_sig = Signature::try_from(delegation_signature.as_ref())
.expect("Failed to convert delegation signature");

// Sanity check: verify the signature
assert!(signer.verify_commit_boost_root(digest, &blst_sig).is_ok());

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

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

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

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

Expand Down

0 comments on commit 601f8d6

Please sign in to comment.