Skip to content
fundamentals

What is inside a Solana shred?

A Solana shred is a packet-sized ledger fragment with three logical regions: a common header, a data or coding header, and type-specific content. The common header identifies the slot, index, format, version, and FEC set. Data shreds carry serialized entries. Coding shreds carry Reed-Solomon parity. Merkle variants also carry an authentication proof.

protocol desk · updated 2026-08-31

3 regions in one packet

A shred has three logical regions even when a decoder represents it as one byte array. The common header comes first. A type-specific header follows. The remaining bytes hold ledger data, parity data, padding, and authentication material according to the selected variant.

The distinction is operational. The common header tells a receiver where the packet belongs. The second header tells the receiver how to interpret it. The tail supplies either source bytes or recovery bytes. Parsing those regions in the wrong order produces plausible integers from the wrong offsets, which is more dangerous than an immediate parse failure.

Current Solana implementations use an 83-byte common header. A data shred has five more header bytes, making an 88-byte prefix. A coding shred has six more, making an 89-byte prefix. Those numbers describe the current serialization. Production decoders should still dispatch on the variant and keep layout constants beside the implementation version they support.

The 83-byte common header

64 signature bytes dominate the common header. The remaining 19 bytes encode a one-byte shred variant, an eight-byte slot, a four-byte index, a two-byte shred version, and a four-byte FEC set index. Integer fields use the protocol's serialized representation, not decimal text or network-order assumptions.

Each field answers a different admission question. The variant selects the parser. The slot selects the leader schedule and the assembly bucket. The index supplies position within the type's sequence. The version separates packets belonging to the intended cluster. The FEC set index groups shards that can participate in the same Reed-Solomon recovery operation.

The signature cannot be evaluated in isolation. A receiver also needs the expected leader identity for that slot and the correct signed message for that variant. Legacy shreds sign bytes following the signature. Merkle shreds sign a Merkle root reconstructed from the packet leaf and its proof.

The 5-byte data header

A data shred adds a two-byte parent offset, a one-byte flags field, and a two-byte size field. The parent offset expresses the distance from the current slot to its parent. The flags combine completion markers with a reference-tick value. The size bounds the meaningful serialized data within the packet.

These fields serve block reconstruction, not merely display. A parent offset of one says the proposed block extends the immediately preceding slot. A larger offset can cross skipped slots. The data-complete bit closes one serialized entry batch. The last-in-slot bit closes the slot and also implies data completion.

The size field matters because packet buffers and erasure shards include bytes that are not application data. Zero padding can follow meaningful bytes. Merkle proof or chaining material can occupy space near the tail. A decoder that passes the entire UDP datagram into an entry deserializer will eventually treat padding or proof bytes as ledger bytes.

The 6-byte coding header

A coding shred adds three two-byte integers: the number of data shreds, the number of coding shreds, and the coding position. Together with the common FEC set index, these fields define an erasure set.

The count pair determines the Reed-Solomon matrix dimensions. If a set declares 32 data shreds and 32 coding shreds, the receiver expects 64 possible shard positions and needs any 32 valid shards to reconstruct the original 32 data shards. The coding position distinguishes parity shard zero from parity shard one and so on.

Coding shreds do not carry a parent offset, completion flags, or a data size. They do not contain a separately serialized transaction stream. Their payload is parity computed across equal-length representations of the data shreds. The exact authenticated and encoded ranges differ between legacy and Merkle formats, so a receiver should use a variant-aware erasure-shard accessor rather than slicing packets by intuition.

Variant selects the layout

One byte near the front controls much of the rest of the packet. Legacy data and legacy coding variants have dedicated discriminator values. Merkle variants use bit patterns that also encode proof length and whether chaining or retransmitter resigning applies.

The variant is therefore not a cosmetic type tag. It changes which bytes are signed, which bytes form an erasure shard, how much data capacity remains, and how the trailing bytes must be interpreted. Treating every data shred as the legacy layout can expose a credible slot and index while silently corrupting the payload boundary.

A sound parser performs minimum-length checks before reading fields, decodes the variant, selects a supported layout, and then validates variant-specific constraints. Unknown variants should be counted and rejected. Falling back to a nearby known layout turns an explicit compatibility event into silent ledger corruption.

Payload is not a transaction boundary

