particle
a content-addressed node. identity = Hemera hash of content. 32 raw bytes, no headers, no version prefix. one hash function, one address space, permanent
the address is the identity. Hemera(content) — that is the particle. no registration, no authority, no namespace collision. two agents on opposite sides of the planet hashing the same content produce the same address. the first cyberlink to that address brings the particle into the cybergraph. a naked hash with no links never enters the graph (axiom A4)
Hemera
Hemera = Poseidon2(
p = 2^64 - 2^32 + 1 Goldilocks field
d = 7 full-round S-box: x -> x^7
partial S-box x -> x^-1 (field inversion)
t = 16 state width (elements)
Rf = 8 full rounds (4 + 4)
Rp = 16 partial rounds
r = 8 rate (elements; 56 bytes in per block, 7 B/element)
c = 8 capacity (64 bytes)
out = 4 elements 32 bytes out
)
every parameter is a power of 2. the Goldilocks field gives native 64-bit CPU arithmetic — a field multiplication is a single instruction. the S-box exponent $d = 7$ is the minimum invertible exponent for this field ($\gcd(7, p-1) = 1$; both 3 and 5 divide $p-1$)
capacity 8 (8 elements, 512 bits) bounds generic attacks on the sponge; collision resistance is set by the output length, not the capacity. a $b$-bit digest gives $b/2$-bit classical (birthday) and about $b/3$-bit quantum (BHT) collision resistance: the 32-byte (4-element) output above gives 128-bit classical and ~85-bit quantum (the hash row of zheng/specs/soundness.md); a 64-byte digest would give 256 and ~170. hemera profile v2 (hemera#15) proposes the longer identity digest for post-quantum collision resistance; Merkle nodes inside a proof stay 32 bytes. the block above mirrors hemera 0.3, which is normative. its algebraic degree is specified in hemera (the S-box and round structure live there, not here). production systems use capacity 4 (128-bit) because their hashes are ephemeral — trace commitments that live seconds. particle addresses live decades. the parameter choice matches the lifetime
one mode only: sponge. no compression mode. two modes producing the same 32-byte output from different inputs would break the address space as a function
initialize: state <- [0; 16]
absorb: for each 8-element chunk of padded input:
state[0..8] ^= chunk
state <- permute(state)
squeeze: output <- state[0..8]
round constants are self-bootstrapping: Hemera generates its own constants from the seed "cyber" (5 bytes) through the zero-constant permutation. no foreign primitives in the dependency chain
see hemera/spec for the full decision record
tree structure
large content splits into 4 KB chunks — OS page aligned, L1 cache fit, ⌈4096/56⌉ = 74 absorb blocks per leaf
leaf: Hemera(chunk_bytes)
internal node: Hemera(left_id || right_id) 64 bytes in (one rate block), 32 bytes out
tree shape: binary, left-balanced
particle: root hash of the tree
left-balanced means the same content prefix always produces the same left subtree. streaming: buffer at most 4 KB + proof per step. deduplication: 4 KB blocks show meaningful repetition in real data. overhead: 1.6% tree metadata
a single chunk (<=4 KB) hashes directly — no tree, just Hemera(content). the particle address is the same whether content is 10 bytes or 10 gigabytes: always 32 bytes, always a Hemera output
domain separation
different uses of Hemera are separated at the input:
| prefix | domain |
|---|---|
| (none) | particle content addressing — bare content in, address out |
0x01 |
edge hashing |
0x02 |
record commitments |
0x03 |
nullifier derivation |
0x04 |
Merkle internal nodes (NMT, MMR) |
H_edge(x) = Hemera(0x01 || x). particle content addressing uses no prefix — the particle address space is the default. proof-system prefixes (Fiat-Shamir, transcript binding) belong to zheng/lens, not the particle domain; the full prefix registry is in hemera.
output format
IPFS CIDv1: <version><multicodec><multihash><length><digest> 36-69 bytes
particle: <digest> 32 bytes
inside the protocol, the 32-byte digest is the complete identifier. IPFS compatibility is a thin translation layer at the gateway — inside nox, the wrapper never exists
all identities live in one flat 32-byte namespace: particles, edges, neurons, commitments, nullifiers. no type tags in the address. the type is determined by where the address appears in the BBG structure
endofunction
Hemera(Hemera(x) || Hemera(y)) type-checks: 32 bytes in one side, 32 bytes the other, 32 bytes out. hash of hashes is a hash. this closure under composition is why Merkle trees, polynomial commitments, and recursive proofs all use the same function without conversion
permanence
| property | zkVM (SP1, RISC Zero) | cyber |
|---|---|---|
| hash lifetime | seconds to hours | decades to permanent |
| parameter update | software release | impossible without rehash |
| rehash cost | zero (ephemeral) | $O(10^{15})$ operations |
| cost of parameter error | reissue proofs | lose the graph |
if Hemera is ever broken: full graph rehash under a new primitive. no version byte, no algorithm agility, no graceful coexistence. one graph, one hash, one identity. storage proofs make this possible — they guarantee content availability for rehashing and must be operational before genesis
performance
| metric | Hemera | SHA-256 |
|---|---|---|
| hash rate (single core) | ~62 MB/s | ~200 MB/s |
| zheng (CCS) constraints per hash | ~1,200 | ~25,000 |
| particles per second (200 B avg) | ~310K | — |
20x cheaper in proofs than SHA-256. 0.6x the raw throughput. the tradeoff: particle addresses are verified far more often than they are created. optimizing for proof cost is optimizing for the common case