Skip to main content

Module dht

Module dht 

Source
Expand description

The subset of Macula’s signed DHT records that direct-dial resolution needs: procedure_advertisement and station_endpoint construction, signing, verification, and storage-key derivation, plus thin wrappers around the mesh’s _dht.* RPC procedures.

Ported from macula-io/macula’s src/record/macula_record.erl and src/macula.erl (the put_record/find_record/find_records facade), cross-checked against macula-go‘s own port of the same reference (dht/record.go, dht/client.go) — see those files’ doc comments for the fuller reasoning behind each field. Only the two record types direct-dial needs are ported; add more constructors here as other direct-dial consumers (streaming, content) are built.

This is a thin RPC client, not a DHT participant. Every function here just issues an ordinary signed CALL (_dht.put_record etc.) to whichever station the given Session is already connected to — real Kademlia routing, replication, and k-bucket maintenance stay entirely on the relay side (macula-station). Nothing in this module talks DHT protocol directly.

Structs§

ContentAnnouncement
A content_announcement record’s fields, read out of its payload — mirrors macula_record:read_content_announcement/1. The optional name/size/chunk_count metadata fields (content_announcement_opts()) are not ported — direct-dial content fetch doesn’t need them to resolve and dial; add them if a future caller needs to prioritize candidates without fetching the manifest.
ProcedureAdvertisement
A procedure_advertisement record’s fields, read out of its payload — mirrors macula_record:read_procedure_advertisement/1. cert_chain is None when the advertisement carries no cert_chain field (the common, unmanaged-realm case); see cert_chain::verify_advertisement_cert_chain.
Record
Mirrors macula_record.erl’s envelope map (type/key/version/ created_at/expires_at/payload/signature). subject_id is not carried — neither record type this module builds uses it.
StationEndpoint
A station_endpoint record’s fields, read out of its payload — mirrors macula_record:read_station_endpoint/1.

Enums§

DhtError
ReadRecordError
RecordFromRpcError
VerifyError

Constants§

DEFAULT_TTL
Matches macula_record’s ?DEFAULT_TTL_MS (48h) — the TTL a procedure_advertisement gets when the caller doesn’t specify one.
TYPE_CONTENT_ANNOUNCEMENT
TYPE_PROCEDURE_ADVERTISEMENT
Record type tags — macula_record.erl’s ?TYPE_* constants.
TYPE_STATION_ENDPOINT

Functions§

content_key
The DHT storage key for every content_announcement naming mcid: SHA-256(mcid). Matches macula_record:content_key/1. Consumers use this with find_records (there may be more than one announcer) before holding any record.
discovery_uri
Matches macula_direct_dial’s discovery_uri/2: the DHT lookup/advertisement key input is hex(realm) + "/" + procedure, so the same procedure name under different realms doesn’t collide in the DHT. The advertiser and every resolver must derive this identically.
find_record
Fetches one record by its storage key (see procedure_key / station_endpoint_key). Returns DhtError::NotFound if none exists — the caller’s signature should still be checked via verify before the payload is trusted; this function does not verify on the caller’s behalf.
find_records
Fetches every record stored at key — the full signer-deduped multiset (e.g. every procedure_advertisement for one procedure). Each record’s signature should be verified via verify before its payload is trusted; this function does not verify on the caller’s behalf.
find_records_by_type
Returns every record of typ currently visible from the station this session is connected to. Coverage depends on that station’s own view of the DHT. Mirrors macula:find_records_by_type/2.
new_content_announcement
Builds an UNSIGNED content_announcement record naming announcer_node as reachable at endpoint for mcid. Sign before put_record. Mirrors macula_record:content_announcement/3,4 — see ContentAnnouncement for which optional metadata fields are not ported.
new_procedure_advertisement
Builds an UNSIGNED procedure_advertisement record naming serving_station as procedure_uri’s current handler. procedure_uri should be the realm-qualified discovery URI (see discovery_uri), matching macula_direct_dial’s own convention — the advertiser and the resolver must derive the identical URI or the DHT storage key (procedure_key) will not agree. Sign before put_record.
new_procedure_advertisement_with_cert_chain
new_procedure_advertisement plus an embedded X.509 service-cert chain (leaf-first PEM: leaf ++ org CA), for Slice 7c Direction B managed-realm authorization — see cert_chain::verify_advertisement_cert_chain for the corresponding check. Opt-in: plain new_procedure_advertisement is unaffected and remains the right choice for unmanaged realms.
procedure_key
The DHT storage key for a procedure_advertisement by its (already realm-qualified — see discovery_uri) URI: SHA-256(uri). Matches macula_record:procedure_key/1.
put_record
Stores a signed record in the mesh DHT. Mirrors macula:put_record/2 — the relay validates the signature on receipt.
read_content_announcement
Extracts a content_announcement record’s typed fields, or an error if r isn’t one or is malformed. Mirrors macula_record:read_content_announcement/1.
read_procedure_advertisement
Extracts a procedure_advertisement record’s typed fields, or an error if r isn’t one or is malformed.
read_station_endpoint
Extracts a station_endpoint record’s typed fields, or an error if r isn’t one or is malformed.
sign
Sets r.signature to the Ed25519 signature over SIG_DOMAIN || canonical_unsigned(r), matching macula_record:sign/2.
station_endpoint_key
The DHT storage key for a station’s own station_endpoint record: SHA-256("station_endpoint" || pubkey). Matches macula_record:station_endpoint_key/1.
verify
Checks r’s Ed25519 signature against its own key, then its expiry. Matches macula_record:verify/1. Distinguishes VerifyError::Expired from VerifyError::InvalidSignature because a caller resolving a record (e.g. direct_dial’s retry loop) should retry past a stale-but-once-valid replica, never past a forged one — see macula_direct_dial.erl’s on_endpoint_verified/3 doing exactly this branch.