Refs
A Ref identifies a block and how to interpret it. On the wire a ref is an IPLD CIDv1 (§2.5): a version, a content codec naming the referenced block's kind, and a multihash carrying the block's hash. This chapter's grammar describes a ref's fields independent of any particular encoding; the authoritative CBOR encoding of a ref (tag 42) is defined in §5.2.
Binary form, 36 bytes with SHA2-256. Each field before the digest is a
varint; the digest is the block's hash.
0x55raw → opaque bytes (a file chunk)0x71dag-cbor → canonical CBOR node (§6)
Other encodings of the same ref:
- string form —
"b" + base32(binary CID)(multibase base32lower) - CBOR form —
tag(42)wrapping a byte string of0x00 || binary CID
Grammar (all varints per §3.1, minimal):
ref = cid-v1
cid-v1 = varint(0x01) || varint(codec) || multihash
codec = 0x55 (raw) / 0x71 (dag-cbor)
multihash = varint(hash-code) || varint(digest-length) || digestCodec — the ref's kind: how a consumer interprets the referenced block. The two admitted codes are multicodec registry entries (§2.5):
kind multicodec code referenced bytes raw raw0x55opaque bytes (a file chunk) node dag-cbor0x71a canonical CBOR node (§6) Every other codec in the registry (e.g.
dag-pb,0x70) is not part of this format. A reader MUST reject it, and SHOULD report a recognized-but-unsupported codec distinctly from malformed input in diagnostics. During garbage collection, an unsupported codec in a ref value aborts the sweep fail-closed (§15.2) — intentionally, since the shape of the referenced subgraph is unknown. (Codec identifiers are minted by the multiformats registry, not by this specification; a future version adopting a new block kind adopts a registered code.)Multihash — hash function code and digest length, then the digest of the block bytes. With SHA2-256:
0x12 0x20 || digest(34 bytes). The function code MUST be a multihash entry of the multicodec registry and MUST be the store's hash function (§3.4, §10.3). The identity multihash (0x00) MUST be rejected wherever it appears: it carries data inside the ref, which would give inline content a second encoding (inline bytes live in the entry fieldd, §7.3 — one value, one encoding).Validation (eager, wherever a ref is decoded — an embedded CBOR link, a
refs:value, a pack-section CID):- The version varint MUST be
0x01. A bare multihash (CIDv0, leading0x12 0x20) MUST be rejected: one link, one encoding. - The codec MUST be
0x55or0x71. - The digest length MUST be in [20, 64], MUST equal the hash function's output length, and MUST equal the number of digest bytes actually present.
- Every varint MUST be minimal (§3.1) — a non-minimal varint is a second encoding of the same ref. A hash-code varint longer than 4 bytes MUST be rejected.
- Total binary length is therefore in [24, 71] (one-byte codes with a 20-byte digest, up to a 4-byte hash code with a 64-byte digest) — and exactly 36 under SHA2-256.
- The version varint MUST be
Worked example — the raw-codec ref of the empty byte string under SHA2-256. (A parse vector only: the empty block cannot occur in a conforming store, §12.1.)
digest e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
multihash 1220 || digest
binary CID 01551220 || digest
string bafkreihdwdcefgh4dqkjv67uzcmw7ojee6xedzdetojuzjevtenxquvyku
CBOR d82a58250001551220 || digestCBOR form: CBOR tag 42 (
0xd8 0x2a) whose payload is a byte string containing0x00 || binary CID— the multibase identity prefix, then the ref. This is exactly the IPLD DAG-CBOR link rule (§5.2 rule 5); the prefix byte MUST be present (DAG-CBOR: the identity prefix "must not be omitted"). Decoders MUST verify: payload is a byte string, first byte0x00, remainder a valid ref under the rules above (§5.3).Tag choice (binding): only tag 42 is admitted; tag 117 and every other non-42 tag MUST be rejected (§5.3). Tag 42 is registered in the IANA "CBOR Tags" registry as "IPLD content identifier" with exactly this payload grammar, and this format's refs are exactly such identifiers — a node of this format is a valid DAG-CBOR block whose links generic IPLD tooling extracts and traverses with no adaptation. (Tag 117 was a private tag used by a pre-IPLD draft of this format that never shipped; see Appendix B for the history.)
String form: the character
bfollowed by the unpadded lowercase base32 (§3.2) of the binary CID — multibasebase32lower, the ecosystem's canonical text form for CIDv1. Emitters MUST produce exactly this form; parsers MUST accept only it —bprefix, lowercase, canonical base32 per §3.2, decoded bytes valid under the rules above. (Non-normative: multibase strings are self-describing, and implementations MAY layer permissive parsing — other multibases, uppercase base32 — at UI boundaries; such input MUST be re-emitted canonically and MUST NOT appear in stored data, packs, or test vectors.)Equality covers the full binary CID: codec + multihash. Two refs to the same bytes under different codecs are different refs (and visibly so as strings:
bafk…raw vsbafy…dag-cbor).Block identity — the storage key (§10.1) and the unit of section deduplication in packs (§12.2) — is the multihash alone. The codec describes how a referrer interprets the block, not what the block is, so identical bytes referenced both as raw and as dag-cbor dedupe to one stored block. (This is the split mainstream IPLD block stores use: storage keyed by multihash, traversal by full CID.)
The codec/multihash asymmetry has two consequences that conforming implementations MUST respect:
- Graph-traversal visited-sets MUST be keyed by the full CID: a multihash first visited via a raw ref MUST still be traversed (its children discovered) when later reached via a dag-cbor ref.
- Storage- and section-level deduplication sets MUST be keyed by the multihash alone: one stored block, one pack section, however many codecs point at it.
A single set doing double duty breaks one direction or the other. (The discipline is easier to keep than under the pre-IPLD draft: full-CID equality is the natural equality of refs, so a naive visited set is already correct, and collapsing to the multihash now takes a deliberate act — stripping the codec — that is correct only in the two deduplication positions above.)
- Store context: the grammar above admits any hash function and any
digest length in [20, 64], but within a given store every ref — a
refs:value, a pack-section CID, an embedded CBOR link — MUST carry exactly the store's hash function and output length (§3.4, §10.3). A well-formed ref with any other multihash can never resolve there and MUST be rejected in that store's context, not deferred to a later "block not found".