ZeroCopyZeroCopy

Processing the stream

Verify leader signatures, deduplicate valid shreds, recover missing data per FEC set and replay and confirm before acting on the stream.

A shred arrives before replay. It can be incomplete, duplicated or from a slot that is later skipped. A received shred does not establish that a transaction executed, landed or finalized. Your application must replay the reconstructed data and confirm at the commitment it needs before acting. See Terms 6.1.

Verify the leader signature

Shreds are not verified before delivery. Use a Solana Merkle shred verifier to check the Ed25519 signature over the Merkle root against the slot leader's identity. Reject unsigned shreds and shreds with invalid signatures. The source allowlist is a traffic filter, not signature verification.

Deduplicate valid shreds

Deduplicate by (slot, index, shred type), where the type distinguishes data from coding shreds. Keep the first signature-valid copy. An invalid copy must not prevent a later valid copy from being accepted.

Receivers in different metros get their own copies, so deduplicate again when combining streams. Retain keys for the slots your application is still processing, then retire them when those slots leave its processing window.

Recover data shreds

Collect data and coding shreds by slot and fec_set_index. Use the coding header's num_data_shreds, num_coding_shreds and position to recover missing data shreds within each FEC set. Decode entries and transactions from the reconstructed data.

UDP does not retransmit missing datagrams. Some FEC sets can remain incomplete; do not treat partial reconstruction as a complete block.

Replay and confirm

Replay the reconstructed data and verify its outcome. Confirm transactions at the commitment your application requires before acting. A shred's slot or last-in-slot flag is not a commitment result. Handle skipped slots and incomplete data explicitly in your consumer.

Receiver example

This TypeScript example runs with Bun. It binds a UDP socket, reads the common header and suppresses repeated (slot, index, variant) keys while they remain in a bounded cache.

Configure the firewall allowlist first. Set SHREDSTREAM_UDP_PORT to the receiver's assigned UDP port and DEDUPE_ENTRIES to the maximum number of header keys to retain, then run bun receiver.ts. The cache evicts the oldest inserted key when full, so a duplicate can appear again after eviction.

receiver.ts
import { createSocket } from 'node:dgram'

const port = Number(process.env.SHREDSTREAM_UDP_PORT)
const capacity = Number(process.env.DEDUPE_ENTRIES)
if (!Number.isInteger(port) || port < 1 || port > 65535) {
  throw new Error('Set SHREDSTREAM_UDP_PORT to the assigned UDP port')
}
if (!Number.isSafeInteger(capacity) || capacity < 1) {
  throw new Error('Set DEDUPE_ENTRIES to a positive integer')
}

const seen = new Set<string>()
const socket = createSocket('udp4')
socket.on('error', (error) => {
  console.error(error)
  socket.close()
  process.exitCode = 1
})
socket.on('message', (message) => {
  if (message.length < 83 || message.length > 1228) return
  const header = {
    signature: message.subarray(0, 64),
    variant: message[64],
    slot: message.readBigUInt64LE(65),
    index: message.readUInt32LE(73),
    version: message.readUInt16LE(77),
    fecSetIndex: message.readUInt32LE(79),
  }
  const key = `${header.slot}:${header.index}:${header.variant}`
  if (seen.has(key)) return
  if (seen.size === capacity) {
    const oldest = seen.values().next().value
    if (oldest !== undefined) seen.delete(oldest)
  }
  seen.add(key)
  console.log({
    slot: header.slot.toString(),
    index: header.index,
    variant: header.variant,
    version: header.version,
    fecSetIndex: header.fecSetIndex,
  })
})
socket.bind(port)

This is a header-inspection receiver. It does not verify signatures, validate the Merkle body or current shred version, recover FEC sets, replay blocks or confirm transactions. Its duplicate cache records unverified headers; do not use it to select a trusted copy or act on transaction data. A production consumer must verify first, derive the shred type from the variant, and keep the first valid (slot, index, type) copy.

On this page