@pinionengineering/prover-client 0.1.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.
@@ -0,0 +1,126 @@
1
+ /**
2
+ * Challenge construction and deterministic derivation.
3
+ *
4
+ * Ports two Go functions exactly:
5
+ *
6
+ * DeriveChallenge() storage-proofs/line/chalderive.go
7
+ * blockHashG1() storage-proofs/por/sw/pub.go
8
+ *
9
+ * Any deviation from these implementations will produce challenges or
10
+ * verification paths that disagree with the server.
11
+ */
12
+ import { hmac } from '@noble/hashes/hmac';
13
+ import { sha256 } from '@noble/hashes/sha256';
14
+ import { bytesToBigInt, hashToG1 } from './bn254.js';
15
+ /**
16
+ * BN254 (alt_bn128 / Ethereum) subgroup order q.
17
+ * = 21888242871839275222246405745257275088548364400416034343698204186575808495617
18
+ */
19
+ export const BN254_ORDER = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
20
+ // ---------------------------------------------------------------------------
21
+ // Base64 helpers (browser + Node ≥ 18)
22
+ // ---------------------------------------------------------------------------
23
+ /** Encode bytes to base64. */
24
+ export function uint8ToBase64(bytes) {
25
+ let s = '';
26
+ for (let i = 0; i < bytes.length; i++)
27
+ s += String.fromCharCode(bytes[i] ?? 0);
28
+ return btoa(s);
29
+ }
30
+ /** Decode a base64 string to bytes. */
31
+ export function base64ToBytes(b64) {
32
+ const bin = atob(b64);
33
+ const out = new Uint8Array(bin.length);
34
+ for (let i = 0; i < bin.length; i++)
35
+ out[i] = bin.charCodeAt(i);
36
+ return out;
37
+ }
38
+ // ---------------------------------------------------------------------------
39
+ // Challenge construction
40
+ // ---------------------------------------------------------------------------
41
+ /**
42
+ * Build a SW-Pub challenge for POST /prove.
43
+ *
44
+ * Returns a base64-encoded JSON string matching wireChal in
45
+ * storage-proofs/line/swpub/adapter.go:
46
+ * { suite_id, seed, c, n }
47
+ *
48
+ * @param challengeSize Number of blocks to sample (≤ totalBlocks).
49
+ * @param totalBlocks Total blocks in the challenged store.
50
+ */
51
+ export function buildChallenge(challengeSize, totalBlocks) {
52
+ const seed = crypto.getRandomValues(new Uint8Array(32));
53
+ const wireChal = {
54
+ suite_id: 1, // SuiteV1 = HMAC-SHA256
55
+ seed: uint8ToBase64(seed),
56
+ c: Math.min(challengeSize, totalBlocks),
57
+ n: totalBlocks,
58
+ };
59
+ return uint8ToBase64(new TextEncoder().encode(JSON.stringify(wireChal)));
60
+ }
61
+ // ---------------------------------------------------------------------------
62
+ // Deterministic index + coefficient derivation
63
+ // ---------------------------------------------------------------------------
64
+ /**
65
+ * Re-derive the challenge indices and blinding coefficients from a seed.
66
+ *
67
+ * Exact port of DeriveChallenge() in storage-proofs/line/chalderive.go (SuiteV1):
68
+ *
69
+ * idxKey = HMAC-SHA256(seed, "indices")
70
+ * coeffKey = HMAC-SHA256(seed, "coeffs")
71
+ * rank[i] = HMAC-SHA256(idxKey, ids[i]) → sort asc → first c positions
72
+ * coeff[t] = HMAC-SHA256(coeffKey, BE64(t)) mod BN254_ORDER
73
+ *
74
+ * Both challenger (browser) and prover (server) independently call this with
75
+ * the same (seed, ids) to agree on which blocks to challenge without any
76
+ * extra round-trip.
77
+ */
78
+ export function deriveIndicesAndCoeffs(seed, ids, c) {
79
+ const idxKey = hmac(sha256, seed, textBytes('indices'));
80
+ const coeffKey = hmac(sha256, seed, textBytes('coeffs'));
81
+ // Rank each block by HMAC(idxKey, id); sort ascending; take first c.
82
+ const ranked = ids.map((id, pos) => ({ pos, rank: hmac(sha256, idxKey, id) }));
83
+ ranked.sort((a, b) => compareBytes(a.rank, b.rank));
84
+ const indices = ranked.slice(0, c).map((r) => r.pos);
85
+ // Derive coefficients: HMAC(coeffKey, BigEndian(t)) mod order.
86
+ // Go encodes t as a uint64 big-endian — 8 bytes.
87
+ const tbuf = new Uint8Array(8);
88
+ const tview = new DataView(tbuf.buffer);
89
+ const coeffs = [];
90
+ for (let t = 0; t < c; t++) {
91
+ tview.setBigUint64(0, BigInt(t), false); // false = big-endian
92
+ coeffs.push(bytesToBigInt(hmac(sha256, coeffKey, tbuf)) % BN254_ORDER);
93
+ }
94
+ return { indices, coeffs };
95
+ }
96
+ // ---------------------------------------------------------------------------
97
+ // Hash-to-G1
98
+ // ---------------------------------------------------------------------------
99
+ /**
100
+ * H(λ‖id) = HashToG1(λ‖id) using RFC 9380 SVDW.
101
+ *
102
+ * Exact port of blockHashG1() in storage-proofs/por/sw/pub.go.
103
+ * λ is the 16-byte file name from WireClientSetup.name; id is CID.Bytes().
104
+ * Uses DST "sw-pub-v1-BN254G1_XMD:SHA-256_SVDW_RO_" internally.
105
+ */
106
+ export function blockHashG1(name, id) {
107
+ const buf = new Uint8Array(name.length + id.length);
108
+ buf.set(name);
109
+ buf.set(id, name.length);
110
+ return hashToG1(buf);
111
+ }
112
+ // ---------------------------------------------------------------------------
113
+ // Internal helpers
114
+ // ---------------------------------------------------------------------------
115
+ function textBytes(s) {
116
+ return new TextEncoder().encode(s);
117
+ }
118
+ function compareBytes(a, b) {
119
+ const len = Math.min(a.length, b.length);
120
+ for (let i = 0; i < len; i++) {
121
+ if ((a[i] ?? 0) !== (b[i] ?? 0))
122
+ return (a[i] ?? 0) < (b[i] ?? 0) ? -1 : 1;
123
+ }
124
+ return a.length - b.length;
125
+ }
126
+ //# sourceMappingURL=challenge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"challenge.js","sourceRoot":"","sources":["../src/challenge.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * HTTP client for the pinion-prover service.
3
+ *
4
+ * Route structure (urlPathPrefix = "/prover"):
5
+ * Authenticated (JWT Bearer): /prover/api/v1/*
6
+ * Unauthenticated: /prover/prove
7
+ *
8
+ * Pass the full base URL including the path prefix, e.g.:
9
+ * new PinionProverClient("https://hydrogen.pinion.build/prover", { getToken })
10
+ */
11
+ import type { AuditResult, ChallengeKeyInfo, CreateKeyResult, ParsedSetup, RawSetupResponse, TagResponse } from './types.js';
12
+ export interface PinionProverClientOptions {
13
+ /**
14
+ * Returns a JWT Bearer token for authenticated endpoints, or null/undefined
15
+ * if no token is available. Called fresh before every authenticated request.
16
+ */
17
+ getToken?: () => Promise<string | null | undefined>;
18
+ }
19
+ /**
20
+ * Options for the audit() convenience wrapper.
21
+ *
22
+ * For exact control over block count, use buildChallenge(n, total) +
23
+ * prove() + verifyProof() directly.
24
+ */
25
+ export interface AuditOptions {
26
+ /**
27
+ * Subset of root CIDs to challenge. Defaults to all roots in the setup.
28
+ */
29
+ roots?: string[];
30
+ /**
31
+ * Percentage of blocks to sample per round, 0–100. Default 1.
32
+ * Repeated 1% rounds accumulate statistical certainty over time — each round
33
+ * forces the server to prove possession of an independently random sample.
34
+ * Use 100 for a one-shot full audit.
35
+ *
36
+ * For an exact block count use buildChallenge(n, total) + prove() + verifyProof().
37
+ */
38
+ challengePct?: number;
39
+ }
40
+ export declare class PinionProverClient {
41
+ private readonly baseUrl;
42
+ private readonly getToken;
43
+ constructor(baseUrl: string, options?: PinionProverClientOptions);
44
+ listKeys(): Promise<ChallengeKeyInfo[]>;
45
+ /**
46
+ * Create a challenge key and return the key ID along with the public key material.
47
+ *
48
+ * The server generates a key pair and keeps the private scalar α. The returned
49
+ * `publicKey` is the public half: G1 points U[0..s-1] and G2 point V = α·G₂.
50
+ * Store these alongside `keyId` — they are all you need to verify proofs locally,
51
+ * independent of the server returning the same material later.
52
+ */
53
+ createKey(): Promise<CreateKeyResult>;
54
+ deleteKey(keyId: string): Promise<void>;
55
+ /**
56
+ * Fetch the setup document for a key: public key material and the block ID
57
+ * lists for all registered roots.
58
+ *
59
+ * Call this once after tagging to obtain the ParsedSetup needed for auditing.
60
+ * Re-call whenever you add or remove roots.
61
+ */
62
+ getSetup(keyId: string): Promise<ParsedSetup>;
63
+ /**
64
+ * Ask the server to walk the IPFS DAG for root, compute per-block
65
+ * authentication tags, and store them under keyId.
66
+ *
67
+ * The root must already be in the "pinned" lifecycle state for the
68
+ * authenticated account. Call getSetup() after tagging to get the updated
69
+ * block ID lists for the next audit cycle.
70
+ */
71
+ tag(root: string, keyId: string): Promise<TagResponse>;
72
+ deregister(keyId: string, root: string): Promise<void>;
73
+ /**
74
+ * POST /prove — unauthenticated, the server resolves the account from key_id.
75
+ *
76
+ * Returns the raw proof bytes. Most callers should use audit() instead,
77
+ * which also cryptographically verifies the response.
78
+ *
79
+ * @param keyId Challenge key ID.
80
+ * @param roots CID strings to prove, in the same order as the challenge.
81
+ * @param challenge base64(JSON(WireChallenge)) from buildChallenge().
82
+ */
83
+ prove(keyId: string, roots: string[], challenge: string): Promise<Uint8Array>;
84
+ /**
85
+ * Run one audit round against a pre-fetched setup.
86
+ *
87
+ * Builds a random challenge for the requested percentage of blocks, posts it
88
+ * to POST /prove, and cryptographically verifies the response. Pass the
89
+ * ParsedSetup obtained from getSetup() — audit() does not fetch it for you,
90
+ * keeping the setup and audit phases explicit.
91
+ *
92
+ * ```ts
93
+ * // Setup phase — done once (or after adding/removing roots):
94
+ * const { keyId } = await client.createKey();
95
+ * await client.tag(cid, keyId);
96
+ * const setup = await client.getSetup(keyId);
97
+ *
98
+ * // Audit phase — repeat on a schedule:
99
+ * const result = await client.audit(keyId, setup);
100
+ * const result = await client.audit(keyId, setup, { challengePct: 100 });
101
+ * ```
102
+ *
103
+ * Throws `PinNotActiveError` if any challenged root is no longer pinned.
104
+ */
105
+ audit(keyId: string, setup: ParsedSetup, options?: AuditOptions): Promise<AuditResult>;
106
+ private get;
107
+ private post;
108
+ private authDelete;
109
+ private authHeaders;
110
+ private httpError;
111
+ }
112
+ export declare class ProverError extends Error {
113
+ readonly status: number;
114
+ readonly body: string;
115
+ constructor(status: number, body: string);
116
+ }
117
+ /**
118
+ * Thrown by prove() when the server returns 409 because a pin is no longer
119
+ * in the "pinned" lifecycle state. The caller should refresh the key's setup
120
+ * and deregister or re-tag the stale root.
121
+ */
122
+ export declare class PinNotActiveError extends Error {
123
+ readonly cid: string;
124
+ constructor(cid: string);
125
+ }
126
+ /**
127
+ * Decode a raw /setup response into a ParsedSetup.
128
+ * The client_setup field is base64(JSON(WireClientSetup)); roots[].block_ids
129
+ * are base64 CID bytes that get decoded to Uint8Arrays.
130
+ */
131
+ export declare function parseSetupResponse(raw: RawSetupResponse): ParsedSetup;
132
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EACV,WAAW,EACX,gBAAgB,EAEhB,eAAe,EACf,WAAW,EAEX,gBAAgB,EAChB,WAAW,EAEZ,MAAM,YAAY,CAAC;AAIpB,MAAM,WAAW,yBAAyB;IACxC;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;CACrD;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;;OAOG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA2C;gBAExD,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B;IAS9D,QAAQ,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI7C;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,eAAe,CAAC;IAUrC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ7C;;;;;;OAMG;IACG,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAOnD;;;;;;;OAOG;IACG,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAItD,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAU5D;;;;;;;;;OASG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAgBnF;;;;;;;;;;;;;;;;;;;;OAoBG;IACG,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,WAAW,CAAC;YAkClF,GAAG;YAQH,IAAI;YAWJ,UAAU;YAQV,WAAW;YAKX,SAAS;CAIxB;AAMD,qBAAa,WAAY,SAAQ,KAAK;aAElB,MAAM,EAAE,MAAM;aACd,IAAI,EAAE,MAAM;gBADZ,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM;CAK/B;AAED;;;;GAIG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;aACd,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM;CAIxC;AAMD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,gBAAgB,GAAG,WAAW,CAWrE"}
package/dist/client.js ADDED
@@ -0,0 +1,231 @@
1
+ /**
2
+ * HTTP client for the pinion-prover service.
3
+ *
4
+ * Route structure (urlPathPrefix = "/prover"):
5
+ * Authenticated (JWT Bearer): /prover/api/v1/*
6
+ * Unauthenticated: /prover/prove
7
+ *
8
+ * Pass the full base URL including the path prefix, e.g.:
9
+ * new PinionProverClient("https://hydrogen.pinion.build/prover", { getToken })
10
+ */
11
+ import { buildChallenge, base64ToBytes } from './challenge.js';
12
+ import { verifyProof, parseClientSetup } from './verify.js';
13
+ export class PinionProverClient {
14
+ baseUrl;
15
+ getToken;
16
+ constructor(baseUrl, options = {}) {
17
+ this.baseUrl = baseUrl.replace(/\/$/, '');
18
+ this.getToken = options.getToken ?? (() => Promise.resolve(null));
19
+ }
20
+ // ---------------------------------------------------------------------------
21
+ // Challenge key lifecycle
22
+ // ---------------------------------------------------------------------------
23
+ async listKeys() {
24
+ return this.get('/api/v1/challenge-keys');
25
+ }
26
+ /**
27
+ * Create a challenge key and return the key ID along with the public key material.
28
+ *
29
+ * The server generates a key pair and keeps the private scalar α. The returned
30
+ * `publicKey` is the public half: G1 points U[0..s-1] and G2 point V = α·G₂.
31
+ * Store these alongside `keyId` — they are all you need to verify proofs locally,
32
+ * independent of the server returning the same material later.
33
+ */
34
+ async createKey() {
35
+ const raw = await this.post('/api/v1/challenge-key', {
36
+ protocol: 'sw-pub',
37
+ });
38
+ return {
39
+ keyId: raw.key_id,
40
+ publicKey: parseClientSetup(raw.client_setup),
41
+ };
42
+ }
43
+ async deleteKey(keyId) {
44
+ await this.authDelete(`/api/v1/challenge-key/${encodeURIComponent(keyId)}`);
45
+ }
46
+ // ---------------------------------------------------------------------------
47
+ // Setup phase
48
+ // ---------------------------------------------------------------------------
49
+ /**
50
+ * Fetch the setup document for a key: public key material and the block ID
51
+ * lists for all registered roots.
52
+ *
53
+ * Call this once after tagging to obtain the ParsedSetup needed for auditing.
54
+ * Re-call whenever you add or remove roots.
55
+ */
56
+ async getSetup(keyId) {
57
+ const raw = await this.get(`/api/v1/setup?key_id=${encodeURIComponent(keyId)}`);
58
+ return parseSetupResponse(raw);
59
+ }
60
+ /**
61
+ * Ask the server to walk the IPFS DAG for root, compute per-block
62
+ * authentication tags, and store them under keyId.
63
+ *
64
+ * The root must already be in the "pinned" lifecycle state for the
65
+ * authenticated account. Call getSetup() after tagging to get the updated
66
+ * block ID lists for the next audit cycle.
67
+ */
68
+ async tag(root, keyId) {
69
+ return this.post('/api/v1/tag', { root, key_id: keyId });
70
+ }
71
+ async deregister(keyId, root) {
72
+ await this.authDelete(`/api/v1/register/${encodeURIComponent(keyId)}/${encodeURIComponent(root)}`);
73
+ }
74
+ // ---------------------------------------------------------------------------
75
+ // Audit phase
76
+ // ---------------------------------------------------------------------------
77
+ /**
78
+ * POST /prove — unauthenticated, the server resolves the account from key_id.
79
+ *
80
+ * Returns the raw proof bytes. Most callers should use audit() instead,
81
+ * which also cryptographically verifies the response.
82
+ *
83
+ * @param keyId Challenge key ID.
84
+ * @param roots CID strings to prove, in the same order as the challenge.
85
+ * @param challenge base64(JSON(WireChallenge)) from buildChallenge().
86
+ */
87
+ async prove(keyId, roots, challenge) {
88
+ const resp = await fetch(`${this.baseUrl}/prove`, {
89
+ method: 'POST',
90
+ headers: { 'Content-Type': 'application/json' },
91
+ body: JSON.stringify({ key_id: keyId, roots, challenge }),
92
+ });
93
+ if (resp.status === 409) {
94
+ const body = await resp.json().catch(() => ({}));
95
+ throw new PinNotActiveError(String(body['cid'] ?? 'unknown'));
96
+ }
97
+ if (!resp.ok) {
98
+ throw new ProverError(resp.status, await resp.text().catch(() => ''));
99
+ }
100
+ return new Uint8Array(await resp.arrayBuffer());
101
+ }
102
+ /**
103
+ * Run one audit round against a pre-fetched setup.
104
+ *
105
+ * Builds a random challenge for the requested percentage of blocks, posts it
106
+ * to POST /prove, and cryptographically verifies the response. Pass the
107
+ * ParsedSetup obtained from getSetup() — audit() does not fetch it for you,
108
+ * keeping the setup and audit phases explicit.
109
+ *
110
+ * ```ts
111
+ * // Setup phase — done once (or after adding/removing roots):
112
+ * const { keyId } = await client.createKey();
113
+ * await client.tag(cid, keyId);
114
+ * const setup = await client.getSetup(keyId);
115
+ *
116
+ * // Audit phase — repeat on a schedule:
117
+ * const result = await client.audit(keyId, setup);
118
+ * const result = await client.audit(keyId, setup, { challengePct: 100 });
119
+ * ```
120
+ *
121
+ * Throws `PinNotActiveError` if any challenged root is no longer pinned.
122
+ */
123
+ async audit(keyId, setup, options = {}) {
124
+ const targetRoots = options.roots ?? setup.roots.map((r) => r.root);
125
+ const challengePct = options.challengePct ?? 1;
126
+ const rootEntries = targetRoots.map((root) => {
127
+ const entry = setup.roots.find((r) => r.root === root);
128
+ if (!entry)
129
+ throw new Error(`root ${root} not found in setup`);
130
+ return entry;
131
+ });
132
+ // Concatenate block IDs across roots in the same order the server does
133
+ // in ipfs-storage-proofs/ipfsproof.go:NewChallengedList.
134
+ const allBlockIds = rootEntries.flatMap((r) => r.blockIds);
135
+ if (allBlockIds.length === 0)
136
+ throw new Error('no blocks to audit');
137
+ const challengeSize = Math.max(1, Math.round((challengePct / 100) * allBlockIds.length));
138
+ const challenge = buildChallenge(challengeSize, allBlockIds.length);
139
+ const proofBytes = await this.prove(keyId, targetRoots, challenge);
140
+ const pass = verifyProof({
141
+ clientSetup: setup.clientSetup,
142
+ blockIds: allBlockIds,
143
+ challenge,
144
+ proofBytes,
145
+ });
146
+ return { pass, blocksChecked: challengeSize, keyId, roots: targetRoots };
147
+ }
148
+ // ---------------------------------------------------------------------------
149
+ // HTTP helpers
150
+ // ---------------------------------------------------------------------------
151
+ async get(path) {
152
+ const resp = await fetch(`${this.baseUrl}${path}`, {
153
+ headers: await this.authHeaders(),
154
+ });
155
+ if (!resp.ok)
156
+ throw await this.httpError(resp);
157
+ return resp.json();
158
+ }
159
+ async post(path, body) {
160
+ const resp = await fetch(`${this.baseUrl}${path}`, {
161
+ method: 'POST',
162
+ headers: { 'Content-Type': 'application/json', ...(await this.authHeaders()) },
163
+ body: JSON.stringify(body),
164
+ });
165
+ if (!resp.ok)
166
+ throw await this.httpError(resp);
167
+ if (resp.status === 204)
168
+ return undefined;
169
+ return resp.json();
170
+ }
171
+ async authDelete(path) {
172
+ const resp = await fetch(`${this.baseUrl}${path}`, {
173
+ method: 'DELETE',
174
+ headers: await this.authHeaders(),
175
+ });
176
+ if (!resp.ok)
177
+ throw await this.httpError(resp);
178
+ }
179
+ async authHeaders() {
180
+ const token = await this.getToken();
181
+ return token ? { Authorization: `Bearer ${token}` } : {};
182
+ }
183
+ async httpError(resp) {
184
+ const text = await resp.text().catch(() => '');
185
+ return new ProverError(resp.status, text);
186
+ }
187
+ }
188
+ // ---------------------------------------------------------------------------
189
+ // Errors
190
+ // ---------------------------------------------------------------------------
191
+ export class ProverError extends Error {
192
+ status;
193
+ body;
194
+ constructor(status, body) {
195
+ super(`pinion-prover: HTTP ${status}: ${body}`);
196
+ this.status = status;
197
+ this.body = body;
198
+ this.name = 'ProverError';
199
+ }
200
+ }
201
+ /**
202
+ * Thrown by prove() when the server returns 409 because a pin is no longer
203
+ * in the "pinned" lifecycle state. The caller should refresh the key's setup
204
+ * and deregister or re-tag the stale root.
205
+ */
206
+ export class PinNotActiveError extends Error {
207
+ cid;
208
+ constructor(cid) {
209
+ super(`pin ${cid} is not in pinned state`);
210
+ this.cid = cid;
211
+ this.name = 'PinNotActiveError';
212
+ }
213
+ }
214
+ // ---------------------------------------------------------------------------
215
+ // Setup parsing (exported for use without the full client)
216
+ // ---------------------------------------------------------------------------
217
+ /**
218
+ * Decode a raw /setup response into a ParsedSetup.
219
+ * The client_setup field is base64(JSON(WireClientSetup)); roots[].block_ids
220
+ * are base64 CID bytes that get decoded to Uint8Arrays.
221
+ */
222
+ export function parseSetupResponse(raw) {
223
+ const clientSetup = parseClientSetup(raw.client_setup);
224
+ const roots = raw.roots.map((r) => ({
225
+ root: r.root,
226
+ blockIds: r.block_ids.map((id) => base64ToBytes(id)),
227
+ }));
228
+ const totalBlocks = roots.reduce((s, r) => s + r.blockIds.length, 0);
229
+ return { clientSetup, roots, totalBlocks, challengeSize: clientSetup.l };
230
+ }
231
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { PinionProverClient, ProverError, PinNotActiveError, parseSetupResponse, } from './client.js';
2
+ export type { PinionProverClientOptions, AuditOptions } from './client.js';
3
+ export { verifyProof, parseClientSetup } from './verify.js';
4
+ export type { VerifyParams } from './verify.js';
5
+ export { buildChallenge, deriveIndicesAndCoeffs, blockHashG1, base64ToBytes, uint8ToBase64, BN254_ORDER, } from './challenge.js';
6
+ export { g1FromBytes, g2FromBytes, g1ScalarMult, g1Add, atePairing, fp12Equal, bytesToBigInt, G1_BASE, G2_BASE, } from './bn254.js';
7
+ export type { G1Point, G2Point, Fp12Elem } from './bn254.js';
8
+ export type { WireClientSetup, WireChallenge, WireProof, RawTaggedRoot, RawSetupResponse, ParsedRoot, ParsedSetup, ChallengeKeyInfo, CreateKeyResponse, CreateKeyResult, TagResponse, AuditResult, } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,yBAAyB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3E,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC5D,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAGxB,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,KAAK,EACL,UAAU,EACV,SAAS,EACT,aAAa,EACb,OAAO,EACP,OAAO,GACR,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG7D,YAAY,EACV,eAAe,EACf,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,UAAU,EACV,WAAW,EACX,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACX,WAAW,GACZ,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,9 @@
1
+ // High-level client
2
+ export { PinionProverClient, ProverError, PinNotActiveError, parseSetupResponse, } from './client.js';
3
+ // Verification
4
+ export { verifyProof, parseClientSetup } from './verify.js';
5
+ // Challenge construction
6
+ export { buildChallenge, deriveIndicesAndCoeffs, blockHashG1, base64ToBytes, uint8ToBase64, BN254_ORDER, } from './challenge.js';
7
+ // BN254 primitives (for advanced use / other protocols)
8
+ export { g1FromBytes, g2FromBytes, g1ScalarMult, g1Add, atePairing, fp12Equal, bytesToBigInt, G1_BASE, G2_BASE, } from './bn254.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAGrB,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAG5D,yBAAyB;AACzB,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,GACZ,MAAM,gBAAgB,CAAC;AAExB,wDAAwD;AACxD,OAAO,EACL,WAAW,EACX,WAAW,EACX,YAAY,EACZ,KAAK,EACL,UAAU,EACV,SAAS,EACT,aAAa,EACb,OAAO,EACP,OAAO,GACR,MAAM,YAAY,CAAC"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Wire format types for the pinion-prover service.
3
+ *
4
+ * All byte fields (G1/G2 curve points, scalars, seeds) are transmitted as
5
+ * standard base64 strings inside JSON objects. The Go service uses encoding/json
6
+ * which encodes []byte as base64 automatically.
7
+ */
8
+ /**
9
+ * The client_setup blob embedded in SetupResponse.
10
+ * Matches wireClientSetup in storage-proofs/line/swpub/adapter.go.
11
+ */
12
+ export interface WireClientSetup {
13
+ protocol: string;
14
+ suite_id: number;
15
+ s: number;
16
+ l: number;
17
+ name: string;
18
+ v: string;
19
+ u: string[];
20
+ }
21
+ /**
22
+ * The challenge sent to POST /prove.
23
+ * Matches wireChal in storage-proofs/line/swpub/adapter.go.
24
+ * Transmitted as base64(JSON(wireChal)).
25
+ */
26
+ export interface WireChallenge {
27
+ suite_id: number;
28
+ seed: string;
29
+ c: number;
30
+ n: number;
31
+ }
32
+ /**
33
+ * The proof returned by POST /prove as application/octet-stream.
34
+ * Despite the content-type, the body is JSON.
35
+ * Matches wireProof in storage-proofs/line/swpub/adapter.go.
36
+ */
37
+ export interface WireProof {
38
+ sigma: string;
39
+ mu: string[];
40
+ }
41
+ /** One root entry in the setup response. */
42
+ export interface RawTaggedRoot {
43
+ root: string;
44
+ block_ids: string[];
45
+ }
46
+ /** Raw JSON from GET /api/v1/setup?key_id=<id>. */
47
+ export interface RawSetupResponse {
48
+ client_setup: string;
49
+ roots: RawTaggedRoot[];
50
+ }
51
+ /** A root entry with block IDs already decoded to Uint8Arrays. */
52
+ export interface ParsedRoot {
53
+ root: string;
54
+ blockIds: Uint8Array[];
55
+ }
56
+ /** Fully decoded result of getSetup(). Ready to pass to audit(). */
57
+ export interface ParsedSetup {
58
+ clientSetup: WireClientSetup;
59
+ roots: ParsedRoot[];
60
+ /** Sum of block counts across all roots. */
61
+ totalBlocks: number;
62
+ /** The l field from clientSetup: recommended blocks per challenge round. */
63
+ challengeSize: number;
64
+ }
65
+ export interface ChallengeKeyInfo {
66
+ key_id: string;
67
+ protocol: string;
68
+ created_at: string;
69
+ audit_count: number;
70
+ blocks_audited: number;
71
+ }
72
+ /** Raw wire response from POST /api/v1/challenge-key. */
73
+ export interface CreateKeyResponse {
74
+ key_id: string;
75
+ client_setup: string;
76
+ }
77
+ /**
78
+ * Result of createKey() — the key ID plus the decoded public key material.
79
+ *
80
+ * `publicKey` contains the G1/G2 points needed to verify proofs locally.
81
+ * Unlike a symmetric secret, this is the *public* half of the key pair — the
82
+ * private half (α) never leaves the server. You can safely store publicKey
83
+ * alongside keyId so that future audits can verify proofs without trusting the
84
+ * server to return the same key material each time.
85
+ */
86
+ export interface CreateKeyResult {
87
+ keyId: string;
88
+ publicKey: WireClientSetup;
89
+ }
90
+ /**
91
+ * Raw tag response from POST /api/v1/tag.
92
+ *
93
+ * `block_ids` is the ordered list of CID bytes for every block in the DAG.
94
+ * This same list is returned by getSetup() per root and is what the client
95
+ * uses to select which blocks to challenge — the server never picks them.
96
+ */
97
+ export interface TagResponse {
98
+ block_ids: string[];
99
+ }
100
+ /** Result of a complete audit round (challenge → prove → cryptographic verify). */
101
+ export interface AuditResult {
102
+ /** true only if the pairing check e(σ,G₂) == e(A,v) passed. */
103
+ pass: boolean;
104
+ /** Number of blocks sampled in this challenge round. */
105
+ blocksChecked: number;
106
+ keyId: string;
107
+ roots: string[];
108
+ }
109
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,EAAE,CAAC;CACb;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,EAAE,CAAC;CACd;AAED,4CAA4C;AAC5C,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,WAAW,gBAAgB;IAC/B,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED,kEAAkE;AAClE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,UAAU,EAAE,CAAC;CACxB;AAED,oEAAoE;AACpE,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,eAAe,CAAC;IAC7B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,eAAe,CAAC;CAC5B;AAED;;;;;;GAMG;AACH,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,mFAAmF;AACnF,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,IAAI,EAAE,OAAO,CAAC;IACd,wDAAwD;IACxD,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB"}