@ust-protocol/ots-verify 1.0.0-rc.4 → 1.0.0-rc.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.mjs +17 -6
- package/package.json +2 -2
package/index.mjs
CHANGED
|
@@ -50,7 +50,7 @@ export function parseOtsBitcoin(ots) {
|
|
|
50
50
|
return found ? { height: found.height, merkle: found.merkle, digest } : null;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
-
export function makeSubstrateVerify({ upgrade = true, fetchImpl = fetch, explorers = EXPLORERS, minConfirmations = 6 } = {}) {
|
|
53
|
+
export function makeSubstrateVerify({ upgrade = true, fetchImpl = fetch, explorers = EXPLORERS, minConfirmations = 6, quorum = 2 } = {}) {
|
|
54
54
|
return async function substrateVerify(anchor, root) {
|
|
55
55
|
const sub = anchor?.substrate ?? anchor?.anchor?.substrate;
|
|
56
56
|
if (sub && sub !== 'bitcoin-ots') return null; // not ours → router delegates onward
|
|
@@ -72,19 +72,30 @@ export function makeSubstrateVerify({ upgrade = true, fetchImpl = fetch, explore
|
|
|
72
72
|
if (!parsed || typeof parsed.height !== 'number') return { final: false, time: 'unproven' };
|
|
73
73
|
const wantMerkle = Buffer.from(parsed.merkle).reverse().toString('hex'); // block header displays reversed
|
|
74
74
|
|
|
75
|
+
// #71 — TRUST TERMINATION HONESTY. A SINGLE explorer is a TRUSTED ORACLE (it could serve a self-consistent
|
|
76
|
+
// fake block/merkle/tip). So finality REQUIRES AGREEMENT across ≥ `quorum` INDEPENDENT explorers, and the
|
|
77
|
+
// result is labelled `explorer-corroborated` — NOT trustless Bitcoin finality. Trustless needs a real node /
|
|
78
|
+
// SPV header-chain (PoW-validated); that is an OPERATOR plugin injected through this SAME substrateVerify
|
|
79
|
+
// seam. This plugin is honest about its ceiling; a reachable explorer that DISAGREES on the merkle root is a
|
|
80
|
+
// definitive NO.
|
|
81
|
+
const need = Math.max(1, Math.min(quorum, explorers.length));
|
|
82
|
+
let agree = 0, time = null, conflict = false;
|
|
75
83
|
for (const base of explorers) {
|
|
76
84
|
try {
|
|
77
85
|
const hash = (await (await fetchImpl(`${base}/block-height/${parsed.height}`, { signal: AbortSignal.timeout(10000) })).text()).trim();
|
|
78
86
|
if (!/^[0-9a-f]{64}$/.test(hash)) continue;
|
|
79
87
|
const blk = await (await fetchImpl(`${base}/block/${hash}`, { signal: AbortSignal.timeout(10000) })).json();
|
|
80
|
-
if (!blk || blk.merkle_root !==
|
|
88
|
+
if (!blk || typeof blk.merkle_root !== 'string') continue;
|
|
89
|
+
if (blk.merkle_root !== wantMerkle) { conflict = true; break; } // an independent source DISAGREES → NO
|
|
81
90
|
const tip = Number((await (await fetchImpl(`${base}/blocks/tip/height`, { signal: AbortSignal.timeout(10000) })).text()).trim());
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
91
|
+
if (!Number.isFinite(tip) || tip - parsed.height + 1 < minConfirmations) continue; // this source lags on burial → don't count
|
|
92
|
+
agree++;
|
|
93
|
+
time = blk.timestamp ? new Date(blk.timestamp * 1000).toISOString().slice(0, 19) + 'Z' : 'bitcoin-block-' + parsed.height;
|
|
94
|
+
if (agree >= need) return { final: true, time, assurance: 'explorer-corroborated', explorers: agree };
|
|
85
95
|
} catch { /* explorer unreachable — try the next */ }
|
|
86
96
|
}
|
|
87
|
-
return { final: false, time: 'unproven' };
|
|
97
|
+
if (conflict) return { final: false, time: 'unproven' }; // a real merkle conflict
|
|
98
|
+
return { final: false, time: 'unproven', detail: `only ${agree}/${need} independent explorers corroborated` };
|
|
88
99
|
};
|
|
89
100
|
}
|
|
90
101
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ust-protocol/ots-verify",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
4
|
-
"description": "Opt-in Bitcoin/OpenTimestamps substrateVerify for UST anchors — cross-checks a genesis/hour root against a REAL Bitcoin block header + >=6 confirmations. #68 witness / #69 A2.",
|
|
3
|
+
"version": "1.0.0-rc.5",
|
|
4
|
+
"description": "Opt-in Bitcoin/OpenTimestamps substrateVerify for UST anchors — cross-checks a genesis/hour root against a REAL Bitcoin block header + >=6 confirmations. #68 witness / #69 A2 / #71 explorer-corroborated (2-of-N).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.mjs",
|
|
7
7
|
"exports": "./index.mjs",
|