macula_record (macula v3.2.0)

View Source

Signed, content-addressed records.

Records are the SDK's primitive for typed, signed, application data put into the mesh's distributed storage. They are content-addressed: the key is the BLAKE3 hash of the deterministic CBOR encoding of the signed body, so two clients computing the same record arrive at the same key.

Anatomy

A record has six fields plus an optional expires_at:

  • type — application-defined 0..255 tag (e.g. 16#02 for station_record, 16#11 for content_announcement). The SDK does not interpret payloads — type is just routing metadata for find_records_by_type/2.
  • payload — opaque application bytes. Conventionally a deterministic CBOR encoding via macula_record_cbor, but the SDK stores it verbatim.
  • pubkey — 32-byte Ed25519 public key of the publisher.
  • ttl_ms — record lifetime hint in milliseconds. The relay expires the record after this elapses.
  • sig — 64-byte Ed25519 signature over the canonical body (type + payload + pubkey + ttl_ms, deterministic CBOR).
  • expires_at — absolute epoch milliseconds, set by the relay on store. Optional in records built locally.

Signing scheme

The signed bytes are the deterministic CBOR encoding (RFC 8949 §4.2.1) of:

   [type, payload, pubkey, ttl_ms]

Verifiers reconstruct this same byte string from the record's fields and check the Ed25519 signature against pubkey.

Content addressing

The key is blake3(canonical_body || sig). Including the signature in the hash prevents two distinct signers from producing the same key for the same logical content — each signed record has a unique address.

Summary

Types

32-byte BLAKE3 of (body || sig)

Functions

Build a signed record. Computes the canonical body, signs with the keypair's private half, and returns the record map. The caller passes the result to macula:put_record/2.

Returns the canonical byte string the signature covers. Exposed so callers / verifiers can inspect what was signed without re-deriving the encoding rules.

The 32-byte content-address key for a record. Computed as BLAKE3 of the canonical body concatenated with the signature.

Verify a record's signature. Returns true if sig is a valid Ed25519 signature over canonical_body/1 under pubkey.

Types

record/0

-type record() ::
          #{type := record_type(),
            payload := binary(),
            pubkey := <<_:256>>,
            ttl_ms := non_neg_integer(),
            sig := <<_:512>>,
            expires_at => non_neg_integer()}.

record_key/0

-type record_key() :: <<_:256>>.

32-byte BLAKE3 of (body || sig)

record_type/0

-type record_type() :: 0..255.

Functions

build(Type, Payload, KeyPair, TtlMs)

-spec build(record_type(), binary(), macula_identity:key_pair(), non_neg_integer()) -> record().

Build a signed record. Computes the canonical body, signs with the keypair's private half, and returns the record map. The caller passes the result to macula:put_record/2.

canonical_body(_)

-spec canonical_body(record()) -> binary().

Returns the canonical byte string the signature covers. Exposed so callers / verifiers can inspect what was signed without re-deriving the encoding rules.

key_of(_)

-spec key_of(record()) -> record_key().

The 32-byte content-address key for a record. Computed as BLAKE3 of the canonical body concatenated with the signature.

verify(Record)

-spec verify(record()) -> boolean().

Verify a record's signature. Returns true if sig is a valid Ed25519 signature over canonical_body/1 under pubkey.