From b6b5bf1aaf897886d27ddb6ef0c5cff36cdbea93 Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:08:39 +0000 Subject: [PATCH 1/8] feat: update manifest and binaries (#2) --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 21200ff..9bb8088 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ description = "EIP-7732 — Enshrined Proposer-Builder Separation (ePBS) referen license = "Apache-2.0" repository = "https://github.com/EIPs-CodeLab/EIP-7732" keywords = ["ethereum", "eip-7732", "epbs", "consensus", "builder"] +# PR #1: BLS signing roots and verification wiring [[bin]] name = "epbs-cli" From dee0251abe4aa7ff17d0d2f769d2ff40c6154d95 Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:12:26 +0000 Subject: [PATCH 2/8] feat: update manifest and binaries (#2) --- src/utils/ssz.rs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/utils/ssz.rs b/src/utils/ssz.rs index b557c8b..ef65306 100644 --- a/src/utils/ssz.rs +++ b/src/utils/ssz.rs @@ -10,12 +10,19 @@ pub fn compute_domain_simple(domain_type: [u8; 4]) -> [u8; 32] { domain } -/// Compute a signing root by hashing serialized message bytes plus domain. -/// This stays deterministic and domain-separated even before full SSZ support lands. -pub fn signing_root(message: &T, domain: [u8; 32]) -> [u8; 32] { - let encoded = serde_json::to_vec(message).expect("serialize message for signing"); +/// Minimal hash_tree_root stand-in: SHA256 over JSON serialization of the message. +/// This keeps signing deterministic and domain-separated until full SSZ is wired. +pub fn hash_tree_root_json(value: &T) -> [u8; 32] { + let encoded = serde_json::to_vec(value).expect("serialize message"); let mut hasher = Sha256::new(); hasher.update(encoded); + hasher.finalize().into() +} + +/// signing_root = hash_tree_root(message) mixed with domain. +pub fn signing_root_json(message: &T, domain: [u8; 32]) -> [u8; 32] { + let mut hasher = Sha256::new(); + hasher.update(hash_tree_root_json(message)); hasher.update(domain); hasher.finalize().into() } From ff1eeb8a724e59cf43918a12d0adb7d349ca6e95 Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:21:30 +0000 Subject: [PATCH 3/8] feat: update manifest and binaries (#2) --- src/builder/bid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder/bid.rs b/src/builder/bid.rs index cd0ceff..61d37a4 100644 --- a/src/builder/bid.rs +++ b/src/builder/bid.rs @@ -91,7 +91,7 @@ pub fn construct_bid( }; let domain = ssz::compute_domain_simple(DOMAIN_BEACON_BUILDER); - let signing_root = ssz::signing_root(&message, domain); + let signing_root = ssz::signing_root_json(&message, domain); let signature = sign_fn(&signing_root).map_err(BidError::SigningFailed)?; From b7d38618e3d279d8d21487798f42f076e54b92dd Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:21:50 +0000 Subject: [PATCH 4/8] feat: update manifest and binaries (#2) --- src/builder/envelope.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder/envelope.rs b/src/builder/envelope.rs index c6264fd..047d521 100644 --- a/src/builder/envelope.rs +++ b/src/builder/envelope.rs @@ -84,7 +84,7 @@ pub fn construct_envelope( }; let domain = ssz::compute_domain_simple(DOMAIN_BEACON_BUILDER); - let signing_root = ssz::signing_root(&message, domain); + let signing_root = ssz::signing_root_json(&message, domain); let signature = sign_fn(&signing_root).map_err(EnvelopeError::SigningFailed)?; Ok(SignedExecutionPayloadEnvelope { message, signature }) From 7340aa99b81cf2ad5dcdb39fd72a8f801d307a1d Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:25:08 +0000 Subject: [PATCH 5/8] chore: add JSON-based signing roots helper (PR #2) --- src/beacon_chain/process_payload_bid.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/beacon_chain/process_payload_bid.rs b/src/beacon_chain/process_payload_bid.rs index 324295a..fef6e01 100644 --- a/src/beacon_chain/process_payload_bid.rs +++ b/src/beacon_chain/process_payload_bid.rs @@ -117,7 +117,7 @@ fn verify_builder_signature( .ok_or(PayloadBidError::MissingPubkey(message.builder_index))?; let domain = ssz::compute_domain_simple(DOMAIN_BEACON_BUILDER); - let signing_root = ssz::signing_root(message, domain); + let signing_root = ssz::signing_root_json(message, domain); crypto::bls_verify(&pk, &signing_root, &signed_bid.signature) .map_err(|_| PayloadBidError::InvalidSignature) } From e9f934e2ef052764b9053e29b7b7b4e9a9beb6bd Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:25:46 +0000 Subject: [PATCH 6/8] chore: add JSON-based signing roots helper (PR #2) --- src/beacon_chain/process_payload_attestation.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/beacon_chain/process_payload_attestation.rs b/src/beacon_chain/process_payload_attestation.rs index e3ef2b8..4044397 100644 --- a/src/beacon_chain/process_payload_attestation.rs +++ b/src/beacon_chain/process_payload_attestation.rs @@ -104,7 +104,7 @@ fn verify_aggregate_ptc_signature( pubkeys: &[BLSPubkey], ) -> Result<(), PayloadAttestationError> { let domain = ssz::compute_domain_simple(DOMAIN_PTC_ATTESTER); - let signing_root = ssz::signing_root(data, domain); + let signing_root = ssz::signing_root_json(data, domain); crypto::bls_verify_aggregate(pubkeys, &signing_root, signature) .map_err(|_| PayloadAttestationError::InvalidSignature) } From ce38b25a23a402e21083a208f544111b02134feb Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:26:04 +0000 Subject: [PATCH 7/8] chore: add JSON-based signing roots helper (PR #2) --- tests/unit/beacon_chain_test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/beacon_chain_test.rs b/tests/unit/beacon_chain_test.rs index 8049e99..0409063 100644 --- a/tests/unit/beacon_chain_test.rs +++ b/tests/unit/beacon_chain_test.rs @@ -99,7 +99,7 @@ fn make_valid_bid(slot: Slot) -> SignedExecutionPayloadBid { blob_kzg_commitments: vec![], }; let domain = ssz::compute_domain_simple(DOMAIN_BEACON_BUILDER); - let signing_root = ssz::signing_root(&message, domain); + let signing_root = ssz::signing_root_json(&message, domain); SignedExecutionPayloadBid { message, signature: crypto::bls_sign(&test_secret_key(), &signing_root), @@ -214,7 +214,7 @@ fn valid_ptc_attestation_accepted() { blob_data_available: true, }; let domain = ssz::compute_domain_simple(DOMAIN_PTC_ATTESTER); - let signing_root = ssz::signing_root(&data, domain); + let signing_root = ssz::signing_root_json(&data, domain); let signature = aggregate_signature(&aggregation_bits, &signing_root); let att = PayloadAttestation { aggregation_bits, From 9acf056c875abfc1beb8734d5d32cd8710720387 Mon Sep 17 00:00:00 2001 From: zacksfF Date: Sat, 21 Mar 2026 11:36:25 +0000 Subject: [PATCH 8/8] chore: rerun CI after signing_root_json fix