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
Signature verification needs a public key and an exact message. The public key is the identity of the validator scheduled to lead the shred's slot. The message comes from the shred variant. For current Merkle shreds, the signed value is the Merkle root reconstructed from the shred leaf and proof. Older legacy layouts sign different bytes. Do not verify a 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 to the same root, and the leader signs that root. Their signature bytes therefore agree for a valid set. This permits caching the result for a (slot, fec_set_index, root, leader) tuple after each member's proof has reconstructed that same 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. Compute the 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 the shred data. It does not prove the slot will be accepted, executed successfully, confirmed, or finalized. 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 64.130.40.90 replace signature verification?
- No. Source filtering removes unrelated traffic and helps protect the parser, but it is not proof that a shred was produced by the scheduled validator. Verify the leader signature and Merkle proof before accepting payload bytes into recovery or transaction processing.
- Why can valid shreds in one FEC set share a signature?
- Current Merkle shreds each prove membership in one FEC-set Merkle root, and the leader signs that root. Members therefore carry the same leader signature when they reconstruct the same root. Each member proof still needs validation because the signature alone does not 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.