@mikeargento/bitgraph 1.9.1 → 1.9.2

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.
Files changed (239) hide show
  1. package/package.json +9 -6
  2. package/dist/__tests__/audit-anchors.test.d.ts +0 -2
  3. package/dist/__tests__/audit-anchors.test.d.ts.map +0 -1
  4. package/dist/__tests__/audit-anchors.test.js +0 -152
  5. package/dist/__tests__/audit-anchors.test.js.map +0 -1
  6. package/dist/__tests__/audit-anomalies.test.d.ts +0 -2
  7. package/dist/__tests__/audit-anomalies.test.d.ts.map +0 -1
  8. package/dist/__tests__/audit-anomalies.test.js +0 -663
  9. package/dist/__tests__/audit-anomalies.test.js.map +0 -1
  10. package/dist/__tests__/audit-attestation.test.d.ts +0 -2
  11. package/dist/__tests__/audit-attestation.test.d.ts.map +0 -1
  12. package/dist/__tests__/audit-attestation.test.js +0 -403
  13. package/dist/__tests__/audit-attestation.test.js.map +0 -1
  14. package/dist/__tests__/audit-bench-smoke.test.d.ts +0 -2
  15. package/dist/__tests__/audit-bench-smoke.test.d.ts.map +0 -1
  16. package/dist/__tests__/audit-bench-smoke.test.js +0 -87
  17. package/dist/__tests__/audit-bench-smoke.test.js.map +0 -1
  18. package/dist/__tests__/audit-boundary.test.d.ts +0 -20
  19. package/dist/__tests__/audit-boundary.test.d.ts.map +0 -1
  20. package/dist/__tests__/audit-boundary.test.js +0 -84
  21. package/dist/__tests__/audit-boundary.test.js.map +0 -1
  22. package/dist/__tests__/audit-cli.test.d.ts +0 -2
  23. package/dist/__tests__/audit-cli.test.d.ts.map +0 -1
  24. package/dist/__tests__/audit-cli.test.js +0 -239
  25. package/dist/__tests__/audit-cli.test.js.map +0 -1
  26. package/dist/__tests__/audit-dependencies.test.d.ts +0 -2
  27. package/dist/__tests__/audit-dependencies.test.d.ts.map +0 -1
  28. package/dist/__tests__/audit-dependencies.test.js +0 -116
  29. package/dist/__tests__/audit-dependencies.test.js.map +0 -1
  30. package/dist/__tests__/audit-fixtures.d.ts +0 -265
  31. package/dist/__tests__/audit-fixtures.d.ts.map +0 -1
  32. package/dist/__tests__/audit-fixtures.js +0 -511
  33. package/dist/__tests__/audit-fixtures.js.map +0 -1
  34. package/dist/__tests__/audit-ingest.test.d.ts +0 -2
  35. package/dist/__tests__/audit-ingest.test.d.ts.map +0 -1
  36. package/dist/__tests__/audit-ingest.test.js +0 -473
  37. package/dist/__tests__/audit-ingest.test.js.map +0 -1
  38. package/dist/__tests__/audit-memory-ingest.test.d.ts +0 -12
  39. package/dist/__tests__/audit-memory-ingest.test.d.ts.map +0 -1
  40. package/dist/__tests__/audit-memory-ingest.test.js +0 -135
  41. package/dist/__tests__/audit-memory-ingest.test.js.map +0 -1
  42. package/dist/__tests__/audit-property.test.d.ts +0 -2
  43. package/dist/__tests__/audit-property.test.d.ts.map +0 -1
  44. package/dist/__tests__/audit-property.test.js +0 -771
  45. package/dist/__tests__/audit-property.test.js.map +0 -1
  46. package/dist/__tests__/audit-real-fixtures.test.d.ts +0 -2
  47. package/dist/__tests__/audit-real-fixtures.test.d.ts.map +0 -1
  48. package/dist/__tests__/audit-real-fixtures.test.js +0 -132
  49. package/dist/__tests__/audit-real-fixtures.test.js.map +0 -1
  50. package/dist/__tests__/audit-real-live.test.d.ts +0 -2
  51. package/dist/__tests__/audit-real-live.test.d.ts.map +0 -1
  52. package/dist/__tests__/audit-real-live.test.js +0 -107
  53. package/dist/__tests__/audit-real-live.test.js.map +0 -1
  54. package/dist/__tests__/audit-reconstruct.test.d.ts +0 -2
  55. package/dist/__tests__/audit-reconstruct.test.d.ts.map +0 -1
  56. package/dist/__tests__/audit-reconstruct.test.js +0 -287
  57. package/dist/__tests__/audit-reconstruct.test.js.map +0 -1
  58. package/dist/__tests__/audit-report.test.d.ts +0 -2
  59. package/dist/__tests__/audit-report.test.d.ts.map +0 -1
  60. package/dist/__tests__/audit-report.test.js +0 -186
  61. package/dist/__tests__/audit-report.test.js.map +0 -1
  62. package/dist/__tests__/audit-roundtrip.test.d.ts +0 -2
  63. package/dist/__tests__/audit-roundtrip.test.d.ts.map +0 -1
  64. package/dist/__tests__/audit-roundtrip.test.js +0 -368
  65. package/dist/__tests__/audit-roundtrip.test.js.map +0 -1
  66. package/dist/__tests__/audit-temporal.test.d.ts +0 -2
  67. package/dist/__tests__/audit-temporal.test.d.ts.map +0 -1
  68. package/dist/__tests__/audit-temporal.test.js +0 -364
  69. package/dist/__tests__/audit-temporal.test.js.map +0 -1
  70. package/dist/__tests__/audit-tiers.test.d.ts +0 -2
  71. package/dist/__tests__/audit-tiers.test.d.ts.map +0 -1
  72. package/dist/__tests__/audit-tiers.test.js +0 -282
  73. package/dist/__tests__/audit-tiers.test.js.map +0 -1
  74. package/dist/__tests__/audit-witness-real.test.d.ts +0 -19
  75. package/dist/__tests__/audit-witness-real.test.d.ts.map +0 -1
  76. package/dist/__tests__/audit-witness-real.test.js +0 -82
  77. package/dist/__tests__/audit-witness-real.test.js.map +0 -1
  78. package/dist/__tests__/audit-witness.test.d.ts +0 -2
  79. package/dist/__tests__/audit-witness.test.d.ts.map +0 -1
  80. package/dist/__tests__/audit-witness.test.js +0 -308
  81. package/dist/__tests__/audit-witness.test.js.map +0 -1
  82. package/dist/__tests__/canonical.test.d.ts +0 -2
  83. package/dist/__tests__/canonical.test.d.ts.map +0 -1
  84. package/dist/__tests__/canonical.test.js +0 -162
  85. package/dist/__tests__/canonical.test.js.map +0 -1
  86. package/dist/__tests__/chain-hash-anchor.test.d.ts +0 -22
  87. package/dist/__tests__/chain-hash-anchor.test.d.ts.map +0 -1
  88. package/dist/__tests__/chain-hash-anchor.test.js +0 -55
  89. package/dist/__tests__/chain-hash-anchor.test.js.map +0 -1
  90. package/dist/__tests__/commit-service.integration.test.d.ts +0 -2
  91. package/dist/__tests__/commit-service.integration.test.d.ts.map +0 -1
  92. package/dist/__tests__/commit-service.integration.test.js +0 -95
  93. package/dist/__tests__/commit-service.integration.test.js.map +0 -1
  94. package/dist/__tests__/constructor.test.d.ts +0 -2
  95. package/dist/__tests__/constructor.test.d.ts.map +0 -1
  96. package/dist/__tests__/constructor.test.js +0 -267
  97. package/dist/__tests__/constructor.test.js.map +0 -1
  98. package/dist/__tests__/declared-proof-fixture.d.ts +0 -66
  99. package/dist/__tests__/declared-proof-fixture.d.ts.map +0 -1
  100. package/dist/__tests__/declared-proof-fixture.js +0 -66
  101. package/dist/__tests__/declared-proof-fixture.js.map +0 -1
  102. package/dist/__tests__/fuse-inline.test.d.ts +0 -2
  103. package/dist/__tests__/fuse-inline.test.d.ts.map +0 -1
  104. package/dist/__tests__/fuse-inline.test.js +0 -181
  105. package/dist/__tests__/fuse-inline.test.js.map +0 -1
  106. package/dist/__tests__/fuse-placement.test.d.ts +0 -2
  107. package/dist/__tests__/fuse-placement.test.d.ts.map +0 -1
  108. package/dist/__tests__/fuse-placement.test.js +0 -31
  109. package/dist/__tests__/fuse-placement.test.js.map +0 -1
  110. package/dist/__tests__/fuse-roundtrip.test.d.ts +0 -2
  111. package/dist/__tests__/fuse-roundtrip.test.d.ts.map +0 -1
  112. package/dist/__tests__/fuse-roundtrip.test.js +0 -241
  113. package/dist/__tests__/fuse-roundtrip.test.js.map +0 -1
  114. package/dist/__tests__/fuse-sdk.test.d.ts +0 -2
  115. package/dist/__tests__/fuse-sdk.test.d.ts.map +0 -1
  116. package/dist/__tests__/fuse-sdk.test.js +0 -117
  117. package/dist/__tests__/fuse-sdk.test.js.map +0 -1
  118. package/dist/__tests__/fuse-set-sdk.test.d.ts +0 -2
  119. package/dist/__tests__/fuse-set-sdk.test.d.ts.map +0 -1
  120. package/dist/__tests__/fuse-set-sdk.test.js +0 -721
  121. package/dist/__tests__/fuse-set-sdk.test.js.map +0 -1
  122. package/dist/__tests__/fuse-set.test.d.ts +0 -2
  123. package/dist/__tests__/fuse-set.test.d.ts.map +0 -1
  124. package/dist/__tests__/fuse-set.test.js +0 -889
  125. package/dist/__tests__/fuse-set.test.js.map +0 -1
  126. package/dist/__tests__/fuse-set2.test.d.ts +0 -2
  127. package/dist/__tests__/fuse-set2.test.d.ts.map +0 -1
  128. package/dist/__tests__/fuse-set2.test.js +0 -294
  129. package/dist/__tests__/fuse-set2.test.js.map +0 -1
  130. package/dist/__tests__/fuse-vectors.test.d.ts +0 -2
  131. package/dist/__tests__/fuse-vectors.test.d.ts.map +0 -1
  132. package/dist/__tests__/fuse-vectors.test.js +0 -175
  133. package/dist/__tests__/fuse-vectors.test.js.map +0 -1
  134. package/dist/__tests__/fuse-verify.test.d.ts +0 -2
  135. package/dist/__tests__/fuse-verify.test.d.ts.map +0 -1
  136. package/dist/__tests__/fuse-verify.test.js +0 -250
  137. package/dist/__tests__/fuse-verify.test.js.map +0 -1
  138. package/dist/__tests__/hello-world.test.d.ts +0 -2
  139. package/dist/__tests__/hello-world.test.d.ts.map +0 -1
  140. package/dist/__tests__/hello-world.test.js +0 -9
  141. package/dist/__tests__/hello-world.test.js.map +0 -1
  142. package/dist/__tests__/mock-proof-fixture.d.ts +0 -15
  143. package/dist/__tests__/mock-proof-fixture.d.ts.map +0 -1
  144. package/dist/__tests__/mock-proof-fixture.js +0 -34
  145. package/dist/__tests__/mock-proof-fixture.js.map +0 -1
  146. package/dist/__tests__/policy-enforcement.test.d.ts +0 -2
  147. package/dist/__tests__/policy-enforcement.test.d.ts.map +0 -1
  148. package/dist/__tests__/policy-enforcement.test.js +0 -188
  149. package/dist/__tests__/policy-enforcement.test.js.map +0 -1
  150. package/dist/__tests__/proof-hash-regression.test.d.ts +0 -2
  151. package/dist/__tests__/proof-hash-regression.test.d.ts.map +0 -1
  152. package/dist/__tests__/proof-hash-regression.test.js +0 -95
  153. package/dist/__tests__/proof-hash-regression.test.js.map +0 -1
  154. package/dist/__tests__/proof-hash.test.d.ts +0 -2
  155. package/dist/__tests__/proof-hash.test.d.ts.map +0 -1
  156. package/dist/__tests__/proof-hash.test.js +0 -116
  157. package/dist/__tests__/proof-hash.test.js.map +0 -1
  158. package/dist/__tests__/proof-integrity.test.d.ts +0 -2
  159. package/dist/__tests__/proof-integrity.test.d.ts.map +0 -1
  160. package/dist/__tests__/proof-integrity.test.js +0 -454
  161. package/dist/__tests__/proof-integrity.test.js.map +0 -1
  162. package/dist/__tests__/realistic-proof-fixture.d.ts +0 -56
  163. package/dist/__tests__/realistic-proof-fixture.d.ts.map +0 -1
  164. package/dist/__tests__/realistic-proof-fixture.js +0 -57
  165. package/dist/__tests__/realistic-proof-fixture.js.map +0 -1
  166. package/dist/__tests__/run.test.d.ts +0 -2
  167. package/dist/__tests__/run.test.d.ts.map +0 -1
  168. package/dist/__tests__/run.test.js +0 -178
  169. package/dist/__tests__/run.test.js.map +0 -1
  170. package/dist/__tests__/verifier.test.d.ts +0 -2
  171. package/dist/__tests__/verifier.test.d.ts.map +0 -1
  172. package/dist/__tests__/verifier.test.js +0 -531
  173. package/dist/__tests__/verifier.test.js.map +0 -1
  174. package/dist/canonical.d.ts +0 -54
  175. package/dist/canonical.d.ts.map +0 -1
  176. package/dist/canonical.js +0 -119
  177. package/dist/canonical.js.map +0 -1
  178. package/dist/proof-hash.d.ts +0 -9
  179. package/dist/proof-hash.d.ts.map +0 -1
  180. package/dist/proof-hash.js +0 -75
  181. package/dist/proof-hash.js.map +0 -1
  182. package/dist/types.d.ts +0 -705
  183. package/dist/types.d.ts.map +0 -1
  184. package/dist/types.js +0 -3
  185. package/dist/types.js.map +0 -1
  186. package/dist/verifier.d.ts +0 -27
  187. package/dist/verifier.d.ts.map +0 -1
  188. package/dist/verifier.js +0 -844
  189. package/dist/verifier.js.map +0 -1
  190. package/src/__tests__/audit-anchors.test.ts +0 -188
  191. package/src/__tests__/audit-anomalies.test.ts +0 -815
  192. package/src/__tests__/audit-attestation.test.ts +0 -529
  193. package/src/__tests__/audit-bench-smoke.test.ts +0 -108
  194. package/src/__tests__/audit-boundary.test.ts +0 -96
  195. package/src/__tests__/audit-cli.test.ts +0 -288
  196. package/src/__tests__/audit-dependencies.test.ts +0 -141
  197. package/src/__tests__/audit-fixtures.ts +0 -736
  198. package/src/__tests__/audit-ingest.test.ts +0 -575
  199. package/src/__tests__/audit-memory-ingest.test.ts +0 -156
  200. package/src/__tests__/audit-property.test.ts +0 -892
  201. package/src/__tests__/audit-real-fixtures.test.ts +0 -153
  202. package/src/__tests__/audit-real-live.test.ts +0 -128
  203. package/src/__tests__/audit-reconstruct.test.ts +0 -353
  204. package/src/__tests__/audit-report.test.ts +0 -222
  205. package/src/__tests__/audit-roundtrip.test.ts +0 -464
  206. package/src/__tests__/audit-temporal.test.ts +0 -446
  207. package/src/__tests__/audit-tiers.test.ts +0 -343
  208. package/src/__tests__/audit-witness-real.test.ts +0 -92
  209. package/src/__tests__/audit-witness.test.ts +0 -345
  210. package/src/__tests__/canonical.test.ts +0 -253
  211. package/src/__tests__/chain-hash-anchor.test.ts +0 -67
  212. package/src/__tests__/commit-service.integration.test.ts +0 -117
  213. package/src/__tests__/constructor.test.ts +0 -340
  214. package/src/__tests__/declared-proof-fixture.ts +0 -65
  215. package/src/__tests__/fuse-inline.test.ts +0 -211
  216. package/src/__tests__/fuse-placement.test.ts +0 -32
  217. package/src/__tests__/fuse-roundtrip.test.ts +0 -243
  218. package/src/__tests__/fuse-sdk.test.ts +0 -142
  219. package/src/__tests__/fuse-set-sdk.test.ts +0 -852
  220. package/src/__tests__/fuse-set.test.ts +0 -1027
  221. package/src/__tests__/fuse-set2.test.ts +0 -343
  222. package/src/__tests__/fuse-vectors.test.ts +0 -218
  223. package/src/__tests__/fuse-verify.test.ts +0 -278
  224. package/src/__tests__/hello-world.test.ts +0 -10
  225. package/src/__tests__/mock-proof-fixture.ts +0 -36
  226. package/src/__tests__/policy-enforcement.test.ts +0 -226
  227. package/src/__tests__/proof-hash-regression.test.ts +0 -107
  228. package/src/__tests__/proof-hash.test.ts +0 -129
  229. package/src/__tests__/proof-integrity.test.ts +0 -576
  230. package/src/__tests__/real-fixtures/anchor-after-112762.json +0 -47
  231. package/src/__tests__/real-fixtures/anchor-with-ethereum-112758.json +0 -47
  232. package/src/__tests__/real-fixtures/live-proof-0.json +0 -42
  233. package/src/__tests__/real-fixtures/live-proof-1.json +0 -43
  234. package/src/__tests__/real-fixtures/live-proof-2.json +0 -43
  235. package/src/__tests__/real-fixtures/successor-112760.json +0 -38
  236. package/src/__tests__/real-fixtures/witness-25525146.json +0 -6
  237. package/src/__tests__/real-fixtures/witness-25525147.json +0 -6
  238. package/src/__tests__/realistic-proof-fixture.ts +0 -57
  239. package/src/__tests__/verifier.test.ts +0 -624