Data payload bytes are slices of a serialized vector of entries. The shredder may split that byte stream wherever packet capacity requires. A transaction can begin in one shred and finish in another. One shred can also contain the end of one entry and the beginning of the next.

Completion flags create boundaries for serialized entry batches, but they do not promise one entry or one transaction per packet. Receivers concatenate meaningful data ranges from consecutive data shreds, stop at a data-complete marker, and only then deserialize the resulting byte sequence.

This distinction affects latency. A parser can inspect headers as soon as each datagram arrives. It cannot safely decode an entry whose bytes have not arrived yet. Speculative streaming decoders can retain partial state, but they still need framing data and must discard the state if an earlier missing shred is later recovered with bytes that change the parse.

Padding has a protocol purpose

Equal-length shards are required by the erasure coding operation. The last data shred in a group often contains fewer meaningful ledger bytes than its capacity. The remaining region is zero padded for encoding.

Padding is not evidence of an empty transaction or an end marker. The data size field and layout rules decide which bytes are meaningful. Reading until the first zero byte is invalid because serialized entries, hashes, signatures, and transactions may legitimately contain zero bytes.

Coding shreds emerge at the erasure shard length by construction. They do not need the same semantic size marker because their content is consumed by Reed-Solomon recovery rather than entry deserialization. After recovery, reconstructed data shards must be rebuilt into valid data shreds and sanitized before their size and flags are trusted.

Authentication occupies two shapes

Legacy authentication is packet-local. The leader signs the serialized bytes following the signature field, including the relevant padded packet region. A changed header or payload byte causes Ed25519 verification to fail.

Merkle authentication is set-oriented. The leader hashes each shred's authenticated leaf material, constructs a canonical tree over the FEC set, and signs the root. Each shred carries the sibling hashes needed to recover that root. Shreds in the same FEC set consequently share the root signature.

The two schemes provide leader authentication through different byte paths. A decoder must not verify a Merkle signature over the packet tail or verify a legacy signature over a computed root. Both operations can be expressed behind one interface, but the interface must dispatch on variant before selecting the message.

Identity needs slot, type, and index

The tuple of slot, shred type, and index identifies a shred for storage and deduplication. Slot plus index is insufficient because data and coding indexes occupy distinct type namespaces. The FEC set index is grouping metadata, not a replacement for the shred index.

Duplicate packets are normal on a fanout path. Two copies with the same identity and the same authenticated bytes can be collapsed. Two valid-looking packets with the same identity but conflicting bytes require duplicate handling, not last-write-wins replacement. Signature and Merkle consistency checks determine whether either copy is attributable to the scheduled leader.

Assembly tables often need a second key for FEC work: slot plus FEC set index. Keep the identity key and recovery key separate. Mixing them tends to produce bugs when coding positions and data indexes are mapped into one shard array.

Sanitization is a staged operation

Packet length comes first. No field should be read until its complete byte range exists. Variant validity comes next, followed by header invariants such as index bounds, parent offset validity, flag combinations, proof length, coding counts, and coding position.

Cluster version and slot horizon checks reject traffic that cannot belong to the receiver's intended ledger view. Signature or Merkle verification establishes leader attribution. FEC consistency checks ensure all admitted members agree on set shape and root. Entry decoding occurs only after ordered data is available.

The order saves work under load. Ed25519 verification is more expensive than comparing a two-byte version or rejecting an impossible coding position. It also prevents malformed packets from allocating enormous buffers based on unchecked counts. Fast rejection is a correctness property when untrusted UDP can arrive at line rate.

Anatomy under raw UDP delivery

Raw UDP preserves the shred bytes but supplies no message order, retransmission, connection state, or backpressure. A 1,216-byte mean datagram in the measured shredstream.sh feed is an observation about traffic, not a universal serialized length.

The receiver must use the UDP datagram length as an outer bound and the shred layout as the inner interpretation. A larger receive buffer avoids truncating packets. The service contract allows packets up to 1,228 bytes, so a consumer should not allocate a 1,216-byte buffer merely because that is the measured average.

Packets can arrive twice, late, or after a slot was already declared complete. They can also arrive in coding-first order. The header provides enough information to place each valid packet without relying on arrival sequence. That is why correct anatomy parsing sits before every higher-level optimization.

What the packet can prove

