argus/src/seed-tld-beacon.mjs

106 lines
4.8 KiB
JavaScript
Raw Normal View History

BNS: per-TLD on-chain registry, multi-beacon indexer, enforcement gate Per-TLD certificates on a distinct TLD beacon supersede the legacy list-in-one-NFT model. TLD label is the NFT commitment; TREG/TUPD payloads on the TLD beacon mirror REG/UPD on the name beacon. Chipnet TLD beacon: bchtest:qzc4c76vtw9nd49g6x8nmvc0jz62uvk4dc7hmpmerh scripthash c85db10e106606273422b2733b2a6fb8b35a4d0e7dbfb20cf59bdb0833c008b8 * config.js, resolver-web.{js,d.ts} — TLD_BEACON + TLD_BEACON_SCRIPTHASH * bns.js — KNOWN_OPS { REG, UPD, TREG, TUPD }, registerTld/updateTld/normalizeTld * bns.js + resolver-web.js — buildIndex({enforceTld:false}) drops name REGs whose TLD lacks a live TLD cert at their block height (mempool-friendly). Lockstep across both files. * lib/tld-index.js — buildTldSnapshot({history,txs}) → deterministic root over canonicalised tlds[]. Pure, importable, and stable across insertion order. * indexer/bns-indexer.js — BeaconIndex is multi-beacon; ws handler dispatches by scripthash; new HTTP endpoint GET /tld-list.json + /health behind BNS_HTTP_PORT; state file v1 → v2 migrates in fromJSON. * publish-tld-mirror.mjs — S3 (floating + immutable content-addressed) plus NIP-33 kind 30078 d:bns-tld-list to Nostr relays, signed via nostr-tools (libauth's Schnorr differs from BIP-340 and relays reject it). * seed-tld-beacon.mjs — idempotent chipnet seed. Current set on the beacon: bch p2p bit nav test x asm neo gt sc sia com dex cex nt (15). `.com` is held by the operator: cert on-chain, excluded from public registrar UI. Design + docs: * Decentralized.DNS/DESIGN-tld-registry.md — schema, enforcement, operator-countersig gate, USD-tiered pricing floors, fee splits, tracker/mirror mechanics, migration/grandfathering. * INSTRUCTIONS.md §3 rewritten for the 4-step flow (TREG → UI → deploy → republish snapshot). * site/tlds/ — public docs page listing current TLDs + verification paths. * site/sirius/register.html — dropdown removed; parallel search across every TLD in the TLDS array, sorted available → taken → not-on-registry. Config: * ariadne.config.json tlds → [bch, p2p, bit, nav, test, x] (CA constraints; on-chain registry is now the authoritative source, config is fallback). * setup/install.ps1 — reads TLD list via fetchTldList (per-TLD registry) with fallback to fetchBcnrTlds (legacy tls.bch list-NFT) then config. Tests: * test/tld-index.test.mjs — 30 self-contained checks (multi-beacon dispatch, state migration, ws routing, snapshot shape + root recomputability). * test/tld-enforcement.test.mjs — synthetic + live chipnet integration (with-gate correctly drops all pre-seed names).
2026-08-29 17:11:02 +02:00
// One-off (idempotent): seed the chipnet TLD-certificate beacon with the
// operator-confirmed initial TLD set. Reads what's already there via the wallet's
// provider (so re-runs skip anything present), then mints a TREG for each
// missing TLD. Verifies at the end by rebuilding the snapshot from beacon
// history — the same code path the /tld-list.json endpoint uses.
//
// node src/seed-tld-beacon.mjs
//
// Design context: Decentralized.DNS/DESIGN-tld-registry.md §9 item 1. Chipnet
// only — mainnet is a separate switch and needs the TLD covenant first.
import { loadWallet } from "./lib/wallet.js";
import { registerTld, parseOpReturn } from "./lib/bns.js";
import { buildTldSnapshot } from "./lib/tld-index.js";
import { TLD_BEACON } from "./config.js";
// Operator-confirmed seed set (2026-08-20): shipped defaults minus
// deviant/bcnr/silentmode, plus x for the coinspectrum.x work already in flight.
// Extended 2026-08-29: asm, neo, gt, sc, sia, com; then dex, cex, nt; then dea.
// The operator holds the countersignature key that would otherwise gate
// ICANN-adjacent TLDs (.com, .sc, .gt, .neo) on mainnet; on chipnet no covenant
// enforces the gate, so these are seeded directly under operator authority.
// `.com` is HELD by the operator (excluded from the public registrar UI) so
// nobody else can claim names under it — the TLD cert stays on-chain, but no
// second-level registrations are offered. Future TUPD may set policy:"frozen"
// once the TLD covenant lands and enforces it.
const SEED_TLDS = [
"bch", "p2p", "bit", "nav", "test", "x",
"asm", "neo", "gt", "sc", "sia", "com",
"dex", "cex", "nt", "dea",
"hub", "os",
BNS: per-TLD on-chain registry, multi-beacon indexer, enforcement gate Per-TLD certificates on a distinct TLD beacon supersede the legacy list-in-one-NFT model. TLD label is the NFT commitment; TREG/TUPD payloads on the TLD beacon mirror REG/UPD on the name beacon. Chipnet TLD beacon: bchtest:qzc4c76vtw9nd49g6x8nmvc0jz62uvk4dc7hmpmerh scripthash c85db10e106606273422b2733b2a6fb8b35a4d0e7dbfb20cf59bdb0833c008b8 * config.js, resolver-web.{js,d.ts} — TLD_BEACON + TLD_BEACON_SCRIPTHASH * bns.js — KNOWN_OPS { REG, UPD, TREG, TUPD }, registerTld/updateTld/normalizeTld * bns.js + resolver-web.js — buildIndex({enforceTld:false}) drops name REGs whose TLD lacks a live TLD cert at their block height (mempool-friendly). Lockstep across both files. * lib/tld-index.js — buildTldSnapshot({history,txs}) → deterministic root over canonicalised tlds[]. Pure, importable, and stable across insertion order. * indexer/bns-indexer.js — BeaconIndex is multi-beacon; ws handler dispatches by scripthash; new HTTP endpoint GET /tld-list.json + /health behind BNS_HTTP_PORT; state file v1 → v2 migrates in fromJSON. * publish-tld-mirror.mjs — S3 (floating + immutable content-addressed) plus NIP-33 kind 30078 d:bns-tld-list to Nostr relays, signed via nostr-tools (libauth's Schnorr differs from BIP-340 and relays reject it). * seed-tld-beacon.mjs — idempotent chipnet seed. Current set on the beacon: bch p2p bit nav test x asm neo gt sc sia com dex cex nt (15). `.com` is held by the operator: cert on-chain, excluded from public registrar UI. Design + docs: * Decentralized.DNS/DESIGN-tld-registry.md — schema, enforcement, operator-countersig gate, USD-tiered pricing floors, fee splits, tracker/mirror mechanics, migration/grandfathering. * INSTRUCTIONS.md §3 rewritten for the 4-step flow (TREG → UI → deploy → republish snapshot). * site/tlds/ — public docs page listing current TLDs + verification paths. * site/sirius/register.html — dropdown removed; parallel search across every TLD in the TLDS array, sorted available → taken → not-on-registry. Config: * ariadne.config.json tlds → [bch, p2p, bit, nav, test, x] (CA constraints; on-chain registry is now the authoritative source, config is fallback). * setup/install.ps1 — reads TLD list via fetchTldList (per-TLD registry) with fallback to fetchBcnrTlds (legacy tls.bch list-NFT) then config. Tests: * test/tld-index.test.mjs — 30 self-contained checks (multi-beacon dispatch, state migration, ws routing, snapshot shape + root recomputability). * test/tld-enforcement.test.mjs — synthetic + live chipnet integration (with-gate correctly drops all pre-seed names).
2026-08-29 17:11:02 +02:00
];
// Empty records for the seed — the TLD covenant work will populate
// policy/fee_bps/reserved later. Empty means "defaults apply everywhere",
// which per the design doc §3 is {policy:"open", fee_bps:500, min_len:1}.
const SEED_RECORDS = {};
const wallet = await loadWallet("main");
console.log(`from wallet : ${wallet.cashaddr}`);
console.log(`TLD beacon : ${TLD_BEACON}`);
console.log(`target TLD set : ${SEED_TLDS.join(" ")}`);
// Fetch what's already on the beacon so re-runs skip it.
console.log("\nfetching current TLD-beacon state …");
const history = await wallet.provider.getHistory(TLD_BEACON);
const txs = new Map();
for (const { tx_hash } of history) {
try { txs.set(tx_hash, await wallet.provider.getRawTransactionObject(tx_hash)); }
catch { /* unreadable — skip */ }
}
const before = buildTldSnapshot({ history, txs });
console.log(`present : ${before.tlds.length ? before.tlds.map((t) => t.tld).join(" ") : "(none)"}`);
const existing = new Set(before.tlds.map((t) => t.tld));
const toMint = SEED_TLDS.filter((t) => !existing.has(t));
if (!toMint.length) {
console.log("\nnothing to do — all target TLDs already registered.");
process.exit(0);
}
console.log(`will register : ${toMint.join(" ")} (${toMint.length} tx)`);
const bal = await wallet.getBalance("sat");
console.log(`wallet balance : ${bal} sat`);
const results = [];
for (const tld of toMint) {
process.stdout.write(` TREG ${tld} … `);
try {
const res = await registerTld(wallet, tld, SEED_RECORDS);
results.push({ tld, ok: true, ...res });
console.log(`ok txid=${res.txid} category=${res.category?.slice(0, 16)}…`);
} catch (e) {
results.push({ tld, ok: false, error: String(e && e.message || e) });
console.log(`FAIL ${e && e.message || e}`);
}
// A short pause so a chain query between two REGs sees the previous tx.
await new Promise((r) => setTimeout(r, 500));
}
const failed = results.filter((r) => !r.ok);
console.log(`\n${results.length - failed.length}/${results.length} TREG(s) broadcast${failed.length ? ` (${failed.length} failed)` : ""}`);
// Verify by rebuilding the snapshot from the beacon.
console.log("\nverifying via TLD-beacon snapshot rebuild …");
await new Promise((r) => setTimeout(r, 2000)); // mempool propagation
const historyAfter = await wallet.provider.getHistory(TLD_BEACON);
const txsAfter = new Map();
for (const { tx_hash } of historyAfter) {
try { txsAfter.set(tx_hash, await wallet.provider.getRawTransactionObject(tx_hash)); }
catch { /* skip */ }
}
const after = buildTldSnapshot({ history: historyAfter, txs: txsAfter });
console.log(`snapshot root : ${after.root}`);
console.log(`snapshot tlds :`);
for (const t of after.tlds) {
console.log(` - ${t.tld.padEnd(6)} cat=${t.category.slice(0, 16)}… regHeight=${t.regHeight ?? "(mempool)"} txid=${t.regTxid.slice(0, 16)}…`);
}
const missing = SEED_TLDS.filter((t) => !after.tlds.some((s) => s.tld === t));
if (missing.length) {
console.log(`\nWARNING: still missing after broadcast: ${missing.join(" ")}`);
process.exit(1);
}
console.log(`\ndone — all ${SEED_TLDS.length} target TLDs present on the TLD beacon.`);
process.exit(0);