@mikeargento/bitgraph-verify 1.3.0 → 1.4.0
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/dist/fuse-verify.d.ts +56 -0
- package/dist/fuse-verify.d.ts.map +1 -0
- package/dist/fuse-verify.js +231 -0
- package/dist/fuse-verify.js.map +1 -0
- package/dist/fuse.d.ts +145 -0
- package/dist/fuse.d.ts.map +1 -0
- package/dist/fuse.js +502 -0
- package/dist/fuse.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/fuse-verify.ts +306 -0
- package/src/fuse.ts +570 -0
- package/src/index.ts +33 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { BitGraphProof, VerificationPolicy } from "./types.js";
|
|
2
|
+
import { type FuseFrame, type FuseMarker } from "./fuse.js";
|
|
3
|
+
export type FuseCategory = "RECORDED" | "FUSED_DIRECT" | "FUSED_FROM_ORIGIN" | "RECONSTRUCTION_MISMATCH" | "INVALID_SLOT_COMMITMENT" | "INVALID_ORIGIN_ATTRIBUTION" | "INVALID_UNDERLYING_PROOF" | "UNDETERMINED_PLACEMENT" | "NO_MATCH";
|
|
4
|
+
export interface FuseSpan {
|
|
5
|
+
slotCounter: string;
|
|
6
|
+
commitCounter: string;
|
|
7
|
+
epochId: string;
|
|
8
|
+
chainId: string | null;
|
|
9
|
+
/** commitCounter minus slotCounter, as a decimal string (bigint-safe). */
|
|
10
|
+
positions: string;
|
|
11
|
+
}
|
|
12
|
+
export interface FuseVerifyResult {
|
|
13
|
+
category: FuseCategory;
|
|
14
|
+
/** The underlying bitgraph/1 verification, reported on its own. */
|
|
15
|
+
proof: {
|
|
16
|
+
valid: boolean;
|
|
17
|
+
reason?: string;
|
|
18
|
+
};
|
|
19
|
+
/** Present when the proof or a Frame marks it fused. */
|
|
20
|
+
marker: FuseMarker | null;
|
|
21
|
+
/** The placement that was checked or that matched a registry scan. */
|
|
22
|
+
placement: string | null;
|
|
23
|
+
fileDigestB64: string;
|
|
24
|
+
artifactDigestB64: string;
|
|
25
|
+
originDigestB64: string | null;
|
|
26
|
+
/** Recomputed from the proof's slot record; null when the proof carries none. */
|
|
27
|
+
slotCommitmentB64: string | null;
|
|
28
|
+
span: FuseSpan | null;
|
|
29
|
+
/** Optional span policy (spec 12.1); distinct from cryptographic validity. */
|
|
30
|
+
policy: {
|
|
31
|
+
spanExceeded: boolean;
|
|
32
|
+
maxPositions: string | null;
|
|
33
|
+
};
|
|
34
|
+
/** The bounded statements of spec 10.7, without the wall-clock floor clause. */
|
|
35
|
+
statements: string[];
|
|
36
|
+
reason: string | null;
|
|
37
|
+
}
|
|
38
|
+
export interface FuseVerifyOptions {
|
|
39
|
+
proof: BitGraphProof;
|
|
40
|
+
bytes: Uint8Array;
|
|
41
|
+
/** A Frame or its JSON; its manifest is advisory. */
|
|
42
|
+
frame?: FuseFrame | string | object | null;
|
|
43
|
+
trustAnchors?: VerificationPolicy;
|
|
44
|
+
/** Refuse to accept a span wider than this many positions (M - N). Never affects validity categories. */
|
|
45
|
+
maxPositions?: bigint | number;
|
|
46
|
+
}
|
|
47
|
+
export declare function verifyFuse(opts: FuseVerifyOptions): Promise<FuseVerifyResult>;
|
|
48
|
+
/**
|
|
49
|
+
* Strict ordering between two proofs where counters are comparable (same
|
|
50
|
+
* signer key, epoch, and chain): fused artifact B was assembled after
|
|
51
|
+
* artifact A was committed when commitCounter(A) < slotCounter(B). Returns
|
|
52
|
+
* null when the two are not comparable; an old pooled slot makes this false,
|
|
53
|
+
* never a false positive.
|
|
54
|
+
*/
|
|
55
|
+
export declare function assembledAfterCommit(a: BitGraphProof, b: BitGraphProof): boolean | null;
|
|
56
|
+
//# sourceMappingURL=fuse-verify.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fuse-verify.d.ts","sourceRoot":"","sources":["../src/fuse-verify.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAUL,KAAK,SAAS,EACd,KAAK,UAAU,EAChB,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,YAAY,GACpB,UAAU,GACV,cAAc,GACd,mBAAmB,GACnB,yBAAyB,GACzB,yBAAyB,GACzB,4BAA4B,GAC5B,0BAA0B,GAC1B,wBAAwB,GACxB,UAAU,CAAC;AAEf,MAAM,WAAW,QAAQ;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,0EAA0E;IAC1E,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,YAAY,CAAC;IACvB,mEAAmE;IACnE,KAAK,EAAE;QAAE,KAAK,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,wDAAwD;IACxD,MAAM,EAAE,UAAU,GAAG,IAAI,CAAC;IAC1B,sEAAsE;IACtE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,iFAAiF;IACjF,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;IACtB,8EAA8E;IAC9E,MAAM,EAAE;QAAE,YAAY,EAAE,OAAO,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC/D,gFAAgF;IAChF,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,aAAa,CAAC;IACrB,KAAK,EAAE,UAAU,CAAC;IAClB,qDAAqD;IACrD,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3C,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,yGAAyG;IACzG,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAChC;AAgDD,wBAAsB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAiJnF;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,EAAE,aAAa,GAAG,OAAO,GAAG,IAAI,CAWvF"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
// Copyright (c) 2024-2026 Mike Argento. Licensed under the MIT License. See LICENSE.
|
|
2
|
+
/**
|
|
3
|
+
* BitGraph Fuse verification (spec 10): two paths, one comparison.
|
|
4
|
+
*
|
|
5
|
+
* Given a proof and a file:
|
|
6
|
+
* 1. Verify the proof as an ordinary bitgraph/1 proof. Fail: stop.
|
|
7
|
+
* 2. Hash the file.
|
|
8
|
+
* 3. Hash equals the artifact digest: RECORDED when nothing marks the proof
|
|
9
|
+
* fused; otherwise the file IS the fused bytes: recompute the commitment
|
|
10
|
+
* from the proof's own slot record, locate it in the bytes per the
|
|
11
|
+
* declared placement, compare.
|
|
12
|
+
* 4. Hash equals the origin digest: rebuild the fused bytes from this file,
|
|
13
|
+
* the proof's slot record and the placement; hash; compare with the
|
|
14
|
+
* artifact digest. A false origin cannot yield bytes that hash to the
|
|
15
|
+
* signed artifact digest, which is what makes an unsigned origin hint
|
|
16
|
+
* self-proving.
|
|
17
|
+
* 5. Neither: NO_MATCH. The proof proves nothing about this file.
|
|
18
|
+
*
|
|
19
|
+
* A Fuse failure is never reinterpreted as a valid recorded proof, and the
|
|
20
|
+
* categories are reported separately, never collapsed to one verdict. The
|
|
21
|
+
* wall-clock floor (the last anchored block preceding the slot) needs anchor
|
|
22
|
+
* evidence this package does not carry; the Player computes it. This module
|
|
23
|
+
* reports the causal span [N, M] and the bounded statements without it.
|
|
24
|
+
*/
|
|
25
|
+
import { sha256 } from "@noble/hashes/sha256";
|
|
26
|
+
import { verifyProofIntegrity } from "./verifier.js";
|
|
27
|
+
import { bytesEqual, bytesToBase64, computeSlotCommitment, getPlacement, PLACEMENTS, mergeMarkers, parseFrame, readFrameMarker, readFuseAttribution, } from "./fuse.js";
|
|
28
|
+
function spanOf(proof) {
|
|
29
|
+
const c = proof.commit;
|
|
30
|
+
if (typeof c.counter !== "string" || typeof c.slotCounter !== "string" || typeof c.epochId !== "string")
|
|
31
|
+
return null;
|
|
32
|
+
let positions;
|
|
33
|
+
try {
|
|
34
|
+
positions = (BigInt(c.counter) - BigInt(c.slotCounter)).toString();
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
slotCounter: c.slotCounter,
|
|
41
|
+
commitCounter: c.counter,
|
|
42
|
+
epochId: c.epochId,
|
|
43
|
+
chainId: typeof c.chainId === "string" ? c.chainId : null,
|
|
44
|
+
positions,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function statements(category, span, originMatched) {
|
|
48
|
+
if (span === null)
|
|
49
|
+
return [];
|
|
50
|
+
const out = [];
|
|
51
|
+
// The origin sentence names exactly what was checked. On the origin path the
|
|
52
|
+
// supplied file was rebuilt into the committed artifact, so its existence by
|
|
53
|
+
// M is established. On the direct path only the fused bytes were supplied:
|
|
54
|
+
// an embedded origin digest agreeing with the signed marker is consistency,
|
|
55
|
+
// not a check of the original, and a check that did not run is never a verdict.
|
|
56
|
+
if (category === "FUSED_FROM_ORIGIN") {
|
|
57
|
+
out.push(`The supplied original rebuilds the committed fused artifact byte for byte, so these exact original bytes existed no later than commit position ${span.commitCounter}.`);
|
|
58
|
+
}
|
|
59
|
+
else if (category === "FUSED_DIRECT" && originMatched) {
|
|
60
|
+
out.push("The fused bytes carry an origin digest that matches the signed marker; the original itself was not supplied and was not checked.");
|
|
61
|
+
}
|
|
62
|
+
if (category === "FUSED_DIRECT" || category === "FUSED_FROM_ORIGIN") {
|
|
63
|
+
out.push(`The exact fused bytes could not feasibly have been finalized before their signed slot allocation at position ${span.slotCounter}, and were committed no later than position ${span.commitCounter}.`);
|
|
64
|
+
}
|
|
65
|
+
if (category === "RECORDED") {
|
|
66
|
+
out.push(`These exact bytes existed no later than commit position ${span.commitCounter}.`);
|
|
67
|
+
}
|
|
68
|
+
return out;
|
|
69
|
+
}
|
|
70
|
+
export async function verifyFuse(opts) {
|
|
71
|
+
const { proof, bytes } = opts;
|
|
72
|
+
const frame = opts.frame === undefined || opts.frame === null ? null : (parseFrame(opts.frame) ?? null);
|
|
73
|
+
const fileDigest = sha256(bytes);
|
|
74
|
+
const fileDigestB64 = bytesToBase64(fileDigest);
|
|
75
|
+
const artifactDigestB64 = proof?.artifact?.digestB64 ?? "";
|
|
76
|
+
const base = (category, extra, reason) => ({
|
|
77
|
+
category,
|
|
78
|
+
proof: extra.proof ?? { valid: true },
|
|
79
|
+
marker: extra.marker ?? null,
|
|
80
|
+
placement: extra.placement ?? null,
|
|
81
|
+
fileDigestB64,
|
|
82
|
+
artifactDigestB64,
|
|
83
|
+
originDigestB64: extra.originDigestB64 ?? null,
|
|
84
|
+
slotCommitmentB64: extra.slotCommitmentB64 ?? null,
|
|
85
|
+
span: extra.span ?? null,
|
|
86
|
+
policy: extra.policy ?? { spanExceeded: false, maxPositions: null },
|
|
87
|
+
statements: extra.statements ?? [],
|
|
88
|
+
reason,
|
|
89
|
+
});
|
|
90
|
+
// 1. The underlying proof.
|
|
91
|
+
const integrity = await verifyProofIntegrity(opts.trustAnchors !== undefined ? { proof, trustAnchors: opts.trustAnchors } : { proof });
|
|
92
|
+
if (!integrity.valid) {
|
|
93
|
+
const reason = integrity.reason ?? "proof failed verification";
|
|
94
|
+
return base("INVALID_UNDERLYING_PROOF", { proof: { valid: false, reason } }, reason);
|
|
95
|
+
}
|
|
96
|
+
// The marker: the signed attribution is authoritative for what it declares;
|
|
97
|
+
// the advisory manifest fills in an undeclared placement or origin hint.
|
|
98
|
+
const marker = mergeMarkers(readFuseAttribution(proof), frame !== null ? readFrameMarker(frame) : null);
|
|
99
|
+
const originDigest = marker?.originDigest;
|
|
100
|
+
const originDigestB64 = originDigest !== undefined ? bytesToBase64(originDigest) : null;
|
|
101
|
+
const span = spanOf(proof);
|
|
102
|
+
// Optional span policy, computed once, reported separately from validity.
|
|
103
|
+
const maxPositions = opts.maxPositions === undefined ? null : BigInt(opts.maxPositions);
|
|
104
|
+
const policy = {
|
|
105
|
+
spanExceeded: maxPositions !== null && span !== null && BigInt(span.positions) > maxPositions,
|
|
106
|
+
maxPositions: maxPositions === null ? null : maxPositions.toString(),
|
|
107
|
+
};
|
|
108
|
+
const common = { proof: { valid: true }, marker, originDigestB64, span, policy };
|
|
109
|
+
// 3. The file is the committed bytes.
|
|
110
|
+
if (fileDigestB64 === artifactDigestB64) {
|
|
111
|
+
if (marker === null) {
|
|
112
|
+
return base("RECORDED", { ...common, statements: statements("RECORDED", span, false) }, null);
|
|
113
|
+
}
|
|
114
|
+
const slot = proof.slotAllocation;
|
|
115
|
+
if (slot === undefined) {
|
|
116
|
+
return base("INVALID_SLOT_COMMITMENT", common, "the proof carries no slot record, so no commitment can be recomputed");
|
|
117
|
+
}
|
|
118
|
+
let expected;
|
|
119
|
+
try {
|
|
120
|
+
expected = computeSlotCommitment(slot);
|
|
121
|
+
}
|
|
122
|
+
catch (err) {
|
|
123
|
+
return base("INVALID_SLOT_COMMITMENT", common, `commitment could not be recomputed: ${err instanceof Error ? err.message : String(err)}`);
|
|
124
|
+
}
|
|
125
|
+
const slotCommitmentB64 = bytesToBase64(expected);
|
|
126
|
+
let placement = marker.placement === null ? undefined : getPlacement(marker.placement);
|
|
127
|
+
let located = placement === undefined ? null : placement.locate(bytes);
|
|
128
|
+
if (marker.placement === null) {
|
|
129
|
+
// Undeclared: try the registry in its fixed order and report the one that matched.
|
|
130
|
+
for (const p of PLACEMENTS) {
|
|
131
|
+
const l = p.locate(bytes);
|
|
132
|
+
if (l !== null) {
|
|
133
|
+
placement = p;
|
|
134
|
+
located = l;
|
|
135
|
+
break;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
if (placement === undefined) {
|
|
139
|
+
return base("INVALID_SLOT_COMMITMENT", { ...common, slotCommitmentB64 }, "no registered placement finds a commitment in the fused bytes");
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (placement === undefined) {
|
|
143
|
+
return base("UNDETERMINED_PLACEMENT", { ...common, slotCommitmentB64 }, `placement "${marker.placement}" is not registered; the commitment cannot be located`);
|
|
144
|
+
}
|
|
145
|
+
if (located === null) {
|
|
146
|
+
return base("INVALID_SLOT_COMMITMENT", { ...common, slotCommitmentB64, placement: placement.id }, `no ${placement.id} commitment found in the fused bytes`);
|
|
147
|
+
}
|
|
148
|
+
if (!bytesEqual(located.commitment, expected)) {
|
|
149
|
+
return base("INVALID_SLOT_COMMITMENT", { ...common, slotCommitmentB64, placement: placement.id }, "the commitment in the fused bytes does not match the proof's slot record");
|
|
150
|
+
}
|
|
151
|
+
// Origin consistency: what the fused bytes say about the origin versus the marker.
|
|
152
|
+
let originMatched = false;
|
|
153
|
+
if (originDigest !== undefined) {
|
|
154
|
+
const embedded = located.originDigest ?? (located.originalBytes !== undefined ? sha256(located.originalBytes) : undefined);
|
|
155
|
+
if (embedded !== undefined) {
|
|
156
|
+
if (!bytesEqual(embedded, originDigest)) {
|
|
157
|
+
return base("INVALID_ORIGIN_ATTRIBUTION", { ...common, slotCommitmentB64, placement: placement.id }, marker.originSource === "attribution"
|
|
158
|
+
? "the origin digest in the signed attribution does not match the origin inside the fused bytes"
|
|
159
|
+
: "the origin digest in the manifest does not match the origin inside the fused bytes");
|
|
160
|
+
}
|
|
161
|
+
originMatched = true;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return base("FUSED_DIRECT", { ...common, slotCommitmentB64, placement: placement.id, statements: statements("FUSED_DIRECT", span, originMatched) }, null);
|
|
165
|
+
}
|
|
166
|
+
// 4. The file is the original: rebuild the fused bytes.
|
|
167
|
+
if (originDigest !== undefined && bytesEqual(fileDigest, originDigest)) {
|
|
168
|
+
const slot = proof.slotAllocation;
|
|
169
|
+
if (slot === undefined) {
|
|
170
|
+
return base("INVALID_SLOT_COMMITMENT", common, "the proof carries no slot record, so the fused bytes cannot be rebuilt");
|
|
171
|
+
}
|
|
172
|
+
let commitment;
|
|
173
|
+
try {
|
|
174
|
+
commitment = computeSlotCommitment(slot);
|
|
175
|
+
}
|
|
176
|
+
catch (err) {
|
|
177
|
+
return base("INVALID_SLOT_COMMITMENT", common, `commitment could not be recomputed: ${err instanceof Error ? err.message : String(err)}`);
|
|
178
|
+
}
|
|
179
|
+
const slotCommitmentB64 = bytesToBase64(commitment);
|
|
180
|
+
const declared = marker !== null && marker.placement !== null ? getPlacement(marker.placement) : undefined;
|
|
181
|
+
if (marker !== null && marker.placement !== null && declared === undefined) {
|
|
182
|
+
return base("UNDETERMINED_PLACEMENT", { ...common, slotCommitmentB64 }, `placement "${marker.placement}" is not registered; the fused bytes cannot be rebuilt`);
|
|
183
|
+
}
|
|
184
|
+
const candidates = declared !== undefined ? [declared] : PLACEMENTS.filter((p) => p.byteExact);
|
|
185
|
+
const artifactDigest = proof.artifact.digestB64;
|
|
186
|
+
for (const p of candidates) {
|
|
187
|
+
if (!p.byteExact)
|
|
188
|
+
continue;
|
|
189
|
+
let rebuilt;
|
|
190
|
+
try {
|
|
191
|
+
rebuilt = p.build({ original: bytes, originDigest, commitment });
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (bytesToBase64(sha256(rebuilt)) === artifactDigest) {
|
|
197
|
+
return base("FUSED_FROM_ORIGIN", { ...common, slotCommitmentB64, placement: p.id, statements: statements("FUSED_FROM_ORIGIN", span, true) }, null);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
return base("RECONSTRUCTION_MISMATCH", { ...common, slotCommitmentB64, placement: declared?.id ?? null }, declared !== undefined
|
|
201
|
+
? `rebuilding ${declared.id} from this file and the proof's slot record does not reproduce the committed artifact digest`
|
|
202
|
+
: "no registered byte-exact placement rebuilds the committed artifact digest from this file");
|
|
203
|
+
}
|
|
204
|
+
// 5. Neither.
|
|
205
|
+
return base("NO_MATCH", common, "this file matches neither the committed artifact digest nor the origin digest; the proof proves nothing about it");
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Strict ordering between two proofs where counters are comparable (same
|
|
209
|
+
* signer key, epoch, and chain): fused artifact B was assembled after
|
|
210
|
+
* artifact A was committed when commitCounter(A) < slotCounter(B). Returns
|
|
211
|
+
* null when the two are not comparable; an old pooled slot makes this false,
|
|
212
|
+
* never a false positive.
|
|
213
|
+
*/
|
|
214
|
+
export function assembledAfterCommit(a, b) {
|
|
215
|
+
const chain = (p) => p.commit.chainId ?? null;
|
|
216
|
+
if (a.signer.publicKeyB64 !== b.signer.publicKeyB64)
|
|
217
|
+
return null;
|
|
218
|
+
if (a.commit.epochId === undefined || a.commit.epochId !== b.commit.epochId)
|
|
219
|
+
return null;
|
|
220
|
+
if (chain(a) !== chain(b))
|
|
221
|
+
return null;
|
|
222
|
+
if (typeof a.commit.counter !== "string" || typeof b.commit.slotCounter !== "string")
|
|
223
|
+
return null;
|
|
224
|
+
try {
|
|
225
|
+
return BigInt(a.commit.counter) < BigInt(b.commit.slotCounter);
|
|
226
|
+
}
|
|
227
|
+
catch {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=fuse-verify.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fuse-verify.js","sourceRoot":"","sources":["../src/fuse-verify.ts"],"names":[],"mappings":"AAAA,qFAAqF;AAErF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAErD,OAAO,EACL,UAAU,EACV,aAAa,EACb,qBAAqB,EACrB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,UAAU,EACV,eAAe,EACf,mBAAmB,GAGpB,MAAM,WAAW,CAAC;AAqDnB,SAAS,MAAM,CAAC,KAAoB;IAClC,MAAM,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACvB,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACrH,IAAI,SAAiB,CAAC;IACtB,IAAI,CAAC;QACH,SAAS,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO;QACL,WAAW,EAAE,CAAC,CAAC,WAAW;QAC1B,aAAa,EAAE,CAAC,CAAC,OAAO;QACxB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,OAAO,EAAE,OAAQ,CAA2B,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAG,CAA0B,CAAC,OAAkB,CAAC,CAAC,CAAC,IAAI;QAC1H,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,QAAsB,EAAE,IAAqB,EAAE,aAAsB;IACvF,IAAI,IAAI,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,6EAA6E;IAC7E,6EAA6E;IAC7E,2EAA2E;IAC3E,4EAA4E;IAC5E,gFAAgF;IAChF,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;QACrC,GAAG,CAAC,IAAI,CACN,kJAAkJ,IAAI,CAAC,aAAa,GAAG,CACxK,CAAC;IACJ,CAAC;SAAM,IAAI,QAAQ,KAAK,cAAc,IAAI,aAAa,EAAE,CAAC;QACxD,GAAG,CAAC,IAAI,CACN,kIAAkI,CACnI,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,KAAK,cAAc,IAAI,QAAQ,KAAK,mBAAmB,EAAE,CAAC;QACpE,GAAG,CAAC,IAAI,CACN,gHAAgH,IAAI,CAAC,WAAW,+CAA+C,IAAI,CAAC,aAAa,GAAG,CACrM,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC5B,GAAG,CAAC,IAAI,CAAC,2DAA2D,IAAI,CAAC,aAAa,GAAG,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAuB;IACtD,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC;IAC9B,MAAM,KAAK,GAAqB,IAAI,CAAC,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,CAAC;IAC1H,MAAM,UAAU,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,aAAa,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;IAChD,MAAM,iBAAiB,GAAG,KAAK,EAAE,QAAQ,EAAE,SAAS,IAAI,EAAE,CAAC;IAE3D,MAAM,IAAI,GAAG,CAAC,QAAsB,EAAE,KAAgC,EAAE,MAAqB,EAAoB,EAAE,CAAC,CAAC;QACnH,QAAQ;QACR,KAAK,EAAE,KAAK,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;QACrC,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,IAAI;QAC5B,SAAS,EAAE,KAAK,CAAC,SAAS,IAAI,IAAI;QAClC,aAAa;QACb,iBAAiB;QACjB,eAAe,EAAE,KAAK,CAAC,eAAe,IAAI,IAAI;QAC9C,iBAAiB,EAAE,KAAK,CAAC,iBAAiB,IAAI,IAAI;QAClD,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,IAAI;QACxB,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE;QACnE,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,EAAE;QAClC,MAAM;KACP,CAAC,CAAC;IAEH,2BAA2B;IAC3B,MAAM,SAAS,GAAG,MAAM,oBAAoB,CAC1C,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,YAAY,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CACzF,CAAC;IACF,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACrB,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,2BAA2B,CAAC;QAC/D,OAAO,IAAI,CAAC,0BAA0B,EAAE,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC;IACvF,CAAC;IAED,4EAA4E;IAC5E,yEAAyE;IACzE,MAAM,MAAM,GAAsB,YAAY,CAAC,mBAAmB,CAAC,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC3H,MAAM,YAAY,GAAG,MAAM,EAAE,YAAY,CAAC;IAC1C,MAAM,eAAe,GAAG,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxF,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAE3B,0EAA0E;IAC1E,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxF,MAAM,MAAM,GAAG;QACb,YAAY,EAAE,YAAY,KAAK,IAAI,IAAI,IAAI,KAAK,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,YAAY;QAC7F,YAAY,EAAE,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,EAAE;KACrE,CAAC;IAEF,MAAM,MAAM,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAEjF,sCAAsC;IACtC,IAAI,aAAa,KAAK,iBAAiB,EAAE,CAAC;QACxC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,IAAI,CAAC,UAAU,EAAE,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;QAChG,CAAC;QACD,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,CAAC;QAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,yBAAyB,EAAE,MAAM,EAAE,sEAAsE,CAAC,CAAC;QACzH,CAAC;QACD,IAAI,QAAoB,CAAC;QACzB,IAAI,CAAC;YACH,QAAQ,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,yBAAyB,EAAE,MAAM,EAAE,uCAAuC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5I,CAAC;QACD,MAAM,iBAAiB,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAC;QAClD,IAAI,SAAS,GAAG,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QACvF,IAAI,OAAO,GAAG,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC9B,mFAAmF;YACnF,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC1B,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;oBAAC,SAAS,GAAG,CAAC,CAAC;oBAAC,OAAO,GAAG,CAAC,CAAC;oBAAC,MAAM;gBAAC,CAAC;YACxD,CAAC;YACD,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;gBAC5B,OAAO,IAAI,CAAC,yBAAyB,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,EAAE,+DAA+D,CAAC,CAAC;YAC5I,CAAC;QACH,CAAC;aAAM,IAAI,SAAS,KAAK,SAAS,EAAE,CAAC;YACnC,OAAO,IAAI,CAAC,wBAAwB,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,EAAE,cAAc,MAAM,CAAC,SAAS,uDAAuD,CAAC,CAAC;QACjK,CAAC;QACD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,OAAO,IAAI,CAAC,yBAAyB,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC,EAAE,sCAAsC,CAAC,CAAC;QAC9J,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,QAAQ,CAAC,EAAE,CAAC;YAC9C,OAAO,IAAI,CAAC,yBAAyB,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,0EAA0E,CAAC,CAAC;QAChL,CAAC;QACD,mFAAmF;QACnF,IAAI,aAAa,GAAG,KAAK,CAAC;QAC1B,IAAI,YAAY,KAAK,SAAS,EAAE,CAAC;YAC/B,MAAM,QAAQ,GAAG,OAAO,CAAC,YAAY,IAAI,CAAC,OAAO,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC3H,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,YAAY,CAAC,EAAE,CAAC;oBACxC,OAAO,IAAI,CACT,4BAA4B,EAC5B,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,EACzD,MAAM,CAAC,YAAY,KAAK,aAAa;wBACnC,CAAC,CAAC,8FAA8F;wBAChG,CAAC,CAAC,oFAAoF,CACzF,CAAC;gBACJ,CAAC;gBACD,aAAa,GAAG,IAAI,CAAC;YACvB,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,SAAS,CAAC,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,cAAc,EAAE,IAAI,EAAE,aAAa,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAC5J,CAAC;IAED,wDAAwD;IACxD,IAAI,YAAY,KAAK,SAAS,IAAI,UAAU,CAAC,UAAU,EAAE,YAAY,CAAC,EAAE,CAAC;QACvE,MAAM,IAAI,GAAG,KAAK,CAAC,cAAc,CAAC;QAClC,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,yBAAyB,EAAE,MAAM,EAAE,wEAAwE,CAAC,CAAC;QAC3H,CAAC;QACD,IAAI,UAAsB,CAAC;QAC3B,IAAI,CAAC;YACH,UAAU,GAAG,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC3C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,IAAI,CAAC,yBAAyB,EAAE,MAAM,EAAE,uCAAuC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5I,CAAC;QACD,MAAM,iBAAiB,GAAG,aAAa,CAAC,UAAU,CAAC,CAAC;QACpD,MAAM,QAAQ,GAAG,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC3G,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,CAAC,SAAS,KAAK,IAAI,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;YAC3E,OAAO,IAAI,CAAC,wBAAwB,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,EAAE,cAAc,MAAM,CAAC,SAAS,wDAAwD,CAAC,CAAC;QAClK,CAAC;QACD,MAAM,UAAU,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/F,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QAChD,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;YAC3B,IAAI,CAAC,CAAC,CAAC,SAAS;gBAAE,SAAS;YAC3B,IAAI,OAAmB,CAAC;YACxB,IAAI,CAAC;gBACH,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC,CAAC;YACnE,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;YACD,IAAI,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,cAAc,EAAE,CAAC;gBACtD,OAAO,IAAI,CAAC,mBAAmB,EAAE,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,mBAAmB,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;YACrJ,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CACT,yBAAyB,EACzB,EAAE,GAAG,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAI,EAAE,EACjE,QAAQ,KAAK,SAAS;YACpB,CAAC,CAAC,cAAc,QAAQ,CAAC,EAAE,8FAA8F;YACzH,CAAC,CAAC,0FAA0F,CAC/F,CAAC;IACJ,CAAC;IAED,cAAc;IACd,OAAO,IAAI,CAAC,UAAU,EAAE,MAAM,EAAE,kHAAkH,CAAC,CAAC;AACtJ,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,CAAgB,EAAE,CAAgB;IACrE,MAAM,KAAK,GAAG,CAAC,CAAgB,EAAE,EAAE,CAAE,CAAC,CAAC,MAA+B,CAAC,OAAO,IAAI,IAAI,CAAC;IACvF,IAAI,CAAC,CAAC,MAAM,CAAC,YAAY,KAAK,CAAC,CAAC,MAAM,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IACjE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACzF,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,MAAM,CAAC,WAAW,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAClG,IAAI,CAAC;QACH,OAAO,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
package/dist/fuse.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { Attribution, BitGraphProof, SlotAllocation } from "./types.js";
|
|
2
|
+
export declare const FUSE_PROFILE: "bitgraph-fuse/1";
|
|
3
|
+
/** Domain separation prefix: the 15 profile bytes followed by one zero byte. */
|
|
4
|
+
export declare const FUSE_DOMAIN: Uint8Array;
|
|
5
|
+
/**
|
|
6
|
+
* The signed attribution name that marks a fused proof (spec 6.5): the profile
|
|
7
|
+
* id itself, the stable wire identifier of this construction. A product name
|
|
8
|
+
* may change; the v1 wire identifier does not (ruled 2026-09-03).
|
|
9
|
+
*/
|
|
10
|
+
export declare const FUSE_ATTRIBUTION_NAME: "bitgraph-fuse/1";
|
|
11
|
+
/** Trailer placement: 8 ASCII magic bytes, 8 reserved zero bytes, 32 commitment bytes. */
|
|
12
|
+
export declare const TRAILER_MAGIC: "BGFUSE01";
|
|
13
|
+
export declare const TRAILER_LENGTH = 48;
|
|
14
|
+
/** Fixed paths inside a container/1 archive. */
|
|
15
|
+
export declare const CONTAINER_MANIFEST_PATH: "bitgraph-fuse/manifest.json";
|
|
16
|
+
export declare const CONTAINER_ORIGINAL_PATH: "bitgraph-fuse/original";
|
|
17
|
+
export declare function bytesToBase64(bytes: Uint8Array): string;
|
|
18
|
+
/** Strict standard base64 (RFC 4648 section 4): no whitespace, no URL-safe alphabet, correct padding. */
|
|
19
|
+
export declare function base64ToBytes(b64: string): Uint8Array | null;
|
|
20
|
+
export declare function bytesToHex(bytes: Uint8Array): string;
|
|
21
|
+
/** Lowercase hex only; uppercase is rejected so one digest has one spelling. */
|
|
22
|
+
export declare function hexToBytes(hex: string): Uint8Array | null;
|
|
23
|
+
export declare function bytesEqual(a: Uint8Array, b: Uint8Array): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* The enclave's canonical slot body: the signed subset of the slot record,
|
|
26
|
+
* excluding signatureB64, with `time` and `chainId` present only when the
|
|
27
|
+
* record carries them. Identical to the reconstruction in verifier.ts
|
|
28
|
+
* (verifySlotAllocation) and to the enclave's own slotBody. There is exactly
|
|
29
|
+
* one serialization of a slot record; this is it.
|
|
30
|
+
*/
|
|
31
|
+
export declare function canonicalSlotBody(slot: SlotAllocation): Record<string, unknown>;
|
|
32
|
+
/** SHA-256 of the canonical slot body; equals the proof's commit.slotHashB64. */
|
|
33
|
+
export declare function computeSlotRecordHash(slot: SlotAllocation): Uint8Array;
|
|
34
|
+
/** The exact preimage of the commitment, for vectors and audits: domain || slotRecordHash || nonce. */
|
|
35
|
+
export declare function slotCommitmentPreimage(slot: SlotAllocation): Uint8Array;
|
|
36
|
+
/** slotCommitment = SHA256(domain || slotRecordHash || nonce). */
|
|
37
|
+
export declare function computeSlotCommitment(slot: SlotAllocation): Uint8Array;
|
|
38
|
+
export interface FusePayload {
|
|
39
|
+
type: typeof FUSE_PROFILE;
|
|
40
|
+
origin?: {
|
|
41
|
+
algorithm: "sha256";
|
|
42
|
+
digest: string;
|
|
43
|
+
};
|
|
44
|
+
slotCommitment: {
|
|
45
|
+
algorithm: "sha256";
|
|
46
|
+
digest: string;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Build the canonical Form C payload bytes (spec 6.2). Digests are lowercase hex. */
|
|
50
|
+
export declare function buildFusePayload(commitment: Uint8Array, originDigest?: Uint8Array): Uint8Array;
|
|
51
|
+
/**
|
|
52
|
+
* Strict parse of Form C bytes. The bytes must be valid UTF-8 JSON, a plain
|
|
53
|
+
* object with exactly the allowed keys, the profile type, lowercase-hex
|
|
54
|
+
* 32-byte digests, and must equal their own re-canonicalization byte for byte
|
|
55
|
+
* (which rejects whitespace, key-order games, and duplicate keys, since a
|
|
56
|
+
* duplicate cannot survive a round trip). Returns null on any deviation.
|
|
57
|
+
*/
|
|
58
|
+
export declare function parseFusePayload(bytes: Uint8Array): {
|
|
59
|
+
commitment: Uint8Array;
|
|
60
|
+
originDigest?: Uint8Array;
|
|
61
|
+
} | null;
|
|
62
|
+
export type PlacementId = "trailer/1" | "container/1" | "produced/1";
|
|
63
|
+
export interface Located {
|
|
64
|
+
/** The commitment found in the fused bytes. */
|
|
65
|
+
commitment: Uint8Array;
|
|
66
|
+
/** The origin digest written into the fused bytes, when the placement writes one. */
|
|
67
|
+
originDigest?: Uint8Array;
|
|
68
|
+
/** The original's bytes as carried inside the fused bytes, for placements that carry them. */
|
|
69
|
+
originalBytes?: Uint8Array;
|
|
70
|
+
}
|
|
71
|
+
export interface Placement {
|
|
72
|
+
readonly id: PlacementId;
|
|
73
|
+
/** A: in-file placement of an existing original; B: container; C: produced artifact. */
|
|
74
|
+
readonly form: "A" | "B" | "C";
|
|
75
|
+
/** True when the fused bytes are a deterministic function of (original, proof, placement). */
|
|
76
|
+
readonly byteExact: boolean;
|
|
77
|
+
/** Build the fused bytes. Forms A and B require `original`; Form C forbids it. */
|
|
78
|
+
build(input: {
|
|
79
|
+
original?: Uint8Array;
|
|
80
|
+
originDigest?: Uint8Array;
|
|
81
|
+
commitment: Uint8Array;
|
|
82
|
+
}): Uint8Array;
|
|
83
|
+
/** Find the commitment in fused bytes, or null when the marker is absent or malformed. */
|
|
84
|
+
locate(fused: Uint8Array): Located | null;
|
|
85
|
+
}
|
|
86
|
+
/** Registered placements in the fixed order a verifier tries them when none is declared. */
|
|
87
|
+
export declare const PLACEMENTS: readonly Placement[];
|
|
88
|
+
export declare function getPlacement(id: string): Placement | undefined;
|
|
89
|
+
/** attribution.name = "bitgraph-fuse/1" (the profile id), title = placement id, message = origin digest in standard base64. */
|
|
90
|
+
export declare function fuseAttribution(placement: PlacementId, originDigest?: Uint8Array): Attribution;
|
|
91
|
+
export type MarkerSource = "attribution" | "manifest";
|
|
92
|
+
/**
|
|
93
|
+
* What marks a proof as fused, and where each fact came from. The signed
|
|
94
|
+
* attribution is authoritative for what it declares; a Frame's advisory
|
|
95
|
+
* manifest may fill in what the signature leaves undeclared (an origin hint,
|
|
96
|
+
* a placement), and is made self-proving only by reconstruction.
|
|
97
|
+
*/
|
|
98
|
+
export interface FuseMarker {
|
|
99
|
+
/** The placement id, or null when none is declared (a verifier then tries the registry in order). */
|
|
100
|
+
placement: string | null;
|
|
101
|
+
placementSource: MarkerSource | null;
|
|
102
|
+
originDigest?: Uint8Array;
|
|
103
|
+
originSource?: MarkerSource;
|
|
104
|
+
/** "attribution" when the proof's signed attribution marks it fused, else "manifest". */
|
|
105
|
+
source: MarkerSource;
|
|
106
|
+
}
|
|
107
|
+
/** Read the fused marker from a proof's signed attribution, or null when the proof is not marked fused. */
|
|
108
|
+
export declare function readFuseAttribution(proof: BitGraphProof): FuseMarker | null;
|
|
109
|
+
/** Merge the signed marker with a manifest marker: the signature wins wherever it declares. */
|
|
110
|
+
export declare function mergeMarkers(signed: FuseMarker | null, manifest: FuseMarker | null): FuseMarker | null;
|
|
111
|
+
export interface FuseFrame {
|
|
112
|
+
type: typeof FUSE_PROFILE;
|
|
113
|
+
manifest: {
|
|
114
|
+
/** Empty string when the placement is left undeclared. */
|
|
115
|
+
placement: string;
|
|
116
|
+
origin?: {
|
|
117
|
+
algorithm: "sha256";
|
|
118
|
+
digest: string;
|
|
119
|
+
};
|
|
120
|
+
artifact: {
|
|
121
|
+
algorithm: "sha256";
|
|
122
|
+
digest: string;
|
|
123
|
+
};
|
|
124
|
+
fusedFile: string | null;
|
|
125
|
+
};
|
|
126
|
+
fusePayload?: FusePayload;
|
|
127
|
+
proof: BitGraphProof;
|
|
128
|
+
}
|
|
129
|
+
export declare function buildFrame(input: {
|
|
130
|
+
proof: BitGraphProof;
|
|
131
|
+
placement: PlacementId;
|
|
132
|
+
artifactDigest: Uint8Array;
|
|
133
|
+
originDigest?: Uint8Array;
|
|
134
|
+
fusedFile: string | null;
|
|
135
|
+
fusePayload?: Uint8Array;
|
|
136
|
+
}): FuseFrame;
|
|
137
|
+
/**
|
|
138
|
+
* Structural read of a Frame. The manifest is advisory: nothing here is
|
|
139
|
+
* trusted beyond its shape, and the nested proof is returned exactly as
|
|
140
|
+
* found for the ordinary verifier. Null when this is not a Frame.
|
|
141
|
+
*/
|
|
142
|
+
export declare function parseFrame(input: unknown): FuseFrame | null;
|
|
143
|
+
/** Marker from a Frame's advisory manifest (unsigned; made self-proving only by reconstruction). */
|
|
144
|
+
export declare function readFrameMarker(frame: FuseFrame): FuseMarker;
|
|
145
|
+
//# sourceMappingURL=fuse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fuse.d.ts","sourceRoot":"","sources":["../src/fuse.ts"],"names":[],"mappings":"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"}
|