Files
skills/docs/networking/drive/drive-mesh-protocol/src/codec/advertise.md
2026-05-29 08:20:56 +01:00

2.9 KiB

advertise

Purpose

Encodes and decodes cd:advertise envelope payloads — the gossip messages a peer emits to announce which chunks it currently holds for a given file. Enforces DMP-08 (presence bitset's bitLength MUST equal totalChunks; padding bits MUST be zero), DMP-09 (generation field is unsigned 32-bit), and DMP-21 (presence MUST be framed via @suaveplan/bitpacker-compressed).

Features

  • encodeAdvertisePayload(payload) — Zod-validates, cross-checks the presence bitset's embedded bitLength against totalChunks, base64-wraps the bitset, and emits UTF-8 JSON bytes.
  • decodeAdvertisePayload(bytes) — inverse, with the same DMP-08 cross-check on the receive side so receivers never trust a malformed advertisement.
  • Both functions throw DmpError with DMP.BITSET_LENGTH_MISMATCH, DMP.BITSET_PADDING_NONZERO, DMP.CODEC_MISMATCH, or DMP.ENVELOPE_MALFORMED depending on the failure class.

Usage: Basic Example

import {
    chunkIdsToRawBitset,
    decodeAdvertisePayload,
    encodeAdvertisePayload,
    encodeFramedBitset,
} from "@suaveplan/drive-mesh-protocol";

const totalChunks = 64;
const raw = chunkIdsToRawBitset([0, 5, 17, 63], totalChunks);
const presence = encodeFramedBitset(raw, totalChunks);

const wire = encodeAdvertisePayload({
    fileId: "f".repeat(64),
    presence,
    totalChunks,
    generation: 7,
    timestamp: Date.now(),
});

const back = decodeAdvertisePayload(wire);

Usage: Advanced Example

import {
    chunkIdsToRawBitset,
    decodeAdvertisePayload,
    encodeAdvertisePayload,
    encodeFramedBitset,
    GenerationTracker,
} from "@suaveplan/drive-mesh-protocol";

const tracker = new GenerationTracker();

function handleIncomingAdvertise(bytes: Uint8Array, peerId: string): void {
    const adv = decodeAdvertisePayload(bytes);
    const r = tracker.observe(peerId, adv.fileId, adv.generation);
    if (!r.accept) return; // DMP-09 stale-drop
    // Update peer-index for (peerId, adv.fileId) using adv.presence.
}

API Reference

  • encodeAdvertisePayload(payload: ChunkAdvertisePayload): Uint8Array.
  • decodeAdvertisePayload(bytes: Uint8Array): ChunkAdvertisePayload.
  • Errors: DMP.BITSET_LENGTH_MISMATCH, DMP.BITSET_PADDING_NONZERO, DMP.CODEC_MISMATCH, DMP.ENVELOPE_MALFORMED.

Implementation Notes

The encode-side cross-check between bitLength (recovered from the framed presence bitset) and totalChunks is intentional defence-in-depth: it stops a bug in the issuer from emitting an advertisement whose receivers would later reject. Generations are validated up to 0xFFFF_FFFF at the schema layer; wrap-detection logic lives in generation/monotonic.ts. The unwrapWire helper passes through bare nulls / non-objects so the schema is the single source of "this isn't a valid envelope" rejection — every malformed input ends up at the schema gate, not at a JS-level type error.