Skip to content

Commit

Permalink
feat: add custom signing domain (Commit-Boost#106)
Browse files Browse the repository at this point in the history
* add custom signing domain

* fix  tests

* ecsda domain

* clippy

* fix
  • Loading branch information
ltitanb authored Sep 4, 2024
1 parent 19b6dc0 commit 45ce8f1
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 67 deletions.
8 changes: 5 additions & 3 deletions benches/pbs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ use alloy::{primitives::B256, rpc::types::beacon::BlsPublicKey};
use cb_common::{
config::RelayConfig,
pbs::{GetHeaderResponse, RelayClient, RelayEntry},
signer::{BlsSecretKey, BlsSigner},
signer::BlsSecretKey,
types::Chain,
utils::blst_pubkey_to_alloy,
};
use cb_tests::mock_relay::{start_mock_relay_service, MockRelayState};
use comfy_table::Table;
Expand Down Expand Up @@ -137,9 +138,10 @@ const MOCK_RELAY_SECRET: [u8; 32] = [
152, 98, 59, 240, 181, 131, 47, 1, 180, 255, 245,
];
async fn start_mock_relay(chain: Chain, relay_config: RelayConfig) {
let signer = BlsSigner::Local(BlsSecretKey::key_gen(&MOCK_RELAY_SECRET, &[]).unwrap());
let signer = BlsSecretKey::key_gen(&MOCK_RELAY_SECRET, &[]).unwrap();
let pubkey: BlsPublicKey = blst_pubkey_to_alloy(&signer.sk_to_pk());

assert_eq!(relay_config.entry.pubkey, *signer.pubkey(), "Expected relay pubkey to be 0xb060572f535ba5615b874ebfef757fbe6825352ad257e31d724e57fe25a067a13cfddd0f00cb17bf3a3d2e901a380c17");
assert_eq!(relay_config.entry.pubkey, pubkey, "Expected relay pubkey to be 0xb060572f535ba5615b874ebfef757fbe6825352ad257e31d724e57fe25a067a13cfddd0f00cb17bf3a3d2e901a380c17");

let relay_port = relay_config.entry.url.port().expect("missing port");

Expand Down
6 changes: 4 additions & 2 deletions crates/common/src/commit/request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use crate::{
constants::COMMIT_BOOST_DOMAIN,
error::BlstErrorWrapper,
signature::verify_signed_builder_message,
signature::verify_signed_message,
signer::schemes::{bls::BlsPublicKey, ecdsa::EcdsaPublicKey},
types::Chain,
};
Expand Down Expand Up @@ -54,11 +55,12 @@ pub type SignedProxyDelegationEcdsa = SignedProxyDelegation<EcdsaPublicKey>;

impl<T: PublicKey> SignedProxyDelegation<T> {
pub fn validate(&self, chain: Chain) -> Result<(), BlstErrorWrapper> {
verify_signed_builder_message(
verify_signed_message(
chain,
&self.message.delegator,
&self.message,
&self.signature,
COMMIT_BOOST_DOMAIN,
)
}
}
Expand Down
9 changes: 1 addition & 8 deletions crates/common/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

pub const APPLICATION_BUILDER_DOMAIN: [u8; 4] = [0, 0, 0, 1];
pub const GENESIS_VALIDATORS_ROOT: [u8; 32] = [0; 32];
pub const COMMIT_BOOST_DOMAIN: [u8; 4] = [109, 109, 111, 67];

// MAINNET
pub const MAINNET_FORK_VERSION: [u8; 4] = [0u8; 4];
Expand All @@ -19,14 +20,6 @@ pub const HOLESKY_BUILDER_DOMAIN: [u8; 32] = [
];
pub const HOLESKY_GENESIS_TIME_SECONDS: u64 = 1695902400;

// RHEA DEVNET
pub const RHEA_FORK_VERSION: [u8; 4] = [16, 0, 0, 56];
pub const RHEA_BUILDER_DOMAIN: [u8; 32] = [
0, 0, 0, 1, 11, 65, 190, 76, 219, 52, 209, 131, 221, 220, 165, 57, 131, 55, 98, 109, 205, 207,
175, 23, 32, 193, 32, 45, 59, 149, 248, 78,
];
pub const RHEA_GENESIS_TIME_SECONDS: u64 = 1718117531;

// HELDER
pub const HELDER_FORK_VERSION: [u8; 4] = [16, 0, 0, 0];
pub const HELDER_BUILDER_DOMAIN: [u8; 32] = [
Expand Down
7 changes: 5 additions & 2 deletions crates/common/src/pbs/types/get_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ mod tests {
use alloy::primitives::U256;

use super::GetHeaderResponse;
use crate::{signature::verify_signed_builder_message, types::Chain};
use crate::{
constants::APPLICATION_BUILDER_DOMAIN, signature::verify_signed_message, types::Chain,
};

#[test]
fn test_get_header() {
Expand Down Expand Up @@ -115,11 +117,12 @@ mod tests {

assert_eq!(parsed.message.value(), U256::from(4293912964927787u64));

assert!(verify_signed_builder_message(
assert!(verify_signed_message(
Chain::Holesky,
&parsed.message.pubkey.into(),
&parsed.message,
&parsed.signature,
APPLICATION_BUILDER_DOMAIN
)
.is_ok())
}
Expand Down
42 changes: 30 additions & 12 deletions crates/common/src/signature.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use crate::{
constants::{APPLICATION_BUILDER_DOMAIN, GENESIS_VALIDATORS_ROOT},
constants::{COMMIT_BOOST_DOMAIN, GENESIS_VALIDATORS_ROOT},
error::BlstErrorWrapper,
signer::{schemes::bls::verify_bls_signature, BlsSecretKey},
types::Chain,
Expand All @@ -26,16 +26,15 @@ pub fn compute_signing_root(object_root: [u8; 32], signing_domain: [u8; 32]) ->
signing_data.tree_hash_root().0
}

#[allow(dead_code)]
fn compute_builder_domain(chain: Chain) -> [u8; 32] {
pub fn compute_domain(chain: Chain, domain_mask: [u8; 4]) -> [u8; 32] {
#[derive(Debug, Encode, Decode, TreeHash)]
struct ForkData {
fork_version: [u8; 4],
genesis_validators_root: [u8; 32],
}

let mut domain = [0u8; 32];
domain[..4].copy_from_slice(&APPLICATION_BUILDER_DOMAIN);
domain[..4].copy_from_slice(&domain_mask);

let fork_version = chain.fork_version();
let fd = ForkData { fork_version, genesis_validators_root: GENESIS_VALIDATORS_ROOT };
Expand All @@ -46,13 +45,14 @@ fn compute_builder_domain(chain: Chain) -> [u8; 32] {
domain
}

pub fn verify_signed_builder_message<T: TreeHash>(
pub fn verify_signed_message<T: TreeHash>(
chain: Chain,
pubkey: &BlsPublicKey,
msg: &T,
signature: &BlsSignature,
domain_mask: [u8; 4],
) -> Result<(), BlstErrorWrapper> {
let domain = chain.builder_domain();
let domain = compute_domain(chain, domain_mask);
let signing_root = compute_signing_root(msg.tree_hash_root().0, domain);

verify_bls_signature(pubkey, &signing_root, signature)
Expand All @@ -76,17 +76,35 @@ pub fn sign_builder_root(
sign_message(secret_key, &signing_root)
}

pub fn sign_commit_boost_root(
chain: Chain,
secret_key: &BlsSecretKey,
object_root: [u8; 32],
) -> BlsSignature {
let domain = compute_domain(chain, COMMIT_BOOST_DOMAIN);
let signing_root = compute_signing_root(object_root, domain);
sign_message(secret_key, &signing_root)
}

#[cfg(test)]
mod tests {

use super::compute_builder_domain;
use crate::types::Chain;
use super::compute_domain;
use crate::{constants::APPLICATION_BUILDER_DOMAIN, types::Chain};

#[test]
fn test_builder_domains() {
assert_eq!(compute_builder_domain(Chain::Mainnet), Chain::Mainnet.builder_domain());
assert_eq!(compute_builder_domain(Chain::Holesky), Chain::Holesky.builder_domain());
assert_eq!(compute_builder_domain(Chain::Rhea), Chain::Rhea.builder_domain());
assert_eq!(compute_builder_domain(Chain::Helder), Chain::Helder.builder_domain());
assert_eq!(
compute_domain(Chain::Mainnet, APPLICATION_BUILDER_DOMAIN),
Chain::Mainnet.builder_domain()
);
assert_eq!(
compute_domain(Chain::Holesky, APPLICATION_BUILDER_DOMAIN),
Chain::Holesky.builder_domain()
);
assert_eq!(
compute_domain(Chain::Helder, APPLICATION_BUILDER_DOMAIN),
Chain::Helder.builder_domain()
);
}
}
6 changes: 3 additions & 3 deletions crates/common/src/signer/schemes/bls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use tree_hash::TreeHash;
use tree_hash_derive::TreeHash;

use crate::{
error::BlstErrorWrapper, signature::sign_builder_root, types::Chain,
error::BlstErrorWrapper, signature::sign_commit_boost_root, types::Chain,
utils::blst_pubkey_to_alloy,
};

Expand Down Expand Up @@ -61,7 +61,7 @@ impl BlsSigner {

pub async fn sign(&self, chain: Chain, object_root: [u8; 32]) -> BlsSignature {
match self {
BlsSigner::Local(sk) => sign_builder_root(chain, sk, object_root),
BlsSigner::Local(sk) => sign_commit_boost_root(chain, sk, object_root),
}
}

Expand All @@ -70,7 +70,7 @@ impl BlsSigner {
}
}

fn random_secret() -> BlsSecretKey {
pub fn random_secret() -> BlsSecretKey {
use rand::RngCore;

let mut rng = rand::thread_rng();
Expand Down
8 changes: 6 additions & 2 deletions crates/common/src/signer/schemes/ecdsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ use ssz_types::{
};
use tree_hash::TreeHash;

use crate::{signature::compute_signing_root, types::Chain};
use crate::{
constants::COMMIT_BOOST_DOMAIN,
signature::{compute_domain, compute_signing_root},
types::Chain,
};

pub type EcdsaSecretKey = k256::ecdsa::SigningKey;

Expand Down Expand Up @@ -205,7 +209,7 @@ impl EcdsaSigner {
pub async fn sign(&self, chain: Chain, object_root: [u8; 32]) -> EcdsaSignature {
match self {
EcdsaSigner::Local(sk) => {
let domain = chain.builder_domain();
let domain = compute_domain(chain, COMMIT_BOOST_DOMAIN);
let signing_root = compute_signing_root(object_root, domain);
k256::ecdsa::signature::Signer::<EcdsaSignatureInner>::sign(sk, &signing_root)
.into()
Expand Down
6 changes: 1 addition & 5 deletions crates/common/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ use crate::constants::{
HELDER_BUILDER_DOMAIN, HELDER_FORK_VERSION, HELDER_GENESIS_TIME_SECONDS,
HOLESKY_BUILDER_DOMAIN, HOLESKY_FORK_VERSION, HOLESKY_GENESIS_TIME_SECONDS,
MAINNET_BUILDER_DOMAIN, MAINNET_FORK_VERSION, MAINNET_GENESIS_TIME_SECONDS,
RHEA_BUILDER_DOMAIN, RHEA_FORK_VERSION, RHEA_GENESIS_TIME_SECONDS,
};

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum Chain {
Mainnet,
Holesky,
Rhea,

Helder,
}

Expand All @@ -21,7 +20,6 @@ impl Chain {
match self {
Chain::Mainnet => MAINNET_BUILDER_DOMAIN,
Chain::Holesky => HOLESKY_BUILDER_DOMAIN,
Chain::Rhea => RHEA_BUILDER_DOMAIN,
Chain::Helder => HELDER_BUILDER_DOMAIN,
}
}
Expand All @@ -30,7 +28,6 @@ impl Chain {
match self {
Chain::Mainnet => MAINNET_FORK_VERSION,
Chain::Holesky => HOLESKY_FORK_VERSION,
Chain::Rhea => RHEA_FORK_VERSION,
Chain::Helder => HELDER_FORK_VERSION,
}
}
Expand All @@ -39,7 +36,6 @@ impl Chain {
match self {
Chain::Mainnet => MAINNET_GENESIS_TIME_SECONDS,
Chain::Holesky => HOLESKY_GENESIS_TIME_SECONDS,
Chain::Rhea => RHEA_GENESIS_TIME_SECONDS,
Chain::Helder => HELDER_GENESIS_TIME_SECONDS,
}
}
Expand Down
6 changes: 4 additions & 2 deletions crates/pbs/src/mev_boost/get_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ use alloy::{
use axum::http::{HeaderMap, HeaderValue};
use cb_common::{
config::PbsConfig,
constants::APPLICATION_BUILDER_DOMAIN,
pbs::{
error::{PbsError, ValidationError},
GetHeaderParams, GetHeaderResponse, RelayClient, SignedExecutionPayloadHeader,
EMPTY_TX_ROOT_HASH, HEADER_SLOT_UUID_KEY, HEADER_START_TIME_UNIX_MS,
},
signature::verify_signed_builder_message,
signature::verify_signed_message,
types::Chain,
utils::{get_user_agent_with_version, ms_into_slot, utcnow_ms},
};
Expand Down Expand Up @@ -318,11 +319,12 @@ fn validate_header(
}

if !skip_sig_verify {
verify_signed_builder_message(
verify_signed_message(
chain,
&received_relay_pubkey,
&signed_header.message,
&signed_header.signature,
APPLICATION_BUILDER_DOMAIN,
)
.map_err(ValidationError::Sigverify)?;
}
Expand Down
27 changes: 17 additions & 10 deletions crates/signer/src/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,14 @@ mod tests {

use super::*;

const CHAIN: Chain = Chain::Holesky;

lazy_static! {
static ref CHAIN: Chain = Chain::Holesky;
static ref MODULE_ID: ModuleId = ModuleId("SAMPLE_MODULE".to_string());
}

fn init_signing_manager() -> (SigningManager, BlsPublicKey) {
let mut signing_manager = SigningManager::new(*CHAIN);
let mut signing_manager = SigningManager::new(CHAIN);

let consensus_signer = ConsensusSigner::new_random();
let consensus_pk = consensus_signer.pubkey();
Expand All @@ -236,7 +237,10 @@ mod tests {
}

mod test_proxy_bls {
use cb_common::signer::schemes::bls::verify_bls_signature;
use cb_common::{
constants::COMMIT_BOOST_DOMAIN, signature::compute_domain,
signer::schemes::bls::verify_bls_signature,
};

use super::*;

Expand All @@ -249,7 +253,7 @@ mod tests {
.await
.unwrap();

let validation_result = signed_delegation.validate(*CHAIN);
let validation_result = signed_delegation.validate(CHAIN);

assert!(
validation_result.is_ok(),
Expand All @@ -274,7 +278,7 @@ mod tests {
let m = &mut signed_delegation.signature.0[0];
(*m, _) = m.overflowing_add(1);

let validation_result = signed_delegation.validate(*CHAIN);
let validation_result = signed_delegation.validate(CHAIN);

assert!(validation_result.is_err(), "Tampered proxy key must be invalid.");
}
Expand All @@ -298,7 +302,7 @@ mod tests {
.unwrap();

// Verify signature
let domain = CHAIN.builder_domain();
let domain = compute_domain(CHAIN, COMMIT_BOOST_DOMAIN);
let signing_root = compute_signing_root(data_root_bytes.tree_hash_root().0, domain);

let validation_result = verify_bls_signature(&proxy_pk, &signing_root, &sig);
Expand All @@ -311,7 +315,10 @@ mod tests {
}

mod test_proxy_ecdsa {
use cb_common::signer::schemes::ecdsa::verify_ecdsa_signature;
use cb_common::{
constants::COMMIT_BOOST_DOMAIN, signature::compute_domain,
signer::schemes::ecdsa::verify_ecdsa_signature,
};

use super::*;

Expand All @@ -324,7 +331,7 @@ mod tests {
.await
.unwrap();

let validation_result = signed_delegation.validate(*CHAIN);
let validation_result = signed_delegation.validate(CHAIN);

assert!(
validation_result.is_ok(),
Expand All @@ -349,7 +356,7 @@ mod tests {
let m = &mut signed_delegation.signature.0[0];
(*m, _) = m.overflowing_add(1);

let validation_result = signed_delegation.validate(*CHAIN);
let validation_result = signed_delegation.validate(CHAIN);

assert!(validation_result.is_err(), "Tampered proxy key must be invalid.");
}
Expand All @@ -373,7 +380,7 @@ mod tests {
.unwrap();

// Verify signature
let domain = CHAIN.builder_domain();
let domain = compute_domain(CHAIN, COMMIT_BOOST_DOMAIN);
let signing_root = compute_signing_root(data_root_bytes.tree_hash_root().0, domain);

let validation_result = verify_ecdsa_signature(&proxy_pk, &signing_root, &sig);
Expand Down
Loading

0 comments on commit 45ce8f1

Please sign in to comment.