Skip to content

feat(core): port core/eth2signeddata#501

Open
varex83agent wants to merge 2 commits into
mainfrom
bohdan/port-eth2signeddata
Open

feat(core): port core/eth2signeddata#501
varex83agent wants to merge 2 commits into
mainfrom
bohdan/port-eth2signeddata

Conversation

@varex83agent

Copy link
Copy Markdown
Collaborator

Summary

Ports core/eth2signeddata from Charon (charon/core/eth2signeddata.go, v1.7.1), closing #438.

The signed-data types already existed in crates/core/src/signeddata.rs (the SignedData trait: 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. The core::types TODO and the sigagg::new_verifier no-op both pointed at this gap.

What's added

New module crates/core/src/eth2signeddata.rs:

  • trait Eth2SignedData: SignedData — adds domain_name() and async epoch(client).
  • verify_eth2_signed_data(client, data, pubkey) — mirrors Go's VerifyEth2SignedData: resolve epoch → message_root()signing::verify(domain, epoch, root, sig, pubkey).
  • Eth2SignedData impls 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's data.(core.Eth2SignedData) type assertion.

Supporting changes:

  • sigagg::new_verifier now takes Arc<EthBeaconNodeApiClient> and verifies via verify_eth2_signed_data (was a no-op placeholder; no production callers yet). New SigAggError variants mirror Go's NewVerifier error paths (invalid eth2 signed data, pubkey from core, aggregate signature verification failed).
  • versioned::SignedProposalBlock::slot() helper (mirrors the existing graffiti()/signature()), needed for the proposal's signing epoch.

Tests

TestVerifyEth2SignedData is translated directly: for each of the 10 payload types the Go table exercises, load the existing golden JSON fixture, resolve epoch + message root against a BeaconMock, BLS-sign the signing-domain data root, inject the signature, and assert verification succeeds. Plus wrong-pubkey / zero-signature rejection, the as_eth2_signed_data view, and a sigagg test that new_verifier rejects 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

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>
Comment thread crates/core/src/eth2signeddata.rs
Comment thread crates/core/src/sigagg.rs Outdated
Comment thread crates/core/src/sigagg.rs
Comment thread crates/core/src/eth2signeddata.rs Outdated
Comment thread crates/core/src/lib.rs
varex83agent added a commit that referenced this pull request Jun 26, 2026
- eth2signeddata: check cheap message_root/signature before the
  (potentially client-bound) epoch lookup in verify_eth2_signed_data
- eth2signeddata: add verification tests for the non-versioned
  Attestation and SignedAggregateAndProof payloads
- sigagg: SigAggError::PubkeyFromCore now carries the inner conversion
  error instead of discarding it
- sigagg: SigAggError::VerificationFailed uses #[from] for Eth2SignedDataError
- types: drop stale "todo: add Eth2SignedData type" comment

Co-Authored-By: Bohdan Ohorodnii <varex83@nethermind.io>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- eth2signeddata: check cheap message_root/signature before the
  (potentially client-bound) epoch lookup in verify_eth2_signed_data
- eth2signeddata: add verification tests for the non-versioned
  Attestation and SignedAggregateAndProof payloads
- sigagg: SigAggError::PubkeyFromCore now carries the inner conversion
  error instead of discarding it
- sigagg: SigAggError::VerificationFailed uses #[from] for Eth2SignedDataError
- types: drop stale "todo: add Eth2SignedData type" comment

Co-Authored-By: Bohdan Ohorodnii <varex83@nethermind.io>
@varex83agent varex83agent force-pushed the bohdan/port-eth2signeddata branch from 2df0f55 to b8a2dc3 Compare June 26, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement core/eth2signeddata

2 participants