feat(core): port core/eth2signeddata#501
Open
varex83agent wants to merge 1 commit into
Open
Conversation
Add the Eth2SignedData layer over the existing signed-data types: the signing DomainName and signing Epoch for each beacon-chain signed payload, plus verify_eth2_signed_data which resolves the upstream domain and runs BLS verification. Wires sigagg's new_verifier to it, replacing the no-op placeholder. Ports charon/core/eth2signeddata.go (v1.7.1). Co-Authored-By: Bohdan Ohorodnii <35969035+varex83@users.noreply.github.com>
iamquang95
approved these changes
Jun 26, 2026
Comment on lines
+466
to
+477
| fn as_eth2_signed_data_views_typed_payloads() { | ||
| let randao: SignedRandao = load("TestJSONSerialisation_SignedRandao.json.golden"); | ||
|
|
||
| // A typed payload is viewable as Eth2SignedData... | ||
| let boxed: Box<dyn SignedData> = Box::new(randao); | ||
| assert!(as_eth2_signed_data(boxed.as_ref()).is_some()); | ||
|
|
||
| // ...while a raw signature is not. | ||
| let sig: Box<dyn SignedData> = Box::new([0u8; SIGNATURE_LENGTH] as Signature); | ||
| assert!(as_eth2_signed_data(sig.as_ref()).is_none()); | ||
| } | ||
| } |
Collaborator
There was a problem hiding this comment.
better have test for all types
| let owned: Box<dyn SignedData> = dyn_clone::clone_box(data); | ||
|
|
||
| Box::pin(async move { | ||
| let tbls_pubkey = tbls_pubkey.map_err(|_| SigAggError::PubkeyFromCore)?; |
Collaborator
There was a problem hiding this comment.
nit: don't discard the inner error
| #[error("aggregate signature verification failed: {source}")] | ||
| VerificationFailed { | ||
| /// The underlying error. | ||
| #[source] |
| data: &dyn Eth2SignedData, | ||
| pubkey: &PublicKey, | ||
| ) -> Result<(), Eth2SignedDataError> { | ||
| let epoch = data.epoch(client).await?; |
Collaborator
There was a problem hiding this comment.
nit: this check is more expensive than
let sig_root = data.message_root()?;
let signature = data.signature()?;
Do it later
|
|
||
| /// Eth2 signed-data verification. | ||
| pub mod eth2signeddata; | ||
|
|
Collaborator
There was a problem hiding this comment.
Stale // todo: add Eth2SignedData type comment in crates/core/src/types.rs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ports
core/eth2signeddatafrom Charon (charon/core/eth2signeddata.go, v1.7.1), closing #438.The signed-data types already existed in
crates/core/src/signeddata.rs(theSignedDatatrait:signature/set_signature/message_root). What was missing is the eth2 verification layer — the per-type signing domain and signing epoch, and the function that ties them to upstream domain resolution + BLS verification. Thecore::typesTODO and thesigagg::new_verifierno-op both pointed at this gap.What's added
New module
crates/core/src/eth2signeddata.rs:trait Eth2SignedData: SignedData— addsdomain_name()and asyncepoch(client).verify_eth2_signed_data(client, data, pubkey)— mirrors Go'sVerifyEth2SignedData: resolve epoch →message_root()→signing::verify(domain, epoch, root, sig, pubkey).Eth2SignedDataimpls for all 12 payloads, matching the Go domain/epoch mapping exactly (proposer, attester, voluntary-exit, application-builder@epoch-0, randao, selection-proof, aggregate-and-proof, sync-committee, contribution-and-proof, sync-committee-selection-proof — versioned and non-versioned variants).as_eth2_signed_data(&dyn SignedData) -> Option<&dyn Eth2SignedData>— the Rust equivalent of Go'sdata.(core.Eth2SignedData)type assertion.Supporting changes:
sigagg::new_verifiernow takesArc<EthBeaconNodeApiClient>and verifies viaverify_eth2_signed_data(was a no-op placeholder; no production callers yet). NewSigAggErrorvariants mirror Go'sNewVerifiererror paths (invalid eth2 signed data,pubkey from core,aggregate signature verification failed).versioned::SignedProposalBlock::slot()helper (mirrors the existinggraffiti()/signature()), needed for the proposal's signing epoch.Tests
TestVerifyEth2SignedDatais translated directly: for each of the 10 payload types the Go table exercises, load the existing golden JSON fixture, resolve epoch + message root against aBeaconMock, BLS-sign the signing-domain data root, inject the signature, and assert verification succeeds. Plus wrong-pubkey / zero-signature rejection, theas_eth2_signed_dataview, and a sigagg test thatnew_verifierrejects non-eth2 data.Gates
cargo +nightly fmt --all --check✅cargo clippy -p pluto-core -p pluto-eth2api --all-targets --all-features -- -D warnings✅cargo test -p pluto-core(559) /cargo test -p pluto-eth2api(114) ✅Closes #438