@@ -1,576 +0,0 @@
1
- // Copyright (c) Argento Computing Inc. All rights reserved. See LICENSE.
2
-
3
- /**
4
- * Tests for verifyProofIntegrity, the bytes-free proof integrity API in
5
- * @mikeargento/bitgraph-verify.
6
- *
7
- * Also carries regression coverage asserting that verify() behavior is
8
- * unchanged by the shared-pipeline refactor: same checks, same order,
9
- * same failure strings.
10
- */
11
-
12
- import { describe, test, before, beforeEach } from "node:test";
13
- import * as assert from "node:assert/strict";
14
- import { getPublicKeyAsync, signAsync } from "@noble/ed25519";
15
- import { sha256 } from "@noble/hashes/sha256";
16
- import {
17
- verify,
18
- verifyProofIntegrity,
19
- resetEpochLinkState,
20
- createVerificationContext,
21
- canonicalize,
22
- } from "@mikeargento/bitgraph-verify";
23
- import type { BitGraphProof, ProofIntegrityResult } from "@mikeargento/bitgraph-verify";
24
- import { Constructor } from "../constructor.js";
25
- import type { HostCapabilities } from "../host.js";
26
-
27
- // ---------------------------------------------------------------------------
28
- // Test-fixture helpers
29
- // ---------------------------------------------------------------------------
30
-
31
- interface Fixture {
32
- proof: BitGraphProof;
33
- bytes: Uint8Array;
34
- publicKeyB64: string;
35
- measurement: string;
36
- }
37
-
38
- /** Constructor-built fixture, mirroring makeFixture in verifier.test.ts. */
39
- async function makeFixture(opts?: {
40
- epochId?: string;
41
- withCounter?: boolean;
42
- }): Promise<Fixture> {
43
- const privateKey = crypto.getRandomValues(new Uint8Array(32));
44
- const publicKeyBytes = await getPublicKeyAsync(privateKey);
45
- const publicKeyB64 = Buffer.from(publicKeyBytes).toString("base64");
46
- const measurement = "test-measurement-integrity";
47
-
48
- let counter = 0;
49
- const host: HostCapabilities = opts?.withCounter
50
- ? {
51
- enforcementTier: "stub" as const,
52
- getMeasurement: async () => measurement,
53
- getFreshNonce: async () => crypto.getRandomValues(new Uint8Array(16)),
54
- sign: async (data: Uint8Array) => signAsync(data, privateKey),
55
- getPublicKey: async () => publicKeyBytes,
56
- nextCounter: async () => String(++counter),
57
- }
58
- : {
59
- enforcementTier: "stub" as const,
60
- getMeasurement: async () => measurement,
61
- getFreshNonce: async () => crypto.getRandomValues(new Uint8Array(16)),
62
- sign: async (data: Uint8Array) => signAsync(data, privateKey),
63
- getPublicKey: async () => publicKeyBytes,
64
- };
65
-
66
- const ctor = await Constructor.initialize(
67
- opts?.epochId !== undefined ? { host, epochId: opts.epochId } : { host },
68
- );
69
-
70
- const bytes = new TextEncoder().encode("bitgraph-integrity-test-payload");
71
- const proof = await ctor.commit({ bytes });
72
-
73
- return { proof, bytes, publicKeyB64, measurement };
74
- }
75
-
76
- /** Deep-clone a proof so mutations don't affect the original. */
77
- function clone(proof: BitGraphProof): BitGraphProof {
78
- return JSON.parse(JSON.stringify(proof)) as BitGraphProof;
79
- }
80
-
81
- function b64(bytes: Uint8Array): string {
82
- return Buffer.from(bytes).toString("base64");
83
- }
84
-
85
- interface ManualKey {
86
- privateKey: Uint8Array;
87
- publicKeyB64: string;
88
- }
89
-
90
- async function makeKey(): Promise<ManualKey> {
91
- const privateKey = crypto.getRandomValues(new Uint8Array(32));
92
- const publicKeyB64 = b64(await getPublicKeyAsync(privateKey));
93
- return { privateKey, publicKeyB64 };
94
- }
95
-
96
- /**
97
- * Manually build and sign a proof over the exact canonical SignedBody
98
- * layout the verifier reconstructs. Used for slot-carrying and
99
- * epochLink-carrying proofs, which the root Constructor does not produce.
100
- */
101
- async function signBody(
102
- key: ManualKey,
103
- artifact: BitGraphProof["artifact"],
104
- commit: BitGraphProof["commit"],
105
- measurement: string,
106
- ): Promise<BitGraphProof> {
107
- const signedBody = {
108
- version: "bitgraph/1" as const,
109
- artifact,
110
- commit,
111
- publicKeyB64: key.publicKeyB64,
112
- enforcement: "stub" as const,
113
- measurement,
114
- };
115
- const signatureB64 = b64(await signAsync(canonicalize(signedBody), key.privateKey));
116
- return {
117
- version: "bitgraph/1",
118
- artifact,
119
- commit,
120
- signer: { publicKeyB64: key.publicKeyB64, signatureB64 },
121
- environment: { enforcement: "stub", measurement },
122
- };
123
- }
124
-
125
- interface SlotFixture {
126
- proof: BitGraphProof;
127
- bytes: Uint8Array;
128
- measurement: string;
129
- }
130
-
131
- /**
132
- * Build a slot-carrying proof: slot allocated at counter 1, commit at
133
- * counter 2, slotHashB64 binding the signed commit to the exact slot body.
134
- */
135
- async function makeSlotFixture(opts?: { commitCounter?: string }): Promise<SlotFixture> {
136
- const key = await makeKey();
137
- const measurement = "test-measurement-slot";
138
- const epochId = "epoch-slot-test";
139
- const nonceB64 = b64(crypto.getRandomValues(new Uint8Array(16)));
140
-
141
- const slotBody = {
142
- version: "bitgraph/slot/1" as const,
143
- nonceB64,
144
- counter: "1",
145
- time: 1_700_000_000_000,
146
- epochId,
147
- publicKeyB64: key.publicKeyB64,
148
- };
149
- const slotCanonical = canonicalize(slotBody);
150
- const slotSignatureB64 = b64(await signAsync(slotCanonical, key.privateKey));
151
- const slotHashB64 = b64(sha256(slotCanonical));
152
-
153
- const bytes = new TextEncoder().encode("bitgraph-integrity-slot-payload");
154
- const artifact: BitGraphProof["artifact"] = {
155
- hashAlg: "sha256",
156
- digestB64: b64(sha256(bytes)),
157
- };
158
- const commit: BitGraphProof["commit"] = {
159
- nonceB64,
160
- counter: opts?.commitCounter ?? "2",
161
- epochId,
162
- slotCounter: "1",
163
- slotHashB64,
164
- };
165
-
166
- const proof = await signBody(key, artifact, commit, measurement);
167
- proof.slotAllocation = { ...slotBody, signatureB64: slotSignatureB64 };
168
- return { proof, bytes, measurement };
169
- }
170
-
171
- interface EpochLinkFixture {
172
- proof: BitGraphProof;
173
- bytes: Uint8Array;
174
- }
175
-
176
- /**
177
- * Build an epoch-genesis proof carrying an epochLink. The link is inside
178
- * the signed commit, so the Ed25519 signature covers it.
179
- */
180
- async function makeEpochLinkFixture(opts?: {
181
- toEpochId?: string;
182
- samePrevKey?: boolean;
183
- }): Promise<EpochLinkFixture> {
184
- const key = await makeKey();
185
- const prevKey = await makeKey();
186
- const toEpochId = opts?.toEpochId ?? "epoch-successor-a";
187
-
188
- const epochLink = {
189
- prevEpochId: "epoch-predecessor-a",
190
- prevPublicKeyB64: opts?.samePrevKey === true ? key.publicKeyB64 : prevKey.publicKeyB64,
191
- prevCounter: "42",
192
- prevProofHashB64: b64(sha256(new TextEncoder().encode("predecessor-terminal-proof"))),
193
- toEpochId,
194
- toPublicKeyB64: key.publicKeyB64,
195
- };
196
-
197
- const bytes = new TextEncoder().encode("bitgraph-integrity-epochlink-payload");
198
- const artifact: BitGraphProof["artifact"] = {
199
- hashAlg: "sha256",
200
- digestB64: b64(sha256(bytes)),
201
- };
202
- const commit: BitGraphProof["commit"] = {
203
- nonceB64: b64(crypto.getRandomValues(new Uint8Array(16))),
204
- counter: "1",
205
- epochId: toEpochId,
206
- epochLink,
207
- };
208
-
209
- const proof = await signBody(key, artifact, commit, "test-measurement-epochlink");
210
- return { proof, bytes };
211
- }
212
-
213
- // ---------------------------------------------------------------------------
214
- // Module-level fixtures
215
- // ---------------------------------------------------------------------------
216
-
217
- let fx!: Fixture;
218
-
219
- before(async () => {
220
- fx = await makeFixture();
221
- });
222
-
223
- // ---------------------------------------------------------------------------
224
- // Happy path: integrity without bytes
225
- // ---------------------------------------------------------------------------
226
-
227
- describe("verifyProofIntegrity: valid proof, no bytes", () => {
228
- test("passes for a freshly created proof and reports binding not checked", async () => {
229
- const result = await verifyProofIntegrity({ proof: fx.proof });
230
- assert.deepEqual(result, { valid: true, artifactBinding: "not-checked" });
231
- });
232
-
233
- test("passes for a proof with counter and epochId", async () => {
234
- const chained = await makeFixture({ withCounter: true, epochId: "epoch-integrity-xyz" });
235
- const result = await verifyProofIntegrity({ proof: chained.proof });
236
- assert.deepEqual(result, { valid: true, artifactBinding: "not-checked" });
237
- });
238
-
239
- test("passes even when verify() with wrong bytes fails: binding is genuinely not checked", async () => {
240
- const wrongBytes = new Uint8Array([1, 2, 3]);
241
- const full = await verify({ proof: fx.proof, bytes: wrongBytes });
242
- assert.equal(full.valid, false);
243
- assert.match(full.reason ?? "", /digest mismatch/);
244
-
245
- const integrity = await verifyProofIntegrity({ proof: fx.proof });
246
- assert.deepEqual(integrity, { valid: true, artifactBinding: "not-checked" });
247
- });
248
- });
249
-
250
- // ---------------------------------------------------------------------------
251
- // Result shape
252
- // ---------------------------------------------------------------------------
253
-
254
- describe("verifyProofIntegrity: result shape", () => {
255
- test("failure result also carries artifactBinding 'not-checked' plus a reason", async () => {
256
- const tampered = clone(fx.proof);
257
- tampered.signer.signatureB64 = Buffer.alloc(64).toString("base64");
258
- const result: ProofIntegrityResult = await verifyProofIntegrity({ proof: tampered });
259
- assert.equal(result.valid, false);
260
- assert.equal(result.artifactBinding, "not-checked");
261
- assert.equal(typeof result.reason, "string");
262
- });
263
- });
264
-
265
- // ---------------------------------------------------------------------------
266
- // Tampering
267
- // ---------------------------------------------------------------------------
268
-
269
- describe("verifyProofIntegrity: tampering", () => {
270
- test("fails when signatureB64 is replaced with all-zeros", async () => {
271
- const tampered = clone(fx.proof);
272
- tampered.signer.signatureB64 = Buffer.alloc(64).toString("base64");
273
- const result = await verifyProofIntegrity({ proof: tampered });
274
- assert.equal(result.valid, false);
275
- assert.match(result.reason ?? "", /signature/);
276
- });
277
-
278
- test("fails when version is tampered, with a version reason", async () => {
279
- const tampered = clone(fx.proof);
280
- (tampered as unknown as Record<string, unknown>)["version"] = "bitgraph/2";
281
- const result = await verifyProofIntegrity({ proof: tampered });
282
- assert.equal(result.valid, false);
283
- assert.equal(result.reason, "unsupported proof version: bitgraph/2");
284
- });
285
-
286
- test("fails when a signed field (measurement) is tampered", async () => {
287
- const tampered = clone(fx.proof);
288
- tampered.environment.measurement = "evil-measurement";
289
- const result = await verifyProofIntegrity({ proof: tampered });
290
- assert.equal(result.valid, false);
291
- assert.match(result.reason ?? "", /signature/);
292
- });
293
-
294
- test("fails when artifact.digestB64 is not valid base64 (well-formedness still checked)", async () => {
295
- const tampered = clone(fx.proof);
296
- tampered.artifact.digestB64 = "!!!";
297
- const result = await verifyProofIntegrity({ proof: tampered });
298
- assert.equal(result.valid, false);
299
- assert.equal(result.reason, "artifact.digestB64 is not valid base64");
300
- });
301
-
302
- test("fails for non-object proof", async () => {
303
- const result = await verifyProofIntegrity({
304
- proof: "not-a-proof" as unknown as BitGraphProof,
305
- });
306
- assert.equal(result.valid, false);
307
- assert.match(result.reason ?? "", /object/);
308
- });
309
- });
310
-
311
- // ---------------------------------------------------------------------------
312
- // Slot allocation (bytes-free)
313
- // ---------------------------------------------------------------------------
314
-
315
- describe("verifyProofIntegrity: slot allocation", () => {
316
- test("passes for a valid slot-carrying proof", async () => {
317
- const slotFx = await makeSlotFixture();
318
- const result = await verifyProofIntegrity({ proof: slotFx.proof });
319
- assert.deepEqual(result, { valid: true, artifactBinding: "not-checked" });
320
- });
321
-
322
- test("fails when commit.slotHashB64 is tampered (signed field)", async () => {
323
- const slotFx = await makeSlotFixture();
324
- const tampered = clone(slotFx.proof);
325
- tampered.commit.slotHashB64 = Buffer.alloc(32, 0xee).toString("base64");
326
- const result = await verifyProofIntegrity({ proof: tampered });
327
- assert.equal(result.valid, false);
328
- assert.match(result.reason ?? "", /signature/);
329
- });
330
-
331
- test("fails with a slot binding reason when the embedded slot record is swapped", async () => {
332
- const slotA = await makeSlotFixture();
333
- const slotB = await makeSlotFixture();
334
- const tampered = clone(slotA.proof);
335
- // slotB's record is validly signed by its own key, but it is not the
336
- // record that slotA's signed commit.slotHashB64 binds to.
337
- tampered.slotAllocation = clone(slotB.proof).slotAllocation!;
338
- const result = await verifyProofIntegrity({ proof: tampered });
339
- assert.equal(result.valid, false);
340
- assert.match(result.reason ?? "", /slotHashB64 does not match SHA-256 of canonical slot body/);
341
- });
342
-
343
- test("fails when slotAllocation.counter is tampered (slot signature breaks)", async () => {
344
- const slotFx = await makeSlotFixture();
345
- const tampered = clone(slotFx.proof);
346
- tampered.slotAllocation!.counter = "999";
347
- const result = await verifyProofIntegrity({ proof: tampered });
348
- assert.equal(result.valid, false);
349
- assert.match(result.reason ?? "", /slotAllocation signature verification failed/);
350
- });
351
-
352
- test("fails when slot counter is not less than commit counter", async () => {
353
- // Slot at counter 1, commit also at counter 1: ordering violated even
354
- // though every signature is genuine.
355
- const slotFx = await makeSlotFixture({ commitCounter: "1" });
356
- const result = await verifyProofIntegrity({ proof: slotFx.proof });
357
- assert.equal(result.valid, false);
358
- assert.match(result.reason ?? "", /must be less than commit\.counter/);
359
- });
360
- });
361
-
362
- // ---------------------------------------------------------------------------
363
- // Epoch link (bytes-free)
364
- // ---------------------------------------------------------------------------
365
-
366
- describe("verifyProofIntegrity: epochLink", () => {
367
- beforeEach(() => {
368
- resetEpochLinkState();
369
- });
370
-
371
- test("passes for a valid epoch-genesis proof with epochLink", async () => {
372
- const linkFx = await makeEpochLinkFixture();
373
- const result = await verifyProofIntegrity({ proof: linkFx.proof });
374
- assert.deepEqual(result, { valid: true, artifactBinding: "not-checked" });
375
- });
376
-
377
- test("is idempotent for the same successor epoch", async () => {
378
- const linkFx = await makeEpochLinkFixture();
379
- const first = await verifyProofIntegrity({ proof: linkFx.proof });
380
- const second = await verifyProofIntegrity({ proof: linkFx.proof });
381
- assert.equal(first.valid, true);
382
- assert.equal(second.valid, true);
383
- });
384
-
385
- test("fails when predecessor and successor keys are identical", async () => {
386
- const linkFx = await makeEpochLinkFixture({ samePrevKey: true });
387
- const result = await verifyProofIntegrity({ proof: linkFx.proof });
388
- assert.equal(result.valid, false);
389
- assert.match(result.reason ?? "", /different keys/);
390
- });
391
-
392
- /* A rejected proof must not change what the verifier accepts afterwards.
393
- Before 2026-09-20 the single-successor map was written during the epoch
394
- link check, which runs BEFORE the policy check, so a proof refused for an
395
- untrusted measurement still claimed its predecessor and the next honest
396
- proof was reported as a fork. Verification is a function of its inputs. */
397
- test("a proof rejected by policy does not consume its predecessor", async () => {
398
- const rejected = await makeEpochLinkFixture({ toEpochId: "epoch-successor-a" });
399
- const honest = await makeEpochLinkFixture({ toEpochId: "epoch-successor-b" });
400
-
401
- const r1 = await verifyProofIntegrity({
402
- proof: rejected.proof,
403
- trustAnchors: { allowedMeasurements: ["some-other-measurement"] },
404
- });
405
- assert.equal(r1.valid, false);
406
-
407
- const r2 = await verifyProofIntegrity({ proof: honest.proof });
408
- assert.equal(r2.valid, true, r2.valid ? "" : r2.reason);
409
- });
410
-
411
- test("an explicit context keeps one verification's history out of another's", async () => {
412
- const a = await makeEpochLinkFixture({ toEpochId: "epoch-successor-a" });
413
- const b = await makeEpochLinkFixture({ toEpochId: "epoch-successor-b" });
414
- const one = createVerificationContext();
415
- const two = createVerificationContext();
416
-
417
- assert.equal((await verifyProofIntegrity({ proof: a.proof, context: one })).valid, true);
418
- assert.equal((await verifyProofIntegrity({ proof: b.proof, context: two })).valid, true);
419
-
420
- // The same context still catches the fork.
421
- const forked = await verifyProofIntegrity({ proof: b.proof, context: one });
422
- assert.equal(forked.valid, false);
423
- assert.match(forked.reason ?? "", /FORK DETECTED/);
424
- });
425
-
426
- test("detects a fork: same predecessor consumed by two successor epochs", async () => {
427
- const first = await makeEpochLinkFixture({ toEpochId: "epoch-successor-a" });
428
- const second = await makeEpochLinkFixture({ toEpochId: "epoch-successor-b" });
429
-
430
- const r1 = await verifyProofIntegrity({ proof: first.proof });
431
- assert.equal(r1.valid, true);
432
-
433
- const r2 = await verifyProofIntegrity({ proof: second.proof });
434
- assert.equal(r2.valid, false);
435
- assert.match(r2.reason ?? "", /FORK DETECTED/);
436
- });
437
- });
438
-
439
- // ---------------------------------------------------------------------------
440
- // Policy checks (trustAnchors)
441
- // ---------------------------------------------------------------------------
442
-
443
- describe("verifyProofIntegrity: policy (trustAnchors)", () => {
444
- test("passes when measurement is in the allowlist", async () => {
445
- const result = await verifyProofIntegrity({
446
- proof: fx.proof,
447
- trustAnchors: { allowedMeasurements: [fx.measurement] },
448
- });
449
- assert.deepEqual(result, { valid: true, artifactBinding: "not-checked" });
450
- });
451
-
452
- test("fails when measurement is not in the allowlist", async () => {
453
- const result = await verifyProofIntegrity({
454
- proof: fx.proof,
455
- trustAnchors: { allowedMeasurements: ["expected-meas"] },
456
- });
457
- assert.equal(result.valid, false);
458
- assert.match(result.reason ?? "", /measurement/);
459
- });
460
-
461
- test("fails when requireEnforcement does not match", async () => {
462
- const result = await verifyProofIntegrity({
463
- proof: fx.proof,
464
- trustAnchors: { requireEnforcement: "measured-tee" },
465
- });
466
- assert.equal(result.valid, false);
467
- assert.match(result.reason ?? "", /enforcement/);
468
- });
469
-
470
- test("requireSlot fails for a slotless proof and passes for a slot-carrying proof", async () => {
471
- const slotless = await verifyProofIntegrity({
472
- proof: fx.proof,
473
- trustAnchors: { requireSlot: true },
474
- });
475
- assert.equal(slotless.valid, false);
476
- assert.match(slotless.reason ?? "", /slotAllocation/);
477
-
478
- const slotFx = await makeSlotFixture();
479
- const slotted = await verifyProofIntegrity({
480
- proof: slotFx.proof,
481
- trustAnchors: { requireSlot: true },
482
- });
483
- assert.deepEqual(slotted, { valid: true, artifactBinding: "not-checked" });
484
- });
485
-
486
- test("counter policy applies without bytes", async () => {
487
- const slotFx = await makeSlotFixture();
488
- const pass = await verifyProofIntegrity({
489
- proof: slotFx.proof,
490
- trustAnchors: { minCounter: "1" },
491
- });
492
- assert.equal(pass.valid, true);
493
-
494
- const failResult = await verifyProofIntegrity({
495
- proof: slotFx.proof,
496
- trustAnchors: { minCounter: "999" },
497
- });
498
- assert.equal(failResult.valid, false);
499
- assert.match(failResult.reason ?? "", /counter/);
500
- });
501
- });
502
-
503
- // ---------------------------------------------------------------------------
504
- // Regression: verify() behavior unchanged by the shared-pipeline refactor
505
- // ---------------------------------------------------------------------------
506
-
507
- describe("regression: verify() unchanged", () => {
508
- test("valid proof with bytes returns exactly { valid: true }", async () => {
509
- const result = await verify({ proof: fx.proof, bytes: fx.bytes });
510
- assert.deepEqual(result, { valid: true });
511
- });
512
-
513
- test("wrong bytes fail with the exact digest mismatch reason", async () => {
514
- const result = await verify({ proof: fx.proof, bytes: new Uint8Array([9, 9, 9]) });
515
- assert.equal(result.valid, false);
516
- assert.equal(
517
- result.reason,
518
- "artifact digest mismatch: the provided bytes do not match the committed digest",
519
- );
520
- });
521
-
522
- test("tampered signature fails with the exact signature reason", async () => {
523
- const tampered = clone(fx.proof);
524
- tampered.signer.signatureB64 = Buffer.alloc(64).toString("base64");
525
- const result = await verify({ proof: tampered, bytes: fx.bytes });
526
- assert.equal(result.valid, false);
527
- assert.equal(result.reason, "signature verification failed: signature does not match");
528
- });
529
-
530
- test("tampered version fails with the exact version reason", async () => {
531
- const tampered = clone(fx.proof);
532
- (tampered as unknown as Record<string, unknown>)["version"] = "bitgraph/2";
533
- const result = await verify({ proof: tampered, bytes: fx.bytes });
534
- assert.equal(result.valid, false);
535
- assert.equal(result.reason, "unsupported proof version: bitgraph/2");
536
- });
537
-
538
- test("verify() and verifyProofIntegrity() agree on every non-artifact failure", async () => {
539
- const variants: Array<(p: BitGraphProof) => void> = [
540
- (p) => {
541
- (p as unknown as Record<string, unknown>)["version"] = "occ/1";
542
- },
543
- (p) => {
544
- p.signer.signatureB64 = Buffer.alloc(64).toString("base64");
545
- },
546
- (p) => {
547
- p.environment.measurement = "evil-measurement";
548
- },
549
- (p) => {
550
- delete (p as unknown as Record<string, unknown>)["signer"];
551
- },
552
- ];
553
-
554
- for (const mutate of variants) {
555
- const tampered = clone(fx.proof);
556
- mutate(tampered);
557
- const full = await verify({ proof: tampered, bytes: fx.bytes });
558
- const integrity = await verifyProofIntegrity({ proof: tampered });
559
- assert.equal(full.valid, integrity.valid);
560
- assert.equal(full.reason, integrity.reason);
561
- }
562
- });
563
-
564
- test("verify() accepts the slot-carrying fixture with its bytes", async () => {
565
- const slotFx = await makeSlotFixture();
566
- const result = await verify({ proof: slotFx.proof, bytes: slotFx.bytes });
567
- assert.deepEqual(result, { valid: true });
568
- });
569
-
570
- test("verify() accepts the epochLink fixture with its bytes", async () => {
571
- resetEpochLinkState();
572
- const linkFx = await makeEpochLinkFixture();
573
- const result = await verify({ proof: linkFx.proof, bytes: linkFx.bytes });
574
- assert.deepEqual(result, { valid: true });
575
- });
576
- });
@@ -1,47 +0,0 @@
1
- {
2
- "version": "bitgraph/1",
3
- "artifact": {
4
- "hashAlg": "sha256",
5
- "digestB64": "s0SCQLL8QR9pf1U/ep6prd3gF1qXAW6bZVf1S15KbfI="
6
- },
7
- "commit": {
8
- "nonceB64": "/fDc/tHc5VXw1lN6TbdloXwJ9kViJ2Xm6DPqAV4J/m8=",
9
- "counter": "112762",
10
- "slotCounter": "112761",
11
- "slotHashB64": "r2DHz1TJRWnW74PeyxhBKBAFc2yIJBE5AEeQIpEU1vs=",
12
- "epochId": "PlvP2VDcMH9RiBA3shEOrd8xEhHuJj6Gshym/V/qKNg=",
13
- "prevB64": "ZJs0jf97XakAdw1e7fiK3yMKpliUplgw6HgTw50n+bw=",
14
- "chainId": "bitgraph:main"
15
- },
16
- "signer": {
17
- "publicKeyB64": "yiKzaYXZyI+tHiSb7K/+OQv8XwErhez2TTk1efl6XAA=",
18
- "signatureB64": "PhE6MG8SyxFMJIGBSkWPftfs/qZ68liHoJ30i0gv0vHRm86sSrmGyEpxYYcY2gfmYRK+p5BLyOoCXc6bhoXCCA=="
19
- },
20
- "environment": {
21
- "enforcement": "measured-tee",
22
- "measurement": "e2fccbae77ee40aac4830e84f195e05d69eb4547bbd961f4d3459feba10807140424aca42ad03810354982598c86b9cb",
23
- "attestation": {
24
- "format": "aws-nitro",
25
- "reportB64": "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"
26
- }
27
- },
28
- "slotAllocation": {
29
- "version": "bitgraph/slot/1",
30
- "nonceB64": "/fDc/tHc5VXw1lN6TbdloXwJ9kViJ2Xm6DPqAV4J/m8=",
31
- "counter": "112761",
32
- "epochId": "PlvP2VDcMH9RiBA3shEOrd8xEhHuJj6Gshym/V/qKNg=",
33
- "publicKeyB64": "yiKzaYXZyI+tHiSb7K/+OQv8XwErhez2TTk1efl6XAA=",
34
- "chainId": "bitgraph:main",
35
- "signatureB64": "ywygI3mZcy7FR4JhTk7Sdk3MYrLdhXB3dUpv+VoTmpwdgQCBKXnTlzXCjsEv3/RXNmh0gzwnHgUAXrqF+lofDQ=="
36
- },
37
- "attribution": {
38
- "name": "Ethereum Anchor",
39
- "title": "https://etherscan.io/block/25525147",
40
- "message": "0x04f48a70f24f21daae546d1ae49132df9e767ba4238b92ae39f0c153eb1436dc"
41
- },
42
- "proofHash": "H7OZf8C1Ry7cbiFMg6wxfbiqBgWNYpzJDhMePmkmda4=",
43
- "ethereum": {
44
- "blockNumber": 25525147,
45
- "blockHash": "0x04f48a70f24f21daae546d1ae49132df9e767ba4238b92ae39f0c153eb1436dc"
46
- }
47
- }