Verify shred signatures
Authenticate each parsed shred against the validator scheduled to lead its slot.
Before you start
- A sanitized typed shred
- A trusted leader schedule for the correct cluster
Verify two facts
Two inputs determine signature verification: an exact message and public key. Use the identity of the validator scheduled as leader for this shred's slot. Let the shred variant determine its message. Current Merkle forms sign the root produced by that shred's leaf and proof, while older legacy forms sign different bytes. Never apply one hand-selected packet slice across both formats.
Use the parser from the Agave release matching the network. Its Shred::verify method derives the signed data for the parsed variant and checks the 64-byte Ed25519 signature.
rust
use solana_ledger::shred::Shred;use solana_pubkey::Pubkey; fn authenticate(packet: &[u8], expected_leader: &Pubkey) -> Result<Shred, String> { let shred = Shred::new_from_serialized_shred(packet.to_vec()) .map_err(|e| e.to_string())?; shred.sanitize().map_err(|e| e.to_string())?; if shred.verify(expected_leader) == false { return Err("leader signature verification failed".to_owned()); } Ok(shred)}The example is correct only when expected_leader comes from trusted cluster state. Reading a public key from the same packet would prove only internal self-consistency, not leader authority.
Maintain the leader schedule
Build a cache from an RPC node or local cluster state. Associate it with genesis identity, cluster, epoch, schedule source, and refresh time. Resolve slot to leader using the epoch schedule and leader schedule returned for that epoch. Fetch ahead of the current slot so a packet never waits on a synchronous RPC request.
Keep a short overlap around epoch boundaries. A schedule refresh that discards the old epoch too early will fail reordered shreds. Bound the cache and retain enough prior slots for the receiver's reorder and recovery windows.
If the leader key is missing, mark the shred pending in a tightly bounded queue or reject it with a distinct reason. Do not classify a dependency miss as an invalid signature. Never allow unverified payload into the FEC or transaction pipeline because later coding recovery can amplify unauthenticated material.
Understand Merkle signature reuse
Merkle shreds in one FEC set carry proofs toward a shared root, which their leader signs. Signature bytes therefore agree across a valid set. Cache the result with a key containing slot, leader, root, and FEC-set index, only after each member proof reconstructs that root.
Do not skip the member proof because another member verified. The signature authenticates the root; the proof binds this member's erasure shard to that root. Verification needs both steps. A packet with a copied signature and invalid proof must fail.
An optional retransmitter signature is separate from the leader signature. It authenticates the retransmission hop when that variant is used. It does not replace leader authentication. The service source IP is a delivery filter, not a cryptographic identity for the proposed ledger data.
Order validation to control cost
Apply cheap checks first: source IP, datagram truncation, maximum length, recognized variant, common-header fields, expected version, and duplicate key lookup. Then parse and sanitize. Resolve the leader from memory, reconstruct its Merkle root, and verify the signature. Admit the shred to FEC state only after success.
Deduplication before signature verification is safe only for an exact byte-identical packet that previously passed verification and remains in a bounded trusted cache. A new payload for an existing shred ID is a conflict, not a duplicate. Authenticate and retain evidence according to the duplicate policy.
Batch without changing semantics
Ed25519 libraries can batch independent verifications. A batch needs one exact message and public key per signature. For Merkle shreds, compute and validate each proof-derived root first. Limit batch size and flush on a short time budget so waiting for a full batch does not erase the feed's latency value.
Batch verification can report only aggregate failure. On failure, verify members individually if attribution matters. Keep the fallback bounded so an attacker cannot force unlimited repeated work. The scheduled leader and service source filtering reduce exposure but do not eliminate malformed input risk.
Handle forks and finality correctly
A valid leader signature proves that the scheduled validator authenticated this shred data. Later slot acceptance, successful execution, confirmation, and finalization remain separate questions. A signed shred can belong to a skipped or abandoned fork. Consumers must reconcile observations with later confirmed state.
Leader schedule correctness is also cluster-specific. A key from mainnet cannot validate a testnet slot merely because the numeric slot overlaps. Tie every schedule cache and expected shred version to one configured cluster.
Test verification
Use fixtures with a valid shred and leader, one flipped leaf byte, one flipped proof entry, one flipped signature byte, the wrong leader, unknown slot, wrong version, and a valid duplicate. Test epoch transition behavior and leader-cache expiry. For Merkle sets, confirm that members reconstruct one root and that a member moved to a different erasure index fails its proof.
Export shred_signature_total{result="ok|invalid|leader_missing"}, proof failure separately, cache hits, cache age, and leader lookup latency. Sample slot and key details in logs without making them metric labels.
Parameters
When it goes wrong
leader signature verification failed: slot=N
Cause. The packet, proof, signature, or expected leader key does not authenticate.
Fix. Reject it and compare the leader schedule, cluster, version, and sampled packet digest.
leader key unavailable: slot=N
Cause. The schedule cache is stale, incomplete, or tied to the wrong epoch.
Fix. Refresh ahead of epoch boundaries and keep a bounded pending queue separate from invalid signatures.
signature failures spike after upgrade
Cause. The parser derives signed data using a format implementation that does not match the network.
Fix. Roll back to the tested pinned Agave revision and replay captured upgrade fixtures.
Questions
- Does filtering source 203.23.178.228 replace signature verification?
- No. Source filtering removes unrelated traffic and helps protect the parser, but cannot prove which scheduled validator produced a shred. Validate its Merkle proof and leader signature before admitting payload bytes into recovery or transaction processing.
- Why can valid shreds in one FEC set share a signature?
- Each current Merkle shred proves membership in one root for its FEC set, and the leader signs that root. Valid members therefore repeat the signature bytes when reconstructing the same root. Every member proof still needs validation because a signature alone cannot bind arbitrary packet bytes to the root.
- Does a valid leader signature mean the transaction is confirmed?
- No. It proves that the scheduled slot leader authenticated the proposed shred data. The slot can still be skipped, abandoned, or land on a fork that does not survive. Transaction execution can also fail. Reconcile raw observations against confirmed or finalized state later.