Byte-Prefix Registry
The complete lookup table of every single-byte SHA-256 domain-separation prefix Truestamp reserves, mapping each prefix value to the object and domain it isolates, so a verifier can reproduce any hash exactly.
Overview
Truestamp hashes with SHA-256 and prepends a single distinguishing byte to the input before hashing, so that each kind of object lives in its own private hash space. This page is the authoritative enumeration of every prefix Truestamp reserves: the exact byte value, the object or context it isolates, and the domain it belongs to. It is a lookup reference, not an explainer. For why domain separation is done at all, see domain-separated hashing. A verifier reproducing any Truestamp hash needs the prefix from this table, because the preimage is always prefix_byte || data.
Every prefix is a single byte written here in hexadecimal (0x11) with its decimal equivalent alongside. Prefixes are grouped so the high nibble names the domain and the low nibble distinguishes contexts within that domain.
Prefix registry
Each row is one reserved prefix. The hash of an object in that context is SHA-256(prefix_byte || preimage). Composite objects (item, observation, block, commitment, proof) hash a structured, length-delimited preimage rather than a single value, detailed in the composite preimage encoding section below; the single-value contexts hash their bytes directly.
| Prefix | Decimal | Domain | Separates |
|---|---|---|---|
0x00 |
0 | Merkle tree | Merkle tree leaf node |
0x01 |
1 | Merkle tree | Merkle tree internal node |
0x11 |
17 | Items | Item claims (user submission) |
0x12 |
18 | Items | Item metadata (submission window) |
0x13 |
19 | Items | Item composite hash (Merkle tree leaf input) |
0x21 |
33 | Entropy | Entropy observation data |
0x22 |
34 | Entropy | Entropy observation metadata |
0x23 |
35 | Entropy | Entropy observation composite hash (Merkle tree leaf input) |
0x31 |
49 | Blockchain | Genesis block constant |
0x32 |
50 | Blockchain | Block hash |
0x33 |
51 | Blockchain | Block metadata |
0x34 |
52 | Blockchain | Commitment data |
0x35 |
53 | Blockchain | Commitment composite hash (two field sets, see below) |
0x41 |
65 | Random tools | Coin toss derivation |
0x42 |
66 | Random tools | Dice roll derivation |
0x43 |
67 | Random tools | Drawing derivation |
0x44 |
68 | Random tools | Lottery derivation |
0x45 |
69 | Random tools | Random integer derivation |
0x51 |
81 | Key management | Key ID derivation (truncated to 4 bytes) |
0x53 |
83 | Key management | Pre-rotation commitment |
0x61 |
97 | Proofs | Proof signing payload |
Reserved ranges
The high nibble reserves a whole decade of prefixes to one domain, so future contexts within a domain claim an unused low nibble without collision.
0x00to0x01: Merkle tree structure (leaf and internal node), the RFC 6962 values.0x1X: Items domain.0x2X: Entropy domain.0x3X: Blockchain domain (blocks and commitments).0x4X: Random tools domain.0x5X: Key management domain.0x6X: Proofs domain.
The last digit distinguishes sub-contexts within a domain. A prefix, once assigned, is never reused for a different purpose.
Composite preimage encoding
The single-value contexts hash their bytes directly: the preimage is prefix_byte || value. The composite contexts (item 0x13, observation 0x23, block 0x32, and both commitment shapes under 0x35) instead bind several fields into one preimage with a length-prefixed serialization, so a verifier can reproduce the hash byte for byte and no field can be confused with another.
A composite preimage is prefix_byte || serialize(fields), where serialize walks the fields in a fixed order and, for each one, emits a 4-byte length followed by the field’s raw bytes:
serialize([f1, f2, ...]) = len32(f1) || f1_bytes || len32(f2) || f2_bytes || ...
- len32 is the field’s byte length as a 32-bit unsigned big-endian integer (4 bytes). A 5-byte field is prefixed with the bytes
00 00 00 05. - An id field is the identifier’s text encoded as UTF-8 bytes: 26 bytes for an item’s ULID, 36 bytes for the UUID of a block or observation. It is never decoded to any other form.
- A hash field (a claims, metadata, entropy, Merkle-root, or previous-block hash) is the 64-character hexadecimal string decoded to its raw 32 bytes, not the hex text.
- The signing key id field is the 8-character hexadecimal string decoded to its raw 4 bytes.
- A nil or absent field serializes as
len32(0)followed by no content bytes. The field keeps its slot, so the field count of a composite never changes. The one place this actually fires is the six-field Merkle inclusion commitment’ssubject_id, which is nil for a commitment that references no subject.
The field order is fixed per composite:
- Item hash (
0x13): id, claims hash, metadata hash, signing key id. - Observation hash (
0x23): id, entropy hash, metadata hash, signing key id. - Block hash (
0x32): id, previous-block hash, Merkle root, block metadata hash, signing key id.
The genesis block preimage is not a nil case
A block preimage is always the full 157 bytes for a 36-character UUIDv7 block id: there is no nil branch, and every block that can appear in a proof bundle has all five fields populated. The genesis block is the case implementers most often expect to be special, and it is not. Its previous-block hash is the constant SHA-256(0x31 || genesis_string), worked below, and its Merkle root is the empty-tree root e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855. Both are real 32-byte values written into the genesis row, so a chain walker that special-cases genesis to len32(0) placeholders derives a 93-byte preimage, gets a different block hash, and wrongly concludes the chain is forged.
The genesis constant is the worked example for prefix 0x31. It is a single-value context, so the preimage is the prefix byte followed by the UTF-8 bytes of the string, with no length delimiting:
genesis string (121 bytes)
truestamp-blockchain-genesis-block-2026-08-01-btc-960482-000000000000000000015845f68133bac045ac657d3515172d5b2639a48911e3
SHA-256(0x31 || genesis string)
9fb6dffc8e89c1cb9fe88e2b58fabd02a2aceb7275ac4d2f4cf5c0d467e9beb6
The string is 121 bytes rather than a short label because it names a Bitcoin block: height 960482, block hash 000000000000000000015845f68133bac045ac657d3515172d5b2639a48911e3, mined at 2026-08-01T00:04:19Z and the first block of that UTC day. That block hash was unpredictable until the block was mined, so nobody could have composed the string any earlier, and the first block of the Truestamp chain therefore carries evidence of the earliest moment the chain could have been minted. The date alone would prove nothing, since any date can be written into a string at any time. That length never reaches a block preimage: the previous-block hash field carries the decoded 32 bytes of the digest above, which is why a block preimage stays 157 bytes however the constant is worded.
Reproduce the digest rather than trusting the copy printed here; the string is the only authored value and the digest is derived from it. The constant also defines the chain, so a different string is a different chain rather than a corrected one.
The two 0x35 shapes
Prefix 0x35 is the one prefix that covers two structurally distinct composites. They cannot collide in practice, but they are not interchangeable, and a verifier must know which one it is reconstructing because the field counts, and therefore the length-prefixed preimages, differ.
- Epoch and external commitment (4 fields): id, commitment data hash, owner id, signing key id. This is what an epoch commitment and an external commitment sign. The owner id is an identifier field, serialized as UTF-8 text: an epoch commitment sets it to the literal string
"epoch:<method>"(for example"epoch:stellar"), while an external commitment sets it to the committed block’s id. - Merkle inclusion commitment (6 fields): id, block id, subject id, Merkle root, the SHA-256 of the raw inclusion proof, signing key id. This is the commitment record that binds one subject to one block. The proof field is hashed before inclusion so the preimage stays fixed-width no matter how deep the tree is, and the subject id is the field that can be nil.
The proof signing payload (0x61) has its own fixed byte layout, given in the proof bundle format.
Empty metadata
An object with no metadata of its own still commits to a metadata hash, so the preimage is never a missing field. That hash is the domain-separated hash of the canonical JSON (JCS) empty object: SHA-256(0x33 || "{}") for a block and SHA-256(0x22 || "{}") for an entropy observation, where {} is the two-byte encoding of an empty map. The genesis block is not an instance of this: it carries a metadata map recording its initial key event (type, sequence, key id, public key, and any pre-rotation commitment), and its metadata hash is the 0x33 hash of that map’s JCS encoding.
Merkle prefixes are a distinct layer
The Merkle tree prefixes 0x00 and 0x01 operate at a different layer from the application prefixes above. They separate the two node types inside a Merkle tree (leaf versus internal node) and are the standard RFC 6962 values. A Merkle leaf is SHA-256(0x00 || leaf_hash) and an internal node is SHA-256(0x01 || left || right). Crucially, the leaf hashes fed into the tree are themselves already domain-separated application hashes: an item composite hash uses prefix 0x13 and an entropy observation composite hash uses 0x23, and those values become the leaves the Merkle tree then re-hashes under 0x00. So a value can be hashed under an application prefix and, at the next layer up, hashed again under a Merkle prefix.
Not to be confused with proof type codes
Truestamp also has a separate set of small integers, the proof type codes (for example 10 for a block subject, 20 for an item subject, 30 through 32 for entropy sources, and 40 and 41 for external commitment chains). These are not byte prefixes and are not part of this registry. A proof type code is a discriminator carried inside a proof and inside the signed proof payload, not a prefix prepended before hashing. The only proofs-domain byte prefix is 0x61, which separates the proof signing payload itself. Do not read the proof type codes as entries in the prefix table.
Citations
- RFC 6962: Certificate Transparency. Source of the leaf (
0x00) and internal-node (0x01) Merkle prefixes and the byte-prefix domain-separation approach this registry follows.