Skip to content
LogoLogo

Records and bound notes

fields_root        = merkle_16(fields)                          typed by the template schema
stakeholders_root  = merkle_4(stake leaves), stake leaf = H(STAKE, party_id, role)   role ∈ {SIGNATORY, OBSERVER}
record             = H(REC, program_id, template_id, instance_id, fields_root, stakeholders_root, rho, salt)
record_nullifier   = H(NULL_REC, rho)

note               = H(NOTE, asset, amount, owner, rho_note)
owner              = H(OWNER_PARTY, pk_d.x, pk_d.y)  |  H(OWNER_RECORD, rho)    (rho of the owning record)
note_nullifier     = H(NULL, nk, leaf_index)          for party-owned notes
                   = H(NULL_BOUND, rho, leaf_index)   for bound notes

Records carry control state only; their amount is implicit zero. Value is always in native notes, so the kernel alone owns conservation and a permissive application cannot mint. A record holds value by owning bound notes. Spending a bound note requires consuming its owning record in the same fragment, which is how escrow, holds, and treasuries work.

Nullifiers are derived from the record's rho, not from any party's key. A multi-stakeholder record has no owner. Every stakeholder knows rho, so every stakeholder can see when the record is consumed, which is exactly Canton's visibility of an archive. Outsiders learn nothing. Authorization to consume is a separate check (§4.3), so knowing rho grants no authority.

Up to 4 stakeholders per record and 16 field slots in v1. Multi-limb fields occupy consecutive slots; the template schema declares limbs.