/** * SDN advertisement-flag DHT rendezvous discovery (alignment loop A3). * * sdn-server now joins the PUBLIC IPFS/Amino DHT with the stock * `/ipfs/kad/1.0.0` protocol (no `protocolPrefix` override — see node.ts, * which likewise runs `kadDHT({ clientMode: true })` with no prefix) and * advertises SDN membership as a rendezvous "flag" using go-libp2p's * routing-discovery content-routing convention: a namespace string is * hashed into a CID, and peers `Provide`/`FindProviders` that CID. * * This module derives the IDENTICAL CID from the IDENTICAL namespace string * so a browser node and a Go daemon rendezvous at the same DHT record. * * --- Go derivation, verified against the source actually vendored for this * repo (not from memory) --- * * Namespace (sdn-server/internal/node/advertisement_discovery.go:22,55-59): * const sdnAdvertisementDiscoveryNamespace = * "space-data-network/discovery/advertisement-flag" * target.Namespace = fmt.Sprintf("%s/%s", sdnAdvertisementDiscoveryNamespace, flag) * // flag is versioninfo.CurrentAdvertisementFlag ("spacedatanetwork/1.0.0" as of * // suite.versions.json today) or one of versioninfo.SupportedAdvertisementFlags — * // the same generated constants sdn-js already ships in version-info.generated.ts. * * CID derivation (go.mod pins github.com/libp2p/go-libp2p v0.46.0; verified * at $GOPATH/pkg/mod/github.com/libp2p/go-libp2p@v0.46.0/p2p/discovery/routing/routing.go:75-82): * func nsToCid(ns string) (cid.Cid, error) { * h, err := mh.Sum([]byte(ns), mh.SHA2_256, -1) // sha2-256 multihash, default (32-byte) digest * return cid.NewCidV1(cid.Raw, h), nil // CIDv1, raw codec (multicodec 0x55) * } * Both `drouting.NewRoutingDiscovery(dht).FindPeers(ctx, ns)` (peer discovery, * advertisement_discovery.go:477-478) and `dutil.Advertise(ctx, routingDiscovery, * ns)` (self-announce, node.go:2661-2662) route through this same `nsToCid`. * * So: CIDv1 { codec: raw (0x55), multihash: sha2-256(utf8(namespace)) }. */ import { CID } from "multiformats/cid"; import type { PeerInfo, PeerId } from "@libp2p/interface"; /** * Base rendezvous namespace — mirrors Go's unexported * `sdnAdvertisementDiscoveryNamespace` constant exactly. */ export declare const SDN_ADVERTISEMENT_DISCOVERY_NAMESPACE = "space-data-network/discovery/advertisement-flag"; export interface SDNAdvertisementDiscoveryTarget { flag: string; namespace: string; } /** * Build the full per-flag rendezvous namespace: * `${SDN_ADVERTISEMENT_DISCOVERY_NAMESPACE}/${flag}` — mirrors Go's * `target.Namespace = fmt.Sprintf("%s/%s", sdnAdvertisementDiscoveryNamespace, flag)`. */ export declare function sdnAdvertisementNamespace(flag: string): string; /** * Ordered, deduplicated discovery targets: current flag first, then any * additional supported flags — mirrors Go's `sdnAdvertisementDiscoveryTargets` * (advertisement_discovery.go:29-63). */ export declare function sdnAdvertisementDiscoveryTargets(currentFlag?: string, supportedFlags?: readonly string[]): { current: SDNAdvertisementDiscoveryTarget; targets: SDNAdvertisementDiscoveryTarget[]; }; /** * Derive the DHT rendezvous CID for a raw namespace string exactly as * go-libp2p's routing-discovery `nsToCid` does: CIDv1, raw codec, sha2-256 * multihash of the UTF-8 namespace bytes. See module doc comment above for * the exact go-libp2p source verified against. */ export declare function advertisementNamespaceToCid(namespace: string): Promise; /** Minimal content-routing surface this module needs (matches libp2p's `ContentRouting`). */ export interface SDNAdvertisementContentRouting { findProviders(cid: CID, options?: { signal?: AbortSignal; }): AsyncIterable; provide(cid: CID, options?: { signal?: AbortSignal; }): Promise; } /** * Minimal libp2p node surface this module needs. The real `Libp2p` instance * (src/node.ts) satisfies this directly — `contentRouting` is required; * `dial`/`getConnections`/`peerId` are used opportunistically when present. */ export interface SDNAdvertisementDiscoveryNode { peerId?: { toString(): string; }; contentRouting: SDNAdvertisementContentRouting; dial?(peer: PeerId): Promise; getConnections?(peerId?: PeerId): unknown[]; } export interface DiscoveredSDNAdvertisementPeer { peerId: string; multiaddrs: string[]; flag: string; } export interface FindSDNAdvertisementPeersOptions { /** libp2p node with a content-routing capable service (e.g. kadDHT). */ libp2p: SDNAdvertisementDiscoveryNode; /** Flags to search for; defaults to [current, ...supported] suite flags. */ flags?: readonly string[]; /** Forwarded to contentRouting.findProviders per flag lookup. */ signal?: AbortSignal; /** * Auto-dial newly discovered peers not already connected (default true) — * the browser-side counterpart of Go's connect-on-discovery behaviour in * `discoverSDNAdvertisementPeersNow` (advertisement_discovery.go:476-506). * Dial failures are non-fatal (peer may be unreachable/NATed); discovery * continues. */ autoDial?: boolean; } /** * Search the public DHT for peers advertising the SDN membership flag(s), * and (by default) dial any that aren't already connected. Wires discovered * peers into the same libp2p connection path used elsewhere in sdn-js * (`SDNNode.dial` / `libp2p.dial`), rather than a bespoke transport. */ export declare function findSDNAdvertisementPeers(options: FindSDNAdvertisementPeersOptions): Promise; export interface ProvideSDNAdvertisementFlagOptions { /** libp2p node with a content-routing capable service (e.g. kadDHT). */ libp2p: Pick; /** Flag to announce; defaults to the current suite advertisement flag. */ flag?: string; signal?: AbortSignal; } /** * Announce this browser node as an SDN member on the public DHT — the * browser-side counterpart of Go's `announceSDNAdvertisement` (node.go:2653- * 2664, which wraps `dutil.Advertise`, itself routed through the same * `nsToCid`/`Provide` path as `RoutingDiscovery.Advertise`). * * Optional by design: most browser nodes are content *consumers* and should * not call this. Call it only when the browser node should itself be * discoverable as an SDN peer. This performs a single provide(); callers * that want the Go daemon's periodic re-announce behaviour (node.go:2605- * 2619, every 30s) should re-invoke this on their own interval — DHT * provider records expire (~24h upstream, republished at ~3h intervals by * convention) so a long-lived browser node should re-provide periodically. */ export declare function provideSDNAdvertisementFlag(options: ProvideSDNAdvertisementFlagOptions): Promise; //# sourceMappingURL=sdn-advertisement-discovery.d.ts.map