@mikeargento/bitgraph 1.1.0 → 1.1.1
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/README.md +49 -40
- package/dist/__tests__/audit-anchors.test.d.ts +2 -0
- package/dist/__tests__/audit-anchors.test.d.ts.map +1 -0
- package/dist/__tests__/audit-anchors.test.js +152 -0
- package/dist/__tests__/audit-anchors.test.js.map +1 -0
- package/dist/__tests__/audit-anomalies.test.d.ts +2 -0
- package/dist/__tests__/audit-anomalies.test.d.ts.map +1 -0
- package/dist/__tests__/audit-anomalies.test.js +663 -0
- package/dist/__tests__/audit-anomalies.test.js.map +1 -0
- package/dist/__tests__/audit-attestation.test.d.ts +2 -0
- package/dist/__tests__/audit-attestation.test.d.ts.map +1 -0
- package/dist/__tests__/audit-attestation.test.js +403 -0
- package/dist/__tests__/audit-attestation.test.js.map +1 -0
- package/dist/__tests__/audit-bench-smoke.test.d.ts +2 -0
- package/dist/__tests__/audit-bench-smoke.test.d.ts.map +1 -0
- package/dist/__tests__/audit-bench-smoke.test.js +87 -0
- package/dist/__tests__/audit-bench-smoke.test.js.map +1 -0
- package/dist/__tests__/audit-boundary.test.d.ts +20 -0
- package/dist/__tests__/audit-boundary.test.d.ts.map +1 -0
- package/dist/__tests__/audit-boundary.test.js +84 -0
- package/dist/__tests__/audit-boundary.test.js.map +1 -0
- package/dist/__tests__/audit-cli.test.d.ts +2 -0
- package/dist/__tests__/audit-cli.test.d.ts.map +1 -0
- package/dist/__tests__/audit-cli.test.js +239 -0
- package/dist/__tests__/audit-cli.test.js.map +1 -0
- package/dist/__tests__/audit-dependencies.test.d.ts +2 -0
- package/dist/__tests__/audit-dependencies.test.d.ts.map +1 -0
- package/dist/__tests__/audit-dependencies.test.js +116 -0
- package/dist/__tests__/audit-dependencies.test.js.map +1 -0
- package/dist/__tests__/audit-fixtures.d.ts +265 -0
- package/dist/__tests__/audit-fixtures.d.ts.map +1 -0
- package/dist/__tests__/audit-fixtures.js +511 -0
- package/dist/__tests__/audit-fixtures.js.map +1 -0
- package/dist/__tests__/audit-ingest.test.d.ts +2 -0
- package/dist/__tests__/audit-ingest.test.d.ts.map +1 -0
- package/dist/__tests__/audit-ingest.test.js +473 -0
- package/dist/__tests__/audit-ingest.test.js.map +1 -0
- package/dist/__tests__/audit-memory-ingest.test.d.ts +12 -0
- package/dist/__tests__/audit-memory-ingest.test.d.ts.map +1 -0
- package/dist/__tests__/audit-memory-ingest.test.js +120 -0
- package/dist/__tests__/audit-memory-ingest.test.js.map +1 -0
- package/dist/__tests__/audit-property.test.d.ts +2 -0
- package/dist/__tests__/audit-property.test.d.ts.map +1 -0
- package/dist/__tests__/audit-property.test.js +771 -0
- package/dist/__tests__/audit-property.test.js.map +1 -0
- package/dist/__tests__/audit-real-fixtures.test.d.ts +2 -0
- package/dist/__tests__/audit-real-fixtures.test.d.ts.map +1 -0
- package/dist/__tests__/audit-real-fixtures.test.js +132 -0
- package/dist/__tests__/audit-real-fixtures.test.js.map +1 -0
- package/dist/__tests__/audit-real-live.test.d.ts +2 -0
- package/dist/__tests__/audit-real-live.test.d.ts.map +1 -0
- package/dist/__tests__/audit-real-live.test.js +107 -0
- package/dist/__tests__/audit-real-live.test.js.map +1 -0
- package/dist/__tests__/audit-reconstruct.test.d.ts +2 -0
- package/dist/__tests__/audit-reconstruct.test.d.ts.map +1 -0
- package/dist/__tests__/audit-reconstruct.test.js +287 -0
- package/dist/__tests__/audit-reconstruct.test.js.map +1 -0
- package/dist/__tests__/audit-report.test.d.ts +2 -0
- package/dist/__tests__/audit-report.test.d.ts.map +1 -0
- package/dist/__tests__/audit-report.test.js +186 -0
- package/dist/__tests__/audit-report.test.js.map +1 -0
- package/dist/__tests__/audit-roundtrip.test.d.ts +2 -0
- package/dist/__tests__/audit-roundtrip.test.d.ts.map +1 -0
- package/dist/__tests__/audit-roundtrip.test.js +368 -0
- package/dist/__tests__/audit-roundtrip.test.js.map +1 -0
- package/dist/__tests__/audit-temporal.test.d.ts +2 -0
- package/dist/__tests__/audit-temporal.test.d.ts.map +1 -0
- package/dist/__tests__/audit-temporal.test.js +364 -0
- package/dist/__tests__/audit-temporal.test.js.map +1 -0
- package/dist/__tests__/audit-tiers.test.d.ts +2 -0
- package/dist/__tests__/audit-tiers.test.d.ts.map +1 -0
- package/dist/__tests__/audit-tiers.test.js +282 -0
- package/dist/__tests__/audit-tiers.test.js.map +1 -0
- package/dist/__tests__/audit-witness-real.test.d.ts +19 -0
- package/dist/__tests__/audit-witness-real.test.d.ts.map +1 -0
- package/dist/__tests__/audit-witness-real.test.js +82 -0
- package/dist/__tests__/audit-witness-real.test.js.map +1 -0
- package/dist/__tests__/audit-witness.test.d.ts +2 -0
- package/dist/__tests__/audit-witness.test.d.ts.map +1 -0
- package/dist/__tests__/audit-witness.test.js +308 -0
- package/dist/__tests__/audit-witness.test.js.map +1 -0
- package/dist/__tests__/chain-hash-anchor.test.d.ts +22 -0
- package/dist/__tests__/chain-hash-anchor.test.d.ts.map +1 -0
- package/dist/__tests__/chain-hash-anchor.test.js +55 -0
- package/dist/__tests__/chain-hash-anchor.test.js.map +1 -0
- package/dist/__tests__/declared-proof-fixture.d.ts +66 -0
- package/dist/__tests__/declared-proof-fixture.d.ts.map +1 -0
- package/dist/__tests__/declared-proof-fixture.js +66 -0
- package/dist/__tests__/declared-proof-fixture.js.map +1 -0
- package/dist/__tests__/mock-proof-fixture.d.ts +15 -0
- package/dist/__tests__/mock-proof-fixture.d.ts.map +1 -0
- package/dist/__tests__/mock-proof-fixture.js +34 -0
- package/dist/__tests__/mock-proof-fixture.js.map +1 -0
- package/dist/__tests__/proof-hash-regression.test.js +4 -43
- package/dist/__tests__/proof-hash-regression.test.js.map +1 -1
- package/dist/__tests__/proof-hash.test.js +3 -21
- package/dist/__tests__/proof-hash.test.js.map +1 -1
- package/dist/__tests__/proof-integrity.test.d.ts +2 -0
- package/dist/__tests__/proof-integrity.test.d.ts.map +1 -0
- package/dist/__tests__/proof-integrity.test.js +426 -0
- package/dist/__tests__/proof-integrity.test.js.map +1 -0
- package/dist/__tests__/realistic-proof-fixture.d.ts +56 -0
- package/dist/__tests__/realistic-proof-fixture.d.ts.map +1 -0
- package/dist/__tests__/realistic-proof-fixture.js +57 -0
- package/dist/__tests__/realistic-proof-fixture.js.map +1 -0
- package/dist/__tests__/verifier.test.js +74 -0
- package/dist/__tests__/verifier.test.js.map +1 -1
- package/package.json +10 -5
- package/src/__tests__/audit-anchors.test.ts +188 -0
- package/src/__tests__/audit-anomalies.test.ts +815 -0
- package/src/__tests__/audit-attestation.test.ts +529 -0
- package/src/__tests__/audit-bench-smoke.test.ts +108 -0
- package/src/__tests__/audit-boundary.test.ts +96 -0
- package/src/__tests__/audit-cli.test.ts +288 -0
- package/src/__tests__/audit-dependencies.test.ts +141 -0
- package/src/__tests__/audit-fixtures.ts +736 -0
- package/src/__tests__/audit-ingest.test.ts +575 -0
- package/src/__tests__/audit-memory-ingest.test.ts +140 -0
- package/src/__tests__/audit-property.test.ts +892 -0
- package/src/__tests__/audit-real-fixtures.test.ts +153 -0
- package/src/__tests__/audit-real-live.test.ts +128 -0
- package/src/__tests__/audit-reconstruct.test.ts +353 -0
- package/src/__tests__/audit-report.test.ts +222 -0
- package/src/__tests__/audit-roundtrip.test.ts +464 -0
- package/src/__tests__/audit-temporal.test.ts +446 -0
- package/src/__tests__/audit-tiers.test.ts +343 -0
- package/src/__tests__/audit-witness-real.test.ts +92 -0
- package/src/__tests__/audit-witness.test.ts +345 -0
- package/src/__tests__/chain-hash-anchor.test.ts +67 -0
- package/src/__tests__/declared-proof-fixture.ts +65 -0
- package/src/__tests__/mock-proof-fixture.ts +36 -0
- package/src/__tests__/proof-hash-regression.test.ts +4 -44
- package/src/__tests__/proof-hash.test.ts +3 -22
- package/src/__tests__/proof-integrity.test.ts +541 -0
- package/src/__tests__/real-fixtures/anchor-after-112762.json +47 -0
- package/src/__tests__/real-fixtures/anchor-with-ethereum-112758.json +47 -0
- package/src/__tests__/real-fixtures/live-proof-0.json +42 -0
- package/src/__tests__/real-fixtures/live-proof-1.json +43 -0
- package/src/__tests__/real-fixtures/live-proof-2.json +43 -0
- package/src/__tests__/real-fixtures/successor-112760.json +38 -0
- package/src/__tests__/real-fixtures/witness-25525146.json +6 -0
- package/src/__tests__/real-fixtures/witness-25525147.json +6 -0
- package/src/__tests__/realistic-proof-fixture.ts +57 -0
- package/src/__tests__/verifier.test.ts +83 -0
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
// Copyright (c) Mike Argento. All rights reserved. See LICENSE.
|
|
2
|
+
/**
|
|
3
|
+
* Anchor witness verification tests (bundle spec section 10.3).
|
|
4
|
+
*
|
|
5
|
+
* The synthetic header is a 20-item RLP list with the block number at
|
|
6
|
+
* index 8 and the timestamp at index 11; its Keccak-256 hash is the
|
|
7
|
+
* "block hash", the anchor's signed attribution.message is that hash,
|
|
8
|
+
* and the anchor's artifact digest is SHA-256 over the hash STRING,
|
|
9
|
+
* exactly like bitcoin-anchor.ts. Full verification yields the header
|
|
10
|
+
* timestamp; every single-point corruption fails with its own stable
|
|
11
|
+
* reason and confers nothing.
|
|
12
|
+
*/
|
|
13
|
+
import { describe, it } from "node:test";
|
|
14
|
+
import * as assert from "node:assert/strict";
|
|
15
|
+
import { keccak_256 } from "@noble/hashes/sha3";
|
|
16
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
17
|
+
import { identifyAnchors, ingestBundle, verifyAnchorWitness, verifyAnchorWitnesses, verifyObservedProofs, } from "@mikeargento/bitgraph-audit";
|
|
18
|
+
import { b64, makeAnchorProof, makeEthereumHeader, makeTempDir, proofJson, utf8, witnessJson, writeBundleDir, } from "./audit-fixtures.js";
|
|
19
|
+
const BLOCK_NUMBER = 24800448;
|
|
20
|
+
const TIMESTAMP = 1750000000;
|
|
21
|
+
const HEADER = makeEthereumHeader({ blockNumber: BLOCK_NUMBER, timestamp: TIMESTAMP });
|
|
22
|
+
const BLOCK_HASH = `0x${Buffer.from(keccak_256(HEADER.headerBytes)).toString("hex")}`;
|
|
23
|
+
async function pipeline(files) {
|
|
24
|
+
const dir = await makeTempDir("bg-audit-witness-");
|
|
25
|
+
await writeBundleDir(dir, files);
|
|
26
|
+
const ingest = await ingestBundle(dir);
|
|
27
|
+
await verifyObservedProofs(ingest);
|
|
28
|
+
return { ingest, anchors: identifyAnchors(ingest) };
|
|
29
|
+
}
|
|
30
|
+
function goodWitness() {
|
|
31
|
+
return witnessJson({
|
|
32
|
+
headerRlpHex: HEADER.headerRlpHex,
|
|
33
|
+
blockNumber: BLOCK_NUMBER,
|
|
34
|
+
blockHash: BLOCK_HASH,
|
|
35
|
+
network: "ethereum-mainnet",
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
describe("audit witness: full verification", () => {
|
|
39
|
+
it("passes every step and yields the header timestamp as the only wall-clock evidence", async () => {
|
|
40
|
+
const anchor = await makeAnchorProof({
|
|
41
|
+
blockHash: BLOCK_HASH,
|
|
42
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
43
|
+
epochId: "E-W1",
|
|
44
|
+
counter: "4",
|
|
45
|
+
slotCounter: "3",
|
|
46
|
+
});
|
|
47
|
+
const { ingest, anchors } = await pipeline({
|
|
48
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
49
|
+
"witnesses/w.json": goodWitness(),
|
|
50
|
+
});
|
|
51
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
52
|
+
assert.equal(analysis.outcomes.length, 1);
|
|
53
|
+
const outcome = analysis.outcomes[0];
|
|
54
|
+
assert.equal(outcome.verified, true);
|
|
55
|
+
assert.equal(outcome.anchorProofHash, anchor.proofHash);
|
|
56
|
+
assert.equal(outcome.computedBlockHash, BLOCK_HASH);
|
|
57
|
+
assert.equal(outcome.blockNumber, String(BLOCK_NUMBER));
|
|
58
|
+
assert.equal(outcome.timestamp, TIMESTAMP);
|
|
59
|
+
assert.equal(outcome.reason, undefined);
|
|
60
|
+
assert.equal(analysis.findings.length, 0);
|
|
61
|
+
});
|
|
62
|
+
it("compares the hash case-insensitively but binds the digest to the exact signed string", async () => {
|
|
63
|
+
// The anchor signed an UPPERCASE hash string; the digest covers that
|
|
64
|
+
// exact string. Step 3 lowercases for comparison, step 4 does not.
|
|
65
|
+
const upper = `0x${BLOCK_HASH.slice(2).toUpperCase()}`;
|
|
66
|
+
const anchor = await makeAnchorProof({
|
|
67
|
+
blockHash: upper,
|
|
68
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
69
|
+
epochId: "E-W2",
|
|
70
|
+
counter: "2",
|
|
71
|
+
});
|
|
72
|
+
const { ingest, anchors } = await pipeline({
|
|
73
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
74
|
+
"witnesses/w.json": goodWitness(),
|
|
75
|
+
});
|
|
76
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
77
|
+
assert.equal(analysis.outcomes.length, 1);
|
|
78
|
+
assert.equal(analysis.outcomes[0].verified, true);
|
|
79
|
+
assert.equal(analysis.outcomes[0].timestamp, TIMESTAMP);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
describe("audit witness: single-point corruptions fail with distinct stable reasons", () => {
|
|
83
|
+
it("wrong claimed blockHash: witness-claimed-hash-mismatch", async () => {
|
|
84
|
+
const anchor = await makeAnchorProof({
|
|
85
|
+
blockHash: BLOCK_HASH,
|
|
86
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
87
|
+
epochId: "E-W3",
|
|
88
|
+
counter: "2",
|
|
89
|
+
});
|
|
90
|
+
const wrongClaim = `0x${"ab".repeat(32)}`;
|
|
91
|
+
const { ingest, anchors } = await pipeline({
|
|
92
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
93
|
+
"witnesses/w.json": witnessJson({
|
|
94
|
+
headerRlpHex: HEADER.headerRlpHex,
|
|
95
|
+
blockNumber: BLOCK_NUMBER,
|
|
96
|
+
blockHash: wrongClaim,
|
|
97
|
+
}),
|
|
98
|
+
});
|
|
99
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
100
|
+
const outcome = analysis.outcomes[0];
|
|
101
|
+
assert.equal(outcome.verified, false);
|
|
102
|
+
assert.equal(outcome.reason, "witness-claimed-hash-mismatch");
|
|
103
|
+
assert.equal(outcome.timestamp, undefined, "a rejected witness confers nothing");
|
|
104
|
+
assert.ok(analysis.findings.some((f) => f.code === "witness-claimed-hash-mismatch"));
|
|
105
|
+
});
|
|
106
|
+
it("wrong artifact digest: witness-digest-mismatch", async () => {
|
|
107
|
+
// Validly signed anchor whose digest covers a different string, so the
|
|
108
|
+
// proof itself verifies but the message-to-digest binding fails.
|
|
109
|
+
const anchor = await makeAnchorProof({
|
|
110
|
+
blockHash: BLOCK_HASH,
|
|
111
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
112
|
+
epochId: "E-W4",
|
|
113
|
+
counter: "2",
|
|
114
|
+
digestB64: b64(sha256(utf8("some other committed artifact"))),
|
|
115
|
+
});
|
|
116
|
+
const { ingest, anchors } = await pipeline({
|
|
117
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
118
|
+
"witnesses/w.json": goodWitness(),
|
|
119
|
+
});
|
|
120
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
121
|
+
const outcome = analysis.outcomes[0];
|
|
122
|
+
assert.equal(outcome.verified, false);
|
|
123
|
+
assert.equal(outcome.reason, "witness-digest-mismatch");
|
|
124
|
+
assert.equal(outcome.timestamp, undefined);
|
|
125
|
+
});
|
|
126
|
+
it("wrong claimed blockNumber: witness-block-number-mismatch", async () => {
|
|
127
|
+
const anchor = await makeAnchorProof({
|
|
128
|
+
blockHash: BLOCK_HASH,
|
|
129
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
130
|
+
epochId: "E-W5",
|
|
131
|
+
counter: "2",
|
|
132
|
+
});
|
|
133
|
+
const { ingest, anchors } = await pipeline({
|
|
134
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
135
|
+
"witnesses/w.json": witnessJson({
|
|
136
|
+
headerRlpHex: HEADER.headerRlpHex,
|
|
137
|
+
blockNumber: BLOCK_NUMBER + 1,
|
|
138
|
+
blockHash: BLOCK_HASH,
|
|
139
|
+
}),
|
|
140
|
+
});
|
|
141
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
142
|
+
const outcome = analysis.outcomes[0];
|
|
143
|
+
assert.equal(outcome.verified, false);
|
|
144
|
+
assert.equal(outcome.reason, "witness-block-number-mismatch");
|
|
145
|
+
assert.match(outcome.detail, /witness claims blockNumber/);
|
|
146
|
+
});
|
|
147
|
+
it("signed Etherscan URL disagreeing with the header: witness-block-number-mismatch", async () => {
|
|
148
|
+
const anchor = await makeAnchorProof({
|
|
149
|
+
blockHash: BLOCK_HASH,
|
|
150
|
+
blockNumber: String(BLOCK_NUMBER + 7),
|
|
151
|
+
epochId: "E-W6",
|
|
152
|
+
counter: "2",
|
|
153
|
+
});
|
|
154
|
+
const { ingest, anchors } = await pipeline({
|
|
155
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
156
|
+
"witnesses/w.json": goodWitness(),
|
|
157
|
+
});
|
|
158
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
159
|
+
const outcome = analysis.outcomes[0];
|
|
160
|
+
assert.equal(outcome.verified, false);
|
|
161
|
+
assert.equal(outcome.reason, "witness-block-number-mismatch");
|
|
162
|
+
assert.match(outcome.detail, /Etherscan URL/);
|
|
163
|
+
});
|
|
164
|
+
it("tampered RLP header bytes: witness-hash-mismatch", async () => {
|
|
165
|
+
const anchor = await makeAnchorProof({
|
|
166
|
+
blockHash: BLOCK_HASH,
|
|
167
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
168
|
+
epochId: "E-W7",
|
|
169
|
+
counter: "2",
|
|
170
|
+
});
|
|
171
|
+
// Flip content bytes in the middle: still well-formed RLP, different
|
|
172
|
+
// Keccak hash. The witness still reaches its intended anchor through
|
|
173
|
+
// the claimed hash and fails loudly at step 3.
|
|
174
|
+
const tampered = HEADER.headerRlpHex.slice(0, 40) +
|
|
175
|
+
(HEADER.headerRlpHex[40] === "f" ? "e" : "f") +
|
|
176
|
+
HEADER.headerRlpHex.slice(41);
|
|
177
|
+
const { ingest, anchors } = await pipeline({
|
|
178
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
179
|
+
"witnesses/w.json": witnessJson({
|
|
180
|
+
headerRlpHex: tampered,
|
|
181
|
+
blockNumber: BLOCK_NUMBER,
|
|
182
|
+
blockHash: BLOCK_HASH,
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
186
|
+
const outcome = analysis.outcomes[0];
|
|
187
|
+
assert.equal(outcome.verified, false);
|
|
188
|
+
assert.equal(outcome.reason, "witness-hash-mismatch");
|
|
189
|
+
assert.equal(outcome.timestamp, undefined);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
describe("audit witness: malformed and unusable witnesses", () => {
|
|
193
|
+
it("field violations fail with witness-malformed", async () => {
|
|
194
|
+
const anchor = await makeAnchorProof({
|
|
195
|
+
blockHash: BLOCK_HASH,
|
|
196
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
197
|
+
epochId: "E-W8",
|
|
198
|
+
counter: "2",
|
|
199
|
+
});
|
|
200
|
+
const { ingest, anchors } = await pipeline({
|
|
201
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
202
|
+
"witnesses/no-header.json": witnessJson({
|
|
203
|
+
blockNumber: BLOCK_NUMBER,
|
|
204
|
+
blockHash: BLOCK_HASH,
|
|
205
|
+
omit: ["headerRlpHex"],
|
|
206
|
+
}),
|
|
207
|
+
"witnesses/string-number.json": witnessJson({
|
|
208
|
+
headerRlpHex: HEADER.headerRlpHex,
|
|
209
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
210
|
+
blockHash: BLOCK_HASH,
|
|
211
|
+
}),
|
|
212
|
+
"witnesses/bad-hash-shape.json": witnessJson({
|
|
213
|
+
headerRlpHex: HEADER.headerRlpHex,
|
|
214
|
+
blockNumber: BLOCK_NUMBER,
|
|
215
|
+
blockHash: "28ed3639",
|
|
216
|
+
}),
|
|
217
|
+
});
|
|
218
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
219
|
+
assert.equal(analysis.outcomes.length, 3);
|
|
220
|
+
for (const outcome of analysis.outcomes) {
|
|
221
|
+
assert.equal(outcome.verified, false);
|
|
222
|
+
assert.equal(outcome.reason, "witness-malformed");
|
|
223
|
+
assert.equal(outcome.timestamp, undefined);
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
it("structurally invalid RLP fails with witness-rlp-invalid", async () => {
|
|
227
|
+
const anchor = await makeAnchorProof({
|
|
228
|
+
blockHash: BLOCK_HASH,
|
|
229
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
230
|
+
epochId: "E-W9",
|
|
231
|
+
counter: "2",
|
|
232
|
+
});
|
|
233
|
+
const { ingest, anchors } = await pipeline({
|
|
234
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
235
|
+
// 0xf9 declares a long list with a 2-byte length that never arrives.
|
|
236
|
+
"witnesses/w.json": witnessJson({
|
|
237
|
+
headerRlpHex: "0xf901",
|
|
238
|
+
blockNumber: BLOCK_NUMBER,
|
|
239
|
+
blockHash: BLOCK_HASH,
|
|
240
|
+
}),
|
|
241
|
+
});
|
|
242
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
243
|
+
assert.equal(analysis.outcomes[0].reason, "witness-rlp-invalid");
|
|
244
|
+
});
|
|
245
|
+
it("a witness matching no anchor is reported witness-unmatched", async () => {
|
|
246
|
+
const otherHeader = makeEthereumHeader({ blockNumber: 5, timestamp: 6 });
|
|
247
|
+
const otherHash = `0x${Buffer.from(keccak_256(otherHeader.headerBytes)).toString("hex")}`;
|
|
248
|
+
const anchor = await makeAnchorProof({
|
|
249
|
+
blockHash: BLOCK_HASH,
|
|
250
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
251
|
+
epochId: "E-W10",
|
|
252
|
+
counter: "2",
|
|
253
|
+
});
|
|
254
|
+
const { ingest, anchors } = await pipeline({
|
|
255
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
256
|
+
"witnesses/w.json": witnessJson({
|
|
257
|
+
headerRlpHex: otherHeader.headerRlpHex,
|
|
258
|
+
blockNumber: 5,
|
|
259
|
+
blockHash: otherHash,
|
|
260
|
+
}),
|
|
261
|
+
});
|
|
262
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
263
|
+
const outcome = analysis.outcomes[0];
|
|
264
|
+
assert.equal(outcome.verified, false);
|
|
265
|
+
assert.equal(outcome.reason, "witness-unmatched");
|
|
266
|
+
assert.equal(outcome.anchorProofHash, undefined);
|
|
267
|
+
});
|
|
268
|
+
it("a witness cannot rescue an invalid anchor: witness-anchor-invalid", async () => {
|
|
269
|
+
const anchor = await makeAnchorProof({
|
|
270
|
+
blockHash: BLOCK_HASH,
|
|
271
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
272
|
+
epochId: "E-W11",
|
|
273
|
+
counter: "2",
|
|
274
|
+
});
|
|
275
|
+
// Tamper the Ed25519 signature: the canonical identity is unchanged
|
|
276
|
+
// (the signature is outside the signed body) but the proof is invalid.
|
|
277
|
+
anchor.proof.signer.signatureB64 = `AA${anchor.proof.signer.signatureB64.slice(2)}`;
|
|
278
|
+
const { ingest, anchors } = await pipeline({
|
|
279
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
280
|
+
"witnesses/w.json": goodWitness(),
|
|
281
|
+
});
|
|
282
|
+
const analysis = await verifyAnchorWitnesses(ingest, anchors);
|
|
283
|
+
const outcome = analysis.outcomes[0];
|
|
284
|
+
assert.equal(outcome.verified, false);
|
|
285
|
+
assert.equal(outcome.reason, "witness-anchor-invalid");
|
|
286
|
+
assert.equal(outcome.timestamp, undefined);
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
describe("audit witness: direct single-pair API", () => {
|
|
290
|
+
it("verifyAnchorWitness runs the full procedure against one anchor", async () => {
|
|
291
|
+
const anchor = await makeAnchorProof({
|
|
292
|
+
blockHash: BLOCK_HASH,
|
|
293
|
+
blockNumber: String(BLOCK_NUMBER),
|
|
294
|
+
epochId: "E-W12",
|
|
295
|
+
counter: "2",
|
|
296
|
+
});
|
|
297
|
+
const { ingest } = await pipeline({
|
|
298
|
+
"proofs/anchor.json": proofJson(anchor.proof),
|
|
299
|
+
"witnesses/w.json": goodWitness(),
|
|
300
|
+
});
|
|
301
|
+
const observed = ingest.proofs.find((p) => p.proofHash === anchor.proofHash);
|
|
302
|
+
const witnessFile = ingest.witnesses[0];
|
|
303
|
+
const outcome = await verifyAnchorWitness(witnessFile, observed);
|
|
304
|
+
assert.equal(outcome.verified, true);
|
|
305
|
+
assert.equal(outcome.timestamp, TIMESTAMP);
|
|
306
|
+
});
|
|
307
|
+
});
|
|
308
|
+
//# sourceMappingURL=audit-witness.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-witness.test.js","sourceRoot":"","sources":["../../src/__tests__/audit-witness.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression: computeChainHash must exclude the anchor service's `ethereum`
|
|
3
|
+
* field so that an Ethereum anchor can be resolved as a chain predecessor.
|
|
4
|
+
*
|
|
5
|
+
* Real-data fixture. `anchor-with-ethereum-112758.json` is a live Ethereum
|
|
6
|
+
* anchor (commit 112758) exactly as it ships in an export bundle: it carries a
|
|
7
|
+
* top-level `ethereum` { blockNumber, blockHash } field that the anchor service
|
|
8
|
+
* appended AFTER the enclave signed it. `successor-112760.json` is the next
|
|
9
|
+
* proof on the chain (the BitGraph whitepaper, commit 112760); its
|
|
10
|
+
* `commit.prevB64` was computed by the enclave over the anchor as the enclave
|
|
11
|
+
* saw it — before the `ethereum` field existed.
|
|
12
|
+
*
|
|
13
|
+
* The bug (latent since the anchor service began stamping `ethereum` on
|
|
14
|
+
* 2026-04-01, exposed once the audit tool resolved prevB64 via computeChainHash
|
|
15
|
+
* on 2026-07-10): computeChainHash hashed the whole proof minus only
|
|
16
|
+
* `proofHash`, so the appended `ethereum` field poisoned the hash and no
|
|
17
|
+
* successor's prevB64 could ever match. The anchor "vanished" from the chain
|
|
18
|
+
* even though it was present in the bundle. The fix excludes `ethereum` (and
|
|
19
|
+
* any ledger/service-added field) from the chain hash.
|
|
20
|
+
*/
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=chain-hash-anchor.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-hash-anchor.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/chain-hash-anchor.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Regression: computeChainHash must exclude the anchor service's `ethereum`
|
|
3
|
+
* field so that an Ethereum anchor can be resolved as a chain predecessor.
|
|
4
|
+
*
|
|
5
|
+
* Real-data fixture. `anchor-with-ethereum-112758.json` is a live Ethereum
|
|
6
|
+
* anchor (commit 112758) exactly as it ships in an export bundle: it carries a
|
|
7
|
+
* top-level `ethereum` { blockNumber, blockHash } field that the anchor service
|
|
8
|
+
* appended AFTER the enclave signed it. `successor-112760.json` is the next
|
|
9
|
+
* proof on the chain (the BitGraph whitepaper, commit 112760); its
|
|
10
|
+
* `commit.prevB64` was computed by the enclave over the anchor as the enclave
|
|
11
|
+
* saw it — before the `ethereum` field existed.
|
|
12
|
+
*
|
|
13
|
+
* The bug (latent since the anchor service began stamping `ethereum` on
|
|
14
|
+
* 2026-04-01, exposed once the audit tool resolved prevB64 via computeChainHash
|
|
15
|
+
* on 2026-07-10): computeChainHash hashed the whole proof minus only
|
|
16
|
+
* `proofHash`, so the appended `ethereum` field poisoned the hash and no
|
|
17
|
+
* successor's prevB64 could ever match. The anchor "vanished" from the chain
|
|
18
|
+
* even though it was present in the bundle. The fix excludes `ethereum` (and
|
|
19
|
+
* any ledger/service-added field) from the chain hash.
|
|
20
|
+
*/
|
|
21
|
+
import { describe, it } from "node:test";
|
|
22
|
+
import * as assert from "node:assert/strict";
|
|
23
|
+
import { readFileSync } from "node:fs";
|
|
24
|
+
import { fileURLToPath } from "node:url";
|
|
25
|
+
import { computeChainHash } from "@mikeargento/bitgraph-verify";
|
|
26
|
+
function loadFixture(name) {
|
|
27
|
+
const url = new URL(`../../src/__tests__/real-fixtures/${name}`, import.meta.url);
|
|
28
|
+
return JSON.parse(readFileSync(fileURLToPath(url), "utf8"));
|
|
29
|
+
}
|
|
30
|
+
describe("computeChainHash: Ethereum anchor chain link (ethereum-field regression)", () => {
|
|
31
|
+
const anchor = loadFixture("anchor-with-ethereum-112758.json");
|
|
32
|
+
const successor = loadFixture("successor-112760.json");
|
|
33
|
+
const expectedPrev = successor.commit.prevB64;
|
|
34
|
+
it("the fixture is the real shape: anchor carries a top-level ethereum field", () => {
|
|
35
|
+
assert.ok(Object.prototype.hasOwnProperty.call(anchor, "ethereum"));
|
|
36
|
+
assert.equal(anchor.commit.counter, "112758");
|
|
37
|
+
assert.equal(successor.commit.counter, "112760");
|
|
38
|
+
});
|
|
39
|
+
it("resolves the successor's prevB64 to the anchor, as exported (with ethereum)", () => {
|
|
40
|
+
// The whole point: the anchor is exported WITH the ethereum field, and its
|
|
41
|
+
// chain hash must still equal the successor's prevB64.
|
|
42
|
+
assert.equal(computeChainHash(anchor), expectedPrev);
|
|
43
|
+
});
|
|
44
|
+
it("ignores the ethereum field entirely (with === without)", () => {
|
|
45
|
+
const withoutEth = { ...anchor };
|
|
46
|
+
delete withoutEth.ethereum;
|
|
47
|
+
assert.equal(computeChainHash(anchor), computeChainHash(withoutEth));
|
|
48
|
+
});
|
|
49
|
+
it("also ignores the ledger-added proofHash field (with === without)", () => {
|
|
50
|
+
const withoutHash = { ...anchor };
|
|
51
|
+
delete withoutHash.proofHash;
|
|
52
|
+
assert.equal(computeChainHash(anchor), computeChainHash(withoutHash));
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
//# sourceMappingURL=chain-hash-anchor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chain-hash-anchor.test.js","sourceRoot":"","sources":["../../src/__tests__/chain-hash-anchor.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,KAAK,MAAM,MAAM,oBAAoB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAsB,MAAM,8BAA8B,CAAC;AAEpF,SAAS,WAAW,CAAC,IAAY;IAC/B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,qCAAqC,IAAI,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC9D,CAAC;AAED,QAAQ,CAAC,0EAA0E,EAAE,GAAG,EAAE;IACxF,MAAM,MAAM,GAAG,WAAW,CAAC,kCAAkC,CAAC,CAAC;IAC/D,MAAM,SAAS,GAAG,WAAW,CAAC,uBAAuB,CAAC,CAAC;IACvD,MAAM,YAAY,GAAI,SAAS,CAAC,MAA8B,CAAC,OAAO,CAAC;IAEvE,EAAE,CAAC,0EAA0E,EAAE,GAAG,EAAE;QAClF,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;QACpE,MAAM,CAAC,KAAK,CAAE,MAAM,CAAC,MAA8B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QACvE,MAAM,CAAC,KAAK,CAAE,SAAS,CAAC,MAA8B,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6EAA6E,EAAE,GAAG,EAAE;QACrF,2EAA2E;QAC3E,uDAAuD;QACvD,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAkC,CAAC,EAAE,YAAY,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,UAAU,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;QAC1D,OAAO,UAAU,CAAC,QAAQ,CAAC;QAC3B,MAAM,CAAC,KAAK,CACV,gBAAgB,CAAC,MAAkC,CAAC,EACpD,gBAAgB,CAAC,UAAsC,CAAC,CACzD,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,MAAM,WAAW,GAA4B,EAAE,GAAG,MAAM,EAAE,CAAC;QAC3D,OAAO,WAAW,CAAC,SAAS,CAAC;QAC7B,MAAM,CAAC,KAAK,CACV,gBAAgB,CAAC,MAAkC,CAAC,EACpD,gBAAgB,CAAC,WAAuC,CAAC,CAC1D,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The first declared recording ever made (ledger #12,010, 2026-08-18), kept
|
|
3
|
+
* as a fixture because its absence is what let two verifier bugs through that
|
|
4
|
+
* day (see dc26b5fd). A real WebAuthn assertion: origin https://bitgraph.ing,
|
|
5
|
+
* rpIdHash = SHA-256("bitgraph.ing"), flags UP|UV|BE|BS (a synced passkey).
|
|
6
|
+
* The artifact bytes are not here, so it is checked with verifyProofIntegrity.
|
|
7
|
+
* Same bytes as packages/player/src/__tests__/fixtures/declared-12010/proof.json.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DECLARED_12010: {
|
|
10
|
+
readonly version: "bitgraph/1";
|
|
11
|
+
readonly artifact: {
|
|
12
|
+
readonly hashAlg: "sha256";
|
|
13
|
+
readonly digestB64: "szEkIOHMuIaOXlqVG9uqKvaKtmnYmklfzOjEldzFP2E=";
|
|
14
|
+
};
|
|
15
|
+
readonly commit: {
|
|
16
|
+
readonly nonceB64: "05pT2TUMA2mJ0iBsQPkOaKFIUa0i4Ta6wdNkqS3jef4=";
|
|
17
|
+
readonly counter: "12010";
|
|
18
|
+
readonly slotCounter: "12009";
|
|
19
|
+
readonly slotHashB64: "VbOoREc4tcmNwFFYmtfenUZ04LNkjP02wQN2okIi81Y=";
|
|
20
|
+
readonly epochId: "plJ+9/nhhVEvDE4X4rCjJI+zys0fIov3XT114+mQIpk=";
|
|
21
|
+
readonly prevB64: "3TzjHBZWqTMte6FE0BZ0SM7hrcRhFv29Sl4NMf/ZvBs=";
|
|
22
|
+
readonly chainId: "bitgraph:main";
|
|
23
|
+
};
|
|
24
|
+
readonly signer: {
|
|
25
|
+
readonly publicKeyB64: "tmp21VjPay+EhaMwmrFLfdjZo2KIjjT7VDqjmm27wHI=";
|
|
26
|
+
readonly signatureB64: "96dTfH4EYq1pRvS7zAhVZuiCLsfrlur0QkA4dfkRQZtbkQ8dgebEQn85TOdvvPtk2YYh9pP0k46HWrZuOOYlBg==";
|
|
27
|
+
};
|
|
28
|
+
readonly environment: {
|
|
29
|
+
readonly enforcement: "measured-tee";
|
|
30
|
+
readonly measurement: "6483cedffed74680ffb287507744a398b288c3fb943eb3f2e4fe889f8b60b3d575ad8942350360b69a1bd7bf713df27f";
|
|
31
|
+
readonly attestation: {
|
|
32
|
+
readonly format: "aws-nitro";
|
|
33
|
+
readonly reportB64: "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";
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
readonly slotAllocation: {
|
|
37
|
+
readonly version: "bitgraph/slot/1";
|
|
38
|
+
readonly nonceB64: "05pT2TUMA2mJ0iBsQPkOaKFIUa0i4Ta6wdNkqS3jef4=";
|
|
39
|
+
readonly counter: "12009";
|
|
40
|
+
readonly epochId: "plJ+9/nhhVEvDE4X4rCjJI+zys0fIov3XT114+mQIpk=";
|
|
41
|
+
readonly publicKeyB64: "tmp21VjPay+EhaMwmrFLfdjZo2KIjjT7VDqjmm27wHI=";
|
|
42
|
+
readonly chainId: "bitgraph:main";
|
|
43
|
+
readonly signatureB64: "LlqN1udFVXP9IFxsjwdF6//NMJZbm/IvBmlzDWJ7sfDAqCHD9fSH24w5AM4thFtf0YxMT/n5FedunYYwUQRgCA==";
|
|
44
|
+
};
|
|
45
|
+
readonly agency: {
|
|
46
|
+
readonly actor: {
|
|
47
|
+
readonly keyId: "ee0c65174625e065c18e732a226b649a138625ba49c3d7dde026957082035cde";
|
|
48
|
+
readonly publicKeyB64: "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVXEkwZppHxU13Ew9Ap+BQnxQcNXuMvH6KPepQe3t8t1Jh2/aEguB0Ttrzxw9WGxmB8a3AdVVv+ybchgrL8XIRg==";
|
|
49
|
+
readonly algorithm: "ES256";
|
|
50
|
+
readonly provider: "passkey";
|
|
51
|
+
};
|
|
52
|
+
readonly authorization: {
|
|
53
|
+
readonly purpose: "bitgraph/commit-authorize/v1";
|
|
54
|
+
readonly format: "webauthn";
|
|
55
|
+
readonly actorKeyId: "ee0c65174625e065c18e732a226b649a138625ba49c3d7dde026957082035cde";
|
|
56
|
+
readonly artifactHash: "szEkIOHMuIaOXlqVG9uqKvaKtmnYmklfzOjEldzFP2E=";
|
|
57
|
+
readonly challenge: "WzE2FoHLFBQhiwQCpdR8xXA0g1FfOcRCcTEG+1iOJa4=";
|
|
58
|
+
readonly timestamp: 1787086799013;
|
|
59
|
+
readonly authenticatorDataB64: "Gv0914qYXymsoynDxplniUKsvF16m3HSkeyxwvtTjnsdAAAAAA==";
|
|
60
|
+
readonly clientDataJSON: "{\"type\":\"webauthn.get\",\"challenge\":\"WzE2FoHLFBQhiwQCpdR8xXA0g1FfOcRCcTEG-1iOJa4\",\"origin\":\"https://bitgraph.ing\",\"crossOrigin\":false}";
|
|
61
|
+
readonly signatureB64: "MEUCIQDBAxBn+pAZcq9YTCVnGcoV6TX+dC1sR1R/0ufz5GSf8gIgMrlaLEPP8f4uFLfTXHT0EA+m85x1LcQNDYqf3557Ktk=";
|
|
62
|
+
};
|
|
63
|
+
};
|
|
64
|
+
readonly proofHash: "gpbq9mzjkjy9xz7wZAsV+eLk1kwTeOtHogysF5rYS2w=";
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=declared-proof-fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declared-proof-fixture.d.ts","sourceRoot":"","sources":["../../src/__tests__/declared-proof-fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwDjB,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The first declared recording ever made (ledger #12,010, 2026-08-18), kept
|
|
3
|
+
* as a fixture because its absence is what let two verifier bugs through that
|
|
4
|
+
* day (see dc26b5fd). A real WebAuthn assertion: origin https://bitgraph.ing,
|
|
5
|
+
* rpIdHash = SHA-256("bitgraph.ing"), flags UP|UV|BE|BS (a synced passkey).
|
|
6
|
+
* The artifact bytes are not here, so it is checked with verifyProofIntegrity.
|
|
7
|
+
* Same bytes as packages/player/src/__tests__/fixtures/declared-12010/proof.json.
|
|
8
|
+
*/
|
|
9
|
+
export const DECLARED_12010 = {
|
|
10
|
+
"version": "bitgraph/1",
|
|
11
|
+
"artifact": {
|
|
12
|
+
"hashAlg": "sha256",
|
|
13
|
+
"digestB64": "szEkIOHMuIaOXlqVG9uqKvaKtmnYmklfzOjEldzFP2E="
|
|
14
|
+
},
|
|
15
|
+
"commit": {
|
|
16
|
+
"nonceB64": "05pT2TUMA2mJ0iBsQPkOaKFIUa0i4Ta6wdNkqS3jef4=",
|
|
17
|
+
"counter": "12010",
|
|
18
|
+
"slotCounter": "12009",
|
|
19
|
+
"slotHashB64": "VbOoREc4tcmNwFFYmtfenUZ04LNkjP02wQN2okIi81Y=",
|
|
20
|
+
"epochId": "plJ+9/nhhVEvDE4X4rCjJI+zys0fIov3XT114+mQIpk=",
|
|
21
|
+
"prevB64": "3TzjHBZWqTMte6FE0BZ0SM7hrcRhFv29Sl4NMf/ZvBs=",
|
|
22
|
+
"chainId": "bitgraph:main"
|
|
23
|
+
},
|
|
24
|
+
"signer": {
|
|
25
|
+
"publicKeyB64": "tmp21VjPay+EhaMwmrFLfdjZo2KIjjT7VDqjmm27wHI=",
|
|
26
|
+
"signatureB64": "96dTfH4EYq1pRvS7zAhVZuiCLsfrlur0QkA4dfkRQZtbkQ8dgebEQn85TOdvvPtk2YYh9pP0k46HWrZuOOYlBg=="
|
|
27
|
+
},
|
|
28
|
+
"environment": {
|
|
29
|
+
"enforcement": "measured-tee",
|
|
30
|
+
"measurement": "6483cedffed74680ffb287507744a398b288c3fb943eb3f2e4fe889f8b60b3d575ad8942350360b69a1bd7bf713df27f",
|
|
31
|
+
"attestation": {
|
|
32
|
+
"format": "aws-nitro",
|
|
33
|
+
"reportB64": "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"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"slotAllocation": {
|
|
37
|
+
"version": "bitgraph/slot/1",
|
|
38
|
+
"nonceB64": "05pT2TUMA2mJ0iBsQPkOaKFIUa0i4Ta6wdNkqS3jef4=",
|
|
39
|
+
"counter": "12009",
|
|
40
|
+
"epochId": "plJ+9/nhhVEvDE4X4rCjJI+zys0fIov3XT114+mQIpk=",
|
|
41
|
+
"publicKeyB64": "tmp21VjPay+EhaMwmrFLfdjZo2KIjjT7VDqjmm27wHI=",
|
|
42
|
+
"chainId": "bitgraph:main",
|
|
43
|
+
"signatureB64": "LlqN1udFVXP9IFxsjwdF6//NMJZbm/IvBmlzDWJ7sfDAqCHD9fSH24w5AM4thFtf0YxMT/n5FedunYYwUQRgCA=="
|
|
44
|
+
},
|
|
45
|
+
"agency": {
|
|
46
|
+
"actor": {
|
|
47
|
+
"keyId": "ee0c65174625e065c18e732a226b649a138625ba49c3d7dde026957082035cde",
|
|
48
|
+
"publicKeyB64": "MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEVXEkwZppHxU13Ew9Ap+BQnxQcNXuMvH6KPepQe3t8t1Jh2/aEguB0Ttrzxw9WGxmB8a3AdVVv+ybchgrL8XIRg==",
|
|
49
|
+
"algorithm": "ES256",
|
|
50
|
+
"provider": "passkey"
|
|
51
|
+
},
|
|
52
|
+
"authorization": {
|
|
53
|
+
"purpose": "bitgraph/commit-authorize/v1",
|
|
54
|
+
"format": "webauthn",
|
|
55
|
+
"actorKeyId": "ee0c65174625e065c18e732a226b649a138625ba49c3d7dde026957082035cde",
|
|
56
|
+
"artifactHash": "szEkIOHMuIaOXlqVG9uqKvaKtmnYmklfzOjEldzFP2E=",
|
|
57
|
+
"challenge": "WzE2FoHLFBQhiwQCpdR8xXA0g1FfOcRCcTEG+1iOJa4=",
|
|
58
|
+
"timestamp": 1787086799013,
|
|
59
|
+
"authenticatorDataB64": "Gv0914qYXymsoynDxplniUKsvF16m3HSkeyxwvtTjnsdAAAAAA==",
|
|
60
|
+
"clientDataJSON": "{\"type\":\"webauthn.get\",\"challenge\":\"WzE2FoHLFBQhiwQCpdR8xXA0g1FfOcRCcTEG-1iOJa4\",\"origin\":\"https://bitgraph.ing\",\"crossOrigin\":false}",
|
|
61
|
+
"signatureB64": "MEUCIQDBAxBn+pAZcq9YTCVnGcoV6TX+dC1sR1R/0ufz5GSf8gIgMrlaLEPP8f4uFLfTXHT0EA+m85x1LcQNDYqf3557Ktk="
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
"proofHash": "gpbq9mzjkjy9xz7wZAsV+eLk1kwTeOtHogysF5rYS2w="
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=declared-proof-fixture.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"declared-proof-fixture.js","sourceRoot":"","sources":["../../src/__tests__/declared-proof-fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,SAAS,EAAE,YAAY;IACvB,UAAU,EAAE;QACV,SAAS,EAAE,QAAQ;QACnB,WAAW,EAAE,8CAA8C;KAC5D;IACD,QAAQ,EAAE;QACR,UAAU,EAAE,8CAA8C;QAC1D,SAAS,EAAE,OAAO;QAClB,aAAa,EAAE,OAAO;QACtB,aAAa,EAAE,8CAA8C;QAC7D,SAAS,EAAE,8CAA8C;QACzD,SAAS,EAAE,8CAA8C;QACzD,SAAS,EAAE,eAAe;KAC3B;IACD,QAAQ,EAAE;QACR,cAAc,EAAE,8CAA8C;QAC9D,cAAc,EAAE,0FAA0F;KAC3G;IACD,aAAa,EAAE;QACb,aAAa,EAAE,cAAc;QAC7B,aAAa,EAAE,kGAAkG;QACjH,aAAa,EAAE;YACb,QAAQ,EAAE,WAAW;YACrB,WAAW,EAAE,82LAA82L;SAC53L;KACF;IACD,gBAAgB,EAAE;QAChB,SAAS,EAAE,iBAAiB;QAC5B,UAAU,EAAE,8CAA8C;QAC1D,SAAS,EAAE,OAAO;QAClB,SAAS,EAAE,8CAA8C;QACzD,cAAc,EAAE,8CAA8C;QAC9D,SAAS,EAAE,eAAe;QAC1B,cAAc,EAAE,0FAA0F;KAC3G;IACD,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,kEAAkE;YAC3E,cAAc,EAAE,8HAA8H;YAC9I,WAAW,EAAE,OAAO;YACpB,UAAU,EAAE,SAAS;SACtB;QACD,eAAe,EAAE;YACf,SAAS,EAAE,8BAA8B;YACzC,QAAQ,EAAE,UAAU;YACpB,YAAY,EAAE,kEAAkE;YAChF,cAAc,EAAE,8CAA8C;YAC9D,WAAW,EAAE,8CAA8C;YAC3D,WAAW,EAAE,aAAa;YAC1B,sBAAsB,EAAE,sDAAsD;YAC9E,gBAAgB,EAAE,qJAAqJ;YACvK,cAAc,EAAE,kGAAkG;SACnH;KACF;IACD,WAAW,EAAE,8CAA8C;CACnD,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared mock proof fixture.
|
|
3
|
+
*
|
|
4
|
+
* Extracted verbatim from proof-hash.test.ts (values unchanged, byte for
|
|
5
|
+
* byte) so other suites can import the fixture without importing a test
|
|
6
|
+
* file (which would re-register its suites under node:test).
|
|
7
|
+
*
|
|
8
|
+
* Placeholder values throughout: the digest, keys, and signatures are not
|
|
9
|
+
* real base64 crypto material. It is a canonical-hash and ingest fixture;
|
|
10
|
+
* it fails full verification by design, always for a precise non-version
|
|
11
|
+
* reason (the placeholder digest is not strict base64), never as a pass.
|
|
12
|
+
*/
|
|
13
|
+
import type { BitGraphProof } from "../index.js";
|
|
14
|
+
export declare const MOCK_PROOF: BitGraphProof;
|
|
15
|
+
//# sourceMappingURL=mock-proof-fixture.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-proof-fixture.d.ts","sourceRoot":"","sources":["../../src/__tests__/mock-proof-fixture.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,eAAO,MAAM,UAAU,EAAE,aAoBxB,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared mock proof fixture.
|
|
3
|
+
*
|
|
4
|
+
* Extracted verbatim from proof-hash.test.ts (values unchanged, byte for
|
|
5
|
+
* byte) so other suites can import the fixture without importing a test
|
|
6
|
+
* file (which would re-register its suites under node:test).
|
|
7
|
+
*
|
|
8
|
+
* Placeholder values throughout: the digest, keys, and signatures are not
|
|
9
|
+
* real base64 crypto material. It is a canonical-hash and ingest fixture;
|
|
10
|
+
* it fails full verification by design, always for a precise non-version
|
|
11
|
+
* reason (the placeholder digest is not strict base64), never as a pass.
|
|
12
|
+
*/
|
|
13
|
+
export const MOCK_PROOF = {
|
|
14
|
+
version: "bitgraph/1",
|
|
15
|
+
artifact: { hashAlg: "sha256", digestB64: "abc123==" },
|
|
16
|
+
commit: {
|
|
17
|
+
nonceB64: "nonce==",
|
|
18
|
+
counter: "42",
|
|
19
|
+
slotCounter: "41",
|
|
20
|
+
epochId: "epoch==",
|
|
21
|
+
prevB64: "prev==",
|
|
22
|
+
},
|
|
23
|
+
signer: {
|
|
24
|
+
publicKeyB64: "pubkey==",
|
|
25
|
+
signatureB64: "sig==",
|
|
26
|
+
},
|
|
27
|
+
environment: {
|
|
28
|
+
enforcement: "measured-tee",
|
|
29
|
+
measurement: "pcr0hash",
|
|
30
|
+
attestation: { format: "aws-nitro", reportB64: "report==" },
|
|
31
|
+
},
|
|
32
|
+
attribution: { name: "test", message: "hello" },
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=mock-proof-fixture.js.map
|