# Entries

> The layout of the serialized entries payload, the decoders that read it, and the delivery properties of the feed.

Source: https://docs.constant-k.com/shredprism/entries/

Every ShredPrism response carries a slot number and an `entries` byte string: this page covers what is in those bytes, what decodes them, and what the feed does not promise.

ShredPrism delivers serialized entries, so deserialization is the first step the reader takes. [Data Stages](https://docs.constant-k.com/get-started/data-stages/) places that step in the pipeline.

## Payload layout

`entries` holds a serialized list of proof-of-history entries. An entry is a link in the hash chain, with the transactions observed before that hash was generated. Most entries hold no transactions: an entry with an empty transaction list is a tick.

| Field                          | Bytes    | Encoding                                         |
| :----------------------------- | :------- | :----------------------------------------------- |
| Entry count                    | 8        | Unsigned 64-bit, little-endian                   |
| *Per entry:* `num_hashes`      | 8        | Unsigned 64-bit, little-endian                   |
| *Per entry:* `hash`            | 32       | The proof-of-history hash                        |
| *Per entry:* transaction count | 8        | Unsigned 64-bit, little-endian                   |
| *Per entry:* transactions      | Variable | Each one in the standard transaction wire format |

constant-k confirmed this layout on 2026-09-20 against the Agave 4.2 serializer. Transaction bytes inside an entry are the same bytes a `base64` RPC response carries, so a decoder that reads one reads the other. Their lengths are not in the layout, so reaching the second transaction means decoding the first.

## Serialization

Since Agave 4.2 the encoding is [wincode](https://docs.rs/wincode/latest/wincode/), a bincode-compatible serializer from Anza. constant-k nodes run Agave 4.3.0.

> **bincode cannot decode this payload:** A version 1 transaction has no bincode representation, at any version of `solana-entry`. `bincode::deserialize` either fails or, on a mixed batch, stops at the first v1 transaction. Jito's own `deshred` example still calls `bincode::deserialize` and is out of date.

## Rust decoding

| Crate                                                                                      | Version                                                                                | Why                                                                                                                                          |
| :----------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- |
| [`solana-entry`](https://docs.rs/solana-entry/latest/solana_entry/entry/struct.Entry.html) | 4.2 or later, feature `agave-unstable-api`                                             | The `Entry` type. The whole crate sits behind that feature, so a build without it sees nothing at all.                                       |
| [`wincode`](https://docs.rs/wincode/latest/wincode/)                                       | The one `solana-entry` already depends on: `0.5` for `solana-entry` 4.2, `0.6` for 4.3 | The serializer. Two wincode versions in one build put `Entry` on one set of traits and the decode call on the other, which does not compile. |

The call is `wincode::deserialize::<Vec<Entry>>`, the same call Agave uses to read a deshredded payload. The [Quickstart](https://docs.constant-k.com/shredprism/quickstart/#rust-consumer) has a consumer that runs.

A truncated payload fails with a read-size error. Trailing bytes after a complete list are ignored rather than reported, so a payload that decodes to fewer entries than its length suggests raises nothing.

## TypeScript decoding

No JavaScript package implements wincode. The outer layout is four fixed-width fields, which `DataView` reads directly, and the transactions inside are in the standard wire format, which `@solana/kit` decodes.

`getCompiledTransactionMessageDecoder()` from `@solana/kit` 8.0.0 or later exposes `read(bytes, offset)`, which returns the decoded message and the offset after it. That offset is what walks the payload from one transaction to the next. `getTransactionDecoder()` does not: it treats everything after the signatures as message bytes and consumes to the end of the buffer, so it only works on a payload holding exactly one transaction.

The transaction's first byte decides which branch reads it:

| First byte   | Format       | Signatures                                                            |
| :----------- | :----------- | :-------------------------------------------------------------------- |
| Below `0x80` | Legacy or v0 | A one-byte count, then that many 64-byte signatures, then the message |
| `0x81`       | Version 1    | The message, then `header.numSignerAccounts` 64-byte signatures       |

The [Quickstart](https://docs.constant-k.com/shredprism/quickstart/#typescript-consumer) has the walk in full. [Transaction v1](https://docs.constant-k.com/rpc/transaction-v1/) covers the rest of that format.

## Delivery properties

The response message has two fields. There is no sequence number, no batch index and no completion flag, so everything below is the consumer's responsibility.

| Property      | What a consumer handles                                                                                                                                                   |
| :------------ | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Granularity   | A message carries a batch of entries, not necessarily every entry of its slot. Several messages can share a `slot` value.                                                 |
| Order         | Slot values do not only increase. Code that keys on the last slot seen needs a tolerance window.                                                                          |
| Duplicates    | The protocol has no message identifier and makes no at-most-once promise. A transaction signature is the key to deduplicate on, held in a set bounded by slot or by time. |
| Completeness  | No message marks the end of a slot, and a batch whose shreds cannot be recovered never arrives. The feed cannot confirm that a slot is whole.                             |
| Empty batches | A message that decodes to zero entries is valid. Treating it as a failure rejects good data.                                                                              |

## Absent from the feed

Entries come from a block while its leader is producing it. A block can be skipped or lose its fork, so a transaction in the feed is not a transaction that landed.

| Not in the feed                                    | Source for it                                                       |
| :------------------------------------------------- | :------------------------------------------------------------------ |
| Execution result: status, fee, logs, compute units | [Kaldera](https://docs.constant-k.com/kaldera/), [`getTransaction`](https://docs.constant-k.com/rpc/http/gettransaction/) |
| Account state after execution                      | [Kaldera](https://docs.constant-k.com/kaldera/), [`getAccountInfo`](https://docs.constant-k.com/rpc/http/getaccountinfo/) |
| Confirmation that a transaction landed             | [`getSignatureStatuses`](https://docs.constant-k.com/rpc/http/getsignaturestatuses/)           |
| Block metadata: parent slot, blockhash, rewards    | [`getBlock`](https://docs.constant-k.com/rpc/http/getblock/)                                   |
| Server-side filters                                | [Kaldera filters](https://docs.constant-k.com/kaldera/filters/)                                |
| Past slots                                         | [Kaldera replay](https://docs.constant-k.com/kaldera/replay/)                                  |

The usual shape pairs the two: ShredPrism decides what to act on, and a post-execution source says what happened.

## Back-pressure

gRPC runs on HTTP/2, which has flow control. A client that stops reading stops the sender instead of losing data, so falling behind costs latency rather than messages.

1. Read the socket on a task that does nothing else.
2. Hand each payload to a bounded queue.
3. Decode and filter behind that queue, never in the reading loop.
4. Decide what the queue does when it is full, and count the drops.

## Differences from a self-hosted proxy

Jito's `shredstream-proxy` is a process an operator runs next to a node. ShredPrism serves the same service and method as a hosted endpoint.

|                        | Self-hosted proxy                                                                                          | ShredPrism                          |
| :--------------------- | :--------------------------------------------------------------------------------------------------------- | :---------------------------------- |
| Deployment             | A process to run and keep running                                                                          | An endpoint to connect to           |
| Shred ingest           | UDP on a bind port, `20000` by default. NAT is not supported and the source addresses need firewall rules. | None                                |
| Authentication         | A Solana keypair, approved in advance, authenticates the proxy upstream                                    | `x-token` metadata on the gRPC call |
| Transport to your code | Plaintext gRPC on a local port                                                                             | gRPC over HTTP/2 with TLS           |
| Region selection       | `--desired-regions`, at most two                                                                           | The endpoint hostname               |
| Service and method     | `shredstream.ShredstreamProxy/SubscribeEntries`                                                            | Identical                           |

## Upstream references

| Source                                                                                       | What it covers                                                                                                                                                       |
| :------------------------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [Jito ShredStream documentation](https://docs.jito.wtf/lowlatencytxnfeed/)                   | The service the protocol comes from. The page carries a sunset notice for Jito's own hosted service, dated 5 September 2026. The protocol it describes is unchanged. |
| [`shredstream.proto`](https://github.com/jito-labs/mev-protos/blob/master/shredstream.proto) | The service definition, alongside the heartbeat and trace messages this call does not use                                                                            |
| [jito-labs/shredstream-proxy](https://github.com/jito-labs/shredstream-proxy)                | The reference implementation, and the `deshred` example whose decoding is out of date                                                                                |
| [`solana-entry`](https://docs.rs/solana-entry/latest/solana_entry/entry/struct.Entry.html)   | The `Entry` type and its fields                                                                                                                                      |
| [`wincode`](https://docs.rs/wincode/latest/wincode/)                                         | The serialization format                                                                                                                                             |