A valid shred can prove that the expected slot leader authenticated particular data or a particular FEC-set root. It can show its claimed slot, position, version, recovery group, and completion state. It can contribute bytes to reconstruct serialized entries.

A shred cannot prove that its slot will remain on the rooted chain. It cannot prove that a transaction inside will execute successfully. A coding shred alone does not reveal application content without sufficient peers from its set. A last-in-slot flag is a leader assertion about production completion, not a consensus commitment.

Infrastructure should preserve those boundaries in its types. Use terms such as authenticated, reconstructed, executed, confirmed, and rooted for different states. Calling every parsed packet confirmed collapses five distinct events and makes downstream risk controls impossible to state.

Byte ownership affects decoder latency

One received datagram often crosses several queues: socket batch, header parser, cryptographic verifier, FEC set, ordered slot assembly, and entry decoder. Copying 1.2 kilobytes at every boundary consumes memory bandwidth and makes ownership hard to audit.

A bounded packet pool can keep the raw bytes stable while stages pass compact handles. Parsed headers should store values, not borrowed pointers into buffers that may be recycled. Meaningful data ranges can reference an admitted packet until assembly copies one completed entry batch into a contiguous decoding buffer.

Zero-copy design is not an absolute goal. Entry deserializers often benefit from one contiguous range, and holding hundreds of fragmented packet buffers can cost more than one planned copy. Measure copies by stage. Preserve actual datagram length and variant-derived offsets beside every handle so a later consumer cannot read unused capacity.

In practice

Slot 318,772,441 produces an FEC set beginning at data index 160. The set declares 32 data shreds and 32 coding shreds.

A data packet is 1,228 bytes. Bytes 0 through 82 form the common header. Bytes 83 through 87 hold parent offset, flags, and size. Its size field says 1,104, so the receiver admits bytes from the data region only up to that declared boundary. The remaining bytes serve padding and variant-specific authentication material.

Data index 173 is missing. The receiver has 31 data shreds and 7 coding shreds, 38 valid shards in total. Any 32 consistent shards are enough for the declared 32-source set. Recovery reconstructs index 173, after which the receiver sanitizes its header, verifies FEC consistency, and inserts it between indexes 172 and 174. A data-complete flag on index 179 then closes the serialized entry batch.

What this does not cover

This page describes the logical and current byte-level anatomy needed to reason about a shred. It does not publish a complete offset table for every legacy, Merkle, chained, or resigned variant. Those layouts evolve, and a decoder should bind constants to the Agave version and feature set it supports.

The page also stops before entry deserialization, Reed-Solomon implementation details, duplicate-proof handling, and fork choice. Packet anatomy establishes what bytes claim. It does not establish that the proposed block will be executed, voted on, or rooted.

Related questions

How many header bytes does a Solana shred have?
Current layouts use an 83-byte common header. A data shred adds five bytes for parent offset, flags, and data size, producing an 88-byte prefix. A coding shred adds six bytes for data count, coding count, and position, producing an 89-byte prefix. Variant-specific trailing material still changes usable payload capacity.
Does one data shred contain one transaction?
No. A data shred contains a byte slice from serialized ledger entries. One transaction can cross multiple shreds, while one shred can contain bytes from several entries or transactions. Receivers order consecutive data shreds, respect declared data sizes and completion flags, then deserialize the combined byte stream into entries and transactions.
Why are there zero bytes after the data?
Reed-Solomon encoding requires equal-length source shards. A data shred whose meaningful ledger bytes do not fill the available region is padded with zeros before erasure coding. The size field marks the meaningful boundary. Searching for the first zero byte is invalid because legitimate serialized ledger data can contain zero bytes.
What uniquely identifies a shred?
Storage and duplicate detection use the slot, shred type, and shred index together. Data and coding shreds have separate type namespaces, so slot plus index can collide across types. FEC work uses another grouping key, normally slot plus FEC set index, along with validated coding counts and positions.
Can a valid shred prove that a transaction is final?
No. Valid authentication attributes shred bytes or a Merkle root to the expected slot leader. Finality requires later consensus and rooting. The slot can be abandoned, and a transaction carried in authenticated data can still fail during execution. Low-latency systems must reconcile early observations against executed and confirmed state.

Read next

Ready to build against this? The documentation covers the implementation.