Snapshot in-progress work: Ariadne mobile, Theseus password manager, Hephaestus
Several concurrent workstreams committed together as a checkpoint:
- Ariadne mobile resolver — BchFetcher/Bns/MainActivity resolution logic,
AndroidManifest + build.ps1
- Theseus password manager — settings.html/chrome.html/settings-preload.js UI +
main.js wiring + package.json resource; Argus password-vault.js, record-picker.js
(+ tests) and resolver-web.d.ts
- Hephaestus — new BCH-wallet OIDC auth-proxy + Forgejo docker-compose and
restic/S3 scripts (secrets referenced via env only; Hephaestus/.env is gitignored)
- Argus public-gateway.mjs updates
- Docs — root README, Email README/RUNBOOK, VPS access runbooks (Checkers/Deviant),
site/hermes, WebsiteDev registry + faster-blocks, Failures/ AAAA-mangle writeup,
Decentralized Storage map, coordination notes
- .gitignore — exclude /.keys/ and Hephaestus/.env
2026-08-14 23:17:18 +02:00
|
|
|
export function normalizeName(input: any): string;
|
|
|
|
|
export function buildIndex({ electrum, WebSocket: WS, client, directIP }?: {
|
|
|
|
|
electrum?: {
|
|
|
|
|
url: string;
|
|
|
|
|
ip: string;
|
|
|
|
|
}[] | undefined;
|
|
|
|
|
directIP?: boolean | undefined;
|
|
|
|
|
}): Promise<Map<any, any>>;
|
|
|
|
|
export function resolveName(input: any, opts?: {}): Promise<any>;
|
|
|
|
|
export function parseElectrumRecord(records: any): ({
|
|
|
|
|
url: string;
|
|
|
|
|
ip: string;
|
|
|
|
|
} | {
|
|
|
|
|
url: string;
|
|
|
|
|
ip?: undefined;
|
|
|
|
|
})[];
|
|
|
|
|
export function getElectrumServers(index: any): ({
|
|
|
|
|
url: string;
|
|
|
|
|
ip: string;
|
|
|
|
|
} | {
|
|
|
|
|
url: string;
|
|
|
|
|
ip?: undefined;
|
|
|
|
|
})[];
|
|
|
|
|
export function fetchElectrumServers(opts?: {}): Promise<({
|
|
|
|
|
url: string;
|
|
|
|
|
ip: string;
|
|
|
|
|
} | {
|
|
|
|
|
url: string;
|
|
|
|
|
ip?: undefined;
|
|
|
|
|
})[]>;
|
|
|
|
|
export function parseTldsRecord(records: any): string[];
|
|
|
|
|
export function getBcnrTlds(index: any): string[];
|
|
|
|
|
export function fetchBcnrTlds(opts?: {}): Promise<string[]>;
|
|
|
|
|
export function isBcnrNativeTld(tldOrList: any, tld: any): boolean;
|
bns: one network table instead of chipnet constants copied into fifteen places
Every client hard-coded the chipnet beacons, address prefix and electrum
servers on its own: resolver, registrar config, wallets, gateway, indexer,
mirror scripts, the browser bundle and the mobile Java. A mainnet launch would
have meant finding all of them and hoping none was missed.
The table now lives in resolver-web.js, the one file every client already
shares, so it stays a single-file drop-in. BNS_NETWORK selects the record;
unset means chipnet, so nothing changes today: the live index resolves the
same 60 names and 20 TLDs, the 67 offline tests pass, and the dashboard,
market and studio load the same values through BNS.NETWORK.
The mainnet record carries the verified public servers, the prefix and its
own Sia bucket, but its beacons, start height and operator address are
deliberately null: requireBeacons() refuses to scan until they are pinned in
the order ROADMAP-MAINNET.md §6 requires. Bns.java reads a generated
BnsNetwork.java so the phone cannot drift from the desktop clients.
NETWORK-CONFIG.md records what reads the table and what a launch still pins.
2026-09-27 21:18:37 +02:00
|
|
|
export interface ElectrumServer { url: string; ip?: string }
|
|
|
|
|
export interface BnsNetwork {
|
|
|
|
|
id: "chipnet" | "mainnet";
|
|
|
|
|
label: string;
|
|
|
|
|
prefix: "bchtest" | "bitcoincash";
|
|
|
|
|
beacon: string | null;
|
|
|
|
|
beaconScripthash: string | null;
|
|
|
|
|
tldBeacon: string | null;
|
|
|
|
|
tldBeaconScripthash: string | null;
|
|
|
|
|
electrum: ElectrumServer[];
|
|
|
|
|
beaconOnly: RegExp;
|
|
|
|
|
electrumListName: string;
|
|
|
|
|
rootTldName: string;
|
|
|
|
|
bootstrapTlds: string[];
|
|
|
|
|
startHeight: number | null;
|
|
|
|
|
hostingBucket: string;
|
|
|
|
|
nameListUrl: string;
|
|
|
|
|
cdnIndexUrl: string;
|
|
|
|
|
nostrTags: { names: string; tlds: string };
|
|
|
|
|
explorerTx: string;
|
|
|
|
|
faucets: { name: string; url: string }[];
|
|
|
|
|
operatorAddress: string | null;
|
|
|
|
|
accountPath: string;
|
|
|
|
|
bchnRpcPort: number;
|
bns: the blocklist consumer, shipped with an empty list
A resolver that learns about blocklists only after the first scam needs a
release before it can warn anyone. The consumer ships now, pointed at a list
with no entries, so the first real report costs a transaction instead.
A list is an address, named by a BNS name whose bl record holds it. Entries
are RPT (the report), BLK and UBK. A flag counts only when it names a valid
report in the same list for the same name and reason, and only when its
transaction is spent FROM the list address: anyone can pay an address, so
being in its history proves nothing. That spend rule is what lets the
authority change hands later without the resolver learning the difference.
resolveName attaches blocked, blockReason, blockReportTxid and blockedBy to a
flagged name and leaves every other answer untouched. With no subscription it
is the old resolver exactly. A list that cannot be read never stops a name
from resolving. Lists are read from full electrum servers: the project's
beacon-only indexers answer 'no history' for any other address, which would
look like an empty list.
The default list is sirius-blocklist.x, a two-part name because a three-part
one collapses to its parent. Address conversion is dependency-free so this
file stays a single-file drop-in.
2026-10-04 02:32:58 +02:00
|
|
|
blocklists: { name: string; beacon: string; scripthash?: string }[];
|
bns: one network table instead of chipnet constants copied into fifteen places
Every client hard-coded the chipnet beacons, address prefix and electrum
servers on its own: resolver, registrar config, wallets, gateway, indexer,
mirror scripts, the browser bundle and the mobile Java. A mainnet launch would
have meant finding all of them and hoping none was missed.
The table now lives in resolver-web.js, the one file every client already
shares, so it stays a single-file drop-in. BNS_NETWORK selects the record;
unset means chipnet, so nothing changes today: the live index resolves the
same 60 names and 20 TLDs, the 67 offline tests pass, and the dashboard,
market and studio load the same values through BNS.NETWORK.
The mainnet record carries the verified public servers, the prefix and its
own Sia bucket, but its beacons, start height and operator address are
deliberately null: requireBeacons() refuses to scan until they are pinned in
the order ROADMAP-MAINNET.md §6 requires. Bns.java reads a generated
BnsNetwork.java so the phone cannot drift from the desktop clients.
NETWORK-CONFIG.md records what reads the table and what a launch still pins.
2026-09-27 21:18:37 +02:00
|
|
|
}
|
2026-10-04 16:53:58 +02:00
|
|
|
/** The transaction's single BNS payload; null when it has none or more than one. */
|
|
|
|
|
export function onlyPayload(vouts: any[]): any | null;
|
2026-10-04 16:13:04 +02:00
|
|
|
/** REG/TREG: is `mint` the only token of its category there is or can ever be? */
|
|
|
|
|
export function soleCertificate(tx: any, mint: any): boolean;
|
BNS: resolvers read covenant-held names
A name whose certificate sits in the registry covenant has an owner and an
expiry that are hashed into its address, not written on the chain. Until
now a resolver saw only "held by some script address", forever.
The transaction that moves the certificate now says the state (`c` in the
payload) and the resolver checks it against the address, using the
covenant's code from the network table. Nobody is trusted about who owns
such a name or until when.
Entering is the one step script cannot police - a certificate can be sent
to a covenant address with any expiry - so resolvers set the price: the
entering transaction pays the fund for whole years and may claim no more
than it paid for. Once a name is inside, only a verified state speaks for
it; otherwise an owner could announce their way back to a name that never
expires.
A name past its grace period stays taken but resolves to nothing, judged
at the chain tip (the indexer now answers what that is) or, failing that,
at the newest block in the beacon history, so a stale index lapses a name
late and never early.
Same rules in the gateway, the Ariadne resolver and the Android resolver;
the builders announce every move, and there is one to put an existing
name into the covenant. Chipnet's fund and steward are the operator key.
2026-10-04 18:08:00 +02:00
|
|
|
/** A covenant-held name's verified state (PROTOCOL-ADDENDUM-covenant-names.md). */
|
|
|
|
|
export interface CovenantState { ownerPkh: string; expiry: number; tier: number; version: number }
|
|
|
|
|
export const COVENANT_MAX_EXPIRY: number;
|
|
|
|
|
export function pkhToAddress(pkhHex: string, prefix?: string): string;
|
|
|
|
|
export function covenantTierIndex(name: string, covenant: any): number;
|
|
|
|
|
export function covenantLockHex(covenant: any, tierIndex: number, ownerPkh: string, expiry: number): string;
|
|
|
|
|
export function covenantClaim(payload: any, holder: any, name: string, network?: any): CovenantState | null;
|
|
|
|
|
export function covenantEntryPaid(claim: CovenantState, tx: any, height: number, network?: any): boolean;
|
|
|
|
|
export function admitCovenantState(entry: any, payload: any, holder: any, tx: any, height: number, network?: any): boolean;
|
|
|
|
|
export function covenantPhase(state: CovenantState | null | undefined, height: number, network?: any): { status: "active" | "idle" | "open"; expiry: number; idleEnd: number } | null;
|
|
|
|
|
export function historyHeight(history: Array<{ height: number }>): number;
|
|
|
|
|
export function applyLifecycle<T extends Map<string, any>>(names: T, height: number, network?: any): T;
|
2026-10-04 01:39:14 +02:00
|
|
|
/** REL: does `tx` burn `entry`'s certificate, spending it from a beacon transaction in `txs`? */
|
|
|
|
|
export function burnsCertificate(tx: any, entry: { category: string }, txs: Map<string, any>): boolean;
|
|
|
|
|
/** One-block gap after a release. `releasedAt` undefined = never released. */
|
|
|
|
|
export function mayReRegister(releasedAt: number | undefined, height: number): boolean;
|
bns: the blocklist consumer, shipped with an empty list
A resolver that learns about blocklists only after the first scam needs a
release before it can warn anyone. The consumer ships now, pointed at a list
with no entries, so the first real report costs a transaction instead.
A list is an address, named by a BNS name whose bl record holds it. Entries
are RPT (the report), BLK and UBK. A flag counts only when it names a valid
report in the same list for the same name and reason, and only when its
transaction is spent FROM the list address: anyone can pay an address, so
being in its history proves nothing. That spend rule is what lets the
authority change hands later without the resolver learning the difference.
resolveName attaches blocked, blockReason, blockReportTxid and blockedBy to a
flagged name and leaves every other answer untouched. With no subscription it
is the old resolver exactly. A list that cannot be read never stops a name
from resolving. Lists are read from full electrum servers: the project's
beacon-only indexers answer 'no history' for any other address, which would
look like an empty list.
The default list is sirius-blocklist.x, a two-part name because a three-part
one collapses to its parent. Address conversion is dependency-free so this
file stays a single-file drop-in.
2026-10-04 02:32:58 +02:00
|
|
|
export interface BlockFlag {
|
|
|
|
|
name: string; reason: string; reportTxid: string; txid: string; height: number;
|
|
|
|
|
evidence: string | null; vote: string | null; source: string | null; address: string;
|
|
|
|
|
}
|
|
|
|
|
export function sha256(bytes: Uint8Array): Uint8Array;
|
|
|
|
|
export function addressToLockHex(address: string): string;
|
|
|
|
|
export function addressToScripthash(address: string): string;
|
|
|
|
|
export const BLOCK_REASONS: Set<string>;
|
|
|
|
|
/** Reduce one list's history to its current flags (pure). */
|
|
|
|
|
export function reduceBlocklist(o: { history: { tx_hash: string; height: number }[]; txs: Map<string, any> | Record<string, any>; address: string; source?: string | null }): Map<string, BlockFlag>;
|
|
|
|
|
export function blocklistAddress(list: { name?: string; beacon?: string }, index?: Map<string, any> | null): string | null;
|
|
|
|
|
export function buildBlocklists(o?: { network?: any; lists?: { name?: string; beacon?: string }[]; index?: Map<string, any> | null; electrum?: any; WebSocket?: any; client?: any; directIP?: boolean }): Promise<Map<string, BlockFlag & { sources: BlockFlag[] }>>;
|
|
|
|
|
export function withBlockFlag<T extends { name: string }>(entry: T, flags: Map<string, BlockFlag> | null): T;
|
bns: one network table instead of chipnet constants copied into fifteen places
Every client hard-coded the chipnet beacons, address prefix and electrum
servers on its own: resolver, registrar config, wallets, gateway, indexer,
mirror scripts, the browser bundle and the mobile Java. A mainnet launch would
have meant finding all of them and hoping none was missed.
The table now lives in resolver-web.js, the one file every client already
shares, so it stays a single-file drop-in. BNS_NETWORK selects the record;
unset means chipnet, so nothing changes today: the live index resolves the
same 60 names and 20 TLDs, the 67 offline tests pass, and the dashboard,
market and studio load the same values through BNS.NETWORK.
The mainnet record carries the verified public servers, the prefix and its
own Sia bucket, but its beacons, start height and operator address are
deliberately null: requireBeacons() refuses to scan until they are pinned in
the order ROADMAP-MAINNET.md §6 requires. Bns.java reads a generated
BnsNetwork.java so the phone cannot drift from the desktop clients.
NETWORK-CONFIG.md records what reads the table and what a launch still pins.
2026-09-27 21:18:37 +02:00
|
|
|
export const NETWORKS: { chipnet: BnsNetwork; mainnet: BnsNetwork };
|
|
|
|
|
export const DEFAULT_NETWORK_ID: "chipnet";
|
|
|
|
|
export function networkIdFromEnv(): string;
|
|
|
|
|
export function getNetwork(idOrRecord?: string | BnsNetwork): BnsNetwork;
|
|
|
|
|
export const NETWORK: BnsNetwork;
|
|
|
|
|
export function requireBeacons(network?: string | BnsNetwork): BnsNetwork;
|
|
|
|
|
export const BEACON: string | null;
|
|
|
|
|
export const BEACON_SCRIPTHASH: string | null;
|
|
|
|
|
export const TLD_BEACON: string | null;
|
|
|
|
|
export const TLD_BEACON_SCRIPTHASH: string | null;
|
|
|
|
|
export const ELECTRUM: ElectrumServer[];
|
Snapshot in-progress work: Ariadne mobile, Theseus password manager, Hephaestus
Several concurrent workstreams committed together as a checkpoint:
- Ariadne mobile resolver — BchFetcher/Bns/MainActivity resolution logic,
AndroidManifest + build.ps1
- Theseus password manager — settings.html/chrome.html/settings-preload.js UI +
main.js wiring + package.json resource; Argus password-vault.js, record-picker.js
(+ tests) and resolver-web.d.ts
- Hephaestus — new BCH-wallet OIDC auth-proxy + Forgejo docker-compose and
restic/S3 scripts (secrets referenced via env only; Hephaestus/.env is gitignored)
- Argus public-gateway.mjs updates
- Docs — root README, Email README/RUNBOOK, VPS access runbooks (Checkers/Deviant),
site/hermes, WebsiteDev registry + faster-blocks, Failures/ AAAA-mangle writeup,
Decentralized Storage map, coordination notes
- .gitignore — exclude /.keys/ and Hephaestus/.env
2026-08-14 23:17:18 +02:00
|
|
|
export const PREFIX: "BNS1";
|
|
|
|
|
export const TLD: ".bch";
|
|
|
|
|
export const DEFAULT_TLD: "bch";
|
|
|
|
|
export const CHIPNET_ELECTRUM: {
|
|
|
|
|
url: string;
|
|
|
|
|
ip: string;
|
|
|
|
|
}[];
|
bns: one network table instead of chipnet constants copied into fifteen places
Every client hard-coded the chipnet beacons, address prefix and electrum
servers on its own: resolver, registrar config, wallets, gateway, indexer,
mirror scripts, the browser bundle and the mobile Java. A mainnet launch would
have meant finding all of them and hoping none was missed.
The table now lives in resolver-web.js, the one file every client already
shares, so it stays a single-file drop-in. BNS_NETWORK selects the record;
unset means chipnet, so nothing changes today: the live index resolves the
same 60 names and 20 TLDs, the 67 offline tests pass, and the dashboard,
market and studio load the same values through BNS.NETWORK.
The mainnet record carries the verified public servers, the prefix and its
own Sia bucket, but its beacons, start height and operator address are
deliberately null: requireBeacons() refuses to scan until they are pinned in
the order ROADMAP-MAINNET.md §6 requires. Bns.java reads a generated
BnsNetwork.java so the phone cannot drift from the desktop clients.
NETWORK-CONFIG.md records what reads the table and what a launch still pins.
2026-09-27 21:18:37 +02:00
|
|
|
export const ELECTRUM_LIST_NAME: string;
|
|
|
|
|
export const ROOT_TLD_NAME: string;
|
Snapshot in-progress work: Ariadne mobile, Theseus password manager, Hephaestus
Several concurrent workstreams committed together as a checkpoint:
- Ariadne mobile resolver — BchFetcher/Bns/MainActivity resolution logic,
AndroidManifest + build.ps1
- Theseus password manager — settings.html/chrome.html/settings-preload.js UI +
main.js wiring + package.json resource; Argus password-vault.js, record-picker.js
(+ tests) and resolver-web.d.ts
- Hephaestus — new BCH-wallet OIDC auth-proxy + Forgejo docker-compose and
restic/S3 scripts (secrets referenced via env only; Hephaestus/.env is gitignored)
- Argus public-gateway.mjs updates
- Docs — root README, Email README/RUNBOOK, VPS access runbooks (Checkers/Deviant),
site/hermes, WebsiteDev registry + faster-blocks, Failures/ AAAA-mangle writeup,
Decentralized Storage map, coordination notes
- .gitignore — exclude /.keys/ and Hephaestus/.env
2026-08-14 23:17:18 +02:00
|
|
|
export const BOOTSTRAP_TLDS: string[];
|