@fluxpointstudios/orynq-sdk-midnight-prover 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.
- package/LICENSE +21 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +89 -0
- package/dist/index.js.map +1 -0
- package/dist/linking/cardano-anchor-link.d.ts +250 -0
- package/dist/linking/cardano-anchor-link.d.ts.map +1 -0
- package/dist/linking/cardano-anchor-link.js +447 -0
- package/dist/linking/cardano-anchor-link.js.map +1 -0
- package/dist/linking/index.d.ts +33 -0
- package/dist/linking/index.d.ts.map +1 -0
- package/dist/linking/index.js +31 -0
- package/dist/linking/index.js.map +1 -0
- package/dist/linking/proof-publication.d.ts +217 -0
- package/dist/linking/proof-publication.d.ts.map +1 -0
- package/dist/linking/proof-publication.js +385 -0
- package/dist/linking/proof-publication.js.map +1 -0
- package/dist/midnight/index.d.ts +30 -0
- package/dist/midnight/index.d.ts.map +1 -0
- package/dist/midnight/index.js +27 -0
- package/dist/midnight/index.js.map +1 -0
- package/dist/midnight/proof-server-client.d.ts +236 -0
- package/dist/midnight/proof-server-client.d.ts.map +1 -0
- package/dist/midnight/proof-server-client.js +422 -0
- package/dist/midnight/proof-server-client.js.map +1 -0
- package/dist/midnight/public-inputs.d.ts +134 -0
- package/dist/midnight/public-inputs.d.ts.map +1 -0
- package/dist/midnight/public-inputs.js +338 -0
- package/dist/midnight/public-inputs.js.map +1 -0
- package/dist/midnight/witness-builder.d.ts +119 -0
- package/dist/midnight/witness-builder.d.ts.map +1 -0
- package/dist/midnight/witness-builder.js +238 -0
- package/dist/midnight/witness-builder.js.map +1 -0
- package/dist/proofs/hash-chain-proof.d.ts +171 -0
- package/dist/proofs/hash-chain-proof.d.ts.map +1 -0
- package/dist/proofs/hash-chain-proof.js +437 -0
- package/dist/proofs/hash-chain-proof.js.map +1 -0
- package/dist/proofs/index.d.ts +35 -0
- package/dist/proofs/index.d.ts.map +1 -0
- package/dist/proofs/index.js +34 -0
- package/dist/proofs/index.js.map +1 -0
- package/dist/proofs/policy-compliance-proof.d.ts +165 -0
- package/dist/proofs/policy-compliance-proof.d.ts.map +1 -0
- package/dist/proofs/policy-compliance-proof.js +514 -0
- package/dist/proofs/policy-compliance-proof.js.map +1 -0
- package/dist/proofs/selective-disclosure.d.ts +213 -0
- package/dist/proofs/selective-disclosure.d.ts.map +1 -0
- package/dist/proofs/selective-disclosure.js +629 -0
- package/dist/proofs/selective-disclosure.js.map +1 -0
- package/dist/prover-interface.d.ts +288 -0
- package/dist/prover-interface.d.ts.map +1 -0
- package/dist/prover-interface.js +114 -0
- package/dist/prover-interface.js.map +1 -0
- package/dist/prover.d.ts +163 -0
- package/dist/prover.d.ts.map +1 -0
- package/dist/prover.js +417 -0
- package/dist/prover.js.map +1 -0
- package/dist/types.d.ts +410 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +128 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
- package/src/__tests__/hash-chain-proof.test.ts +709 -0
- package/src/__tests__/midnight-prover.test.ts +716 -0
- package/src/__tests__/policy-compliance.test.ts +567 -0
- package/src/__tests__/proof-publication.test.ts +644 -0
- package/src/__tests__/selective-disclosure.test.ts +921 -0
- package/src/index.ts +260 -0
- package/src/linking/cardano-anchor-link.ts +682 -0
- package/src/linking/index.ts +58 -0
- package/src/linking/proof-publication.ts +557 -0
- package/src/midnight/index.ts +73 -0
- package/src/midnight/proof-server-client.ts +595 -0
- package/src/midnight/public-inputs.ts +590 -0
- package/src/midnight/witness-builder.ts +341 -0
- package/src/proofs/hash-chain-proof.ts +610 -0
- package/src/proofs/index.ts +77 -0
- package/src/proofs/policy-compliance-proof.ts +717 -0
- package/src/proofs/selective-disclosure.ts +839 -0
- package/src/prover-interface.ts +410 -0
- package/src/prover.ts +537 -0
- package/src/types.ts +551 -0
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Witness builder for hash-chain ZK proofs.
|
|
3
|
+
*
|
|
4
|
+
* Location: packages/midnight-prover/src/midnight/witness-builder.ts
|
|
5
|
+
*
|
|
6
|
+
* Summary:
|
|
7
|
+
* This module converts trace events into a circuit-compatible witness format
|
|
8
|
+
* for the hash-chain validity proof. The witness contains the private inputs
|
|
9
|
+
* needed by the ZK circuit to prove that a sequence of events produces
|
|
10
|
+
* the expected rolling hash.
|
|
11
|
+
*
|
|
12
|
+
* Usage:
|
|
13
|
+
* Used by HashChainProver to prepare data for proof generation.
|
|
14
|
+
* The witness format matches the expected Compact circuit input structure.
|
|
15
|
+
*
|
|
16
|
+
* Related files:
|
|
17
|
+
* - hash-chain-proof.ts: Uses this to build witnesses for proof generation
|
|
18
|
+
* - public-inputs.ts: Builds corresponding public inputs
|
|
19
|
+
* - @fluxpointstudios/orynq-sdk-process-trace: TraceEvent types
|
|
20
|
+
*/
|
|
21
|
+
import { sha256StringHex, canonicalize, hexToBytes, } from "@fluxpointstudios/orynq-sdk-core/utils";
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// TYPES
|
|
24
|
+
// =============================================================================
|
|
25
|
+
/**
|
|
26
|
+
* Hash domain prefix for event hashing in witness building.
|
|
27
|
+
* Matches the process-trace package domain prefix for consistency.
|
|
28
|
+
*/
|
|
29
|
+
const HASH_DOMAIN_EVENT = "poi-trace:event:v1|";
|
|
30
|
+
/**
|
|
31
|
+
* Hash domain prefix for rolling hash computation.
|
|
32
|
+
* Matches the process-trace package domain prefix for consistency.
|
|
33
|
+
*/
|
|
34
|
+
const HASH_DOMAIN_ROLL = "poi-trace:roll:v1|";
|
|
35
|
+
// =============================================================================
|
|
36
|
+
// MAIN FUNCTION
|
|
37
|
+
// =============================================================================
|
|
38
|
+
/**
|
|
39
|
+
* Build a hash-chain witness from trace events.
|
|
40
|
+
*
|
|
41
|
+
* This function converts an array of TraceEvents into a circuit-compatible
|
|
42
|
+
* witness format. The witness contains:
|
|
43
|
+
* 1. The genesis hash (starting point)
|
|
44
|
+
* 2. Each event serialized as bytes with its hash
|
|
45
|
+
* 3. The computed rolling hash for verification
|
|
46
|
+
*
|
|
47
|
+
* The rolling hash computation matches the algorithm in process-trace:
|
|
48
|
+
* - Events are sorted by seq number
|
|
49
|
+
* - Each event hash is H(domain + canonical(event - hash field))
|
|
50
|
+
* - Rolling hash is H(domain + prevHash + "|" + eventHash)
|
|
51
|
+
*
|
|
52
|
+
* @param events - Array of trace events to build witness from
|
|
53
|
+
* @param genesisHash - Initial hash state (hex string, typically from initRollingHash)
|
|
54
|
+
* @returns Promise resolving to the complete hash chain witness
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* const witness = await buildHashChainWitness(traceBundle.privateRun.events, genesisHash);
|
|
59
|
+
* console.log(witness.eventCount); // Number of events
|
|
60
|
+
* console.log(witness.computedRollingHash); // Final hash
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
export async function buildHashChainWitness(events, genesisHash) {
|
|
64
|
+
// Sort events by sequence number for deterministic ordering
|
|
65
|
+
const sortedEvents = [...events].sort((a, b) => a.seq - b.seq);
|
|
66
|
+
// Build event witnesses
|
|
67
|
+
const eventWitnesses = [];
|
|
68
|
+
for (const event of sortedEvents) {
|
|
69
|
+
const eventWitness = await buildEventWitness(event);
|
|
70
|
+
eventWitnesses.push(eventWitness);
|
|
71
|
+
}
|
|
72
|
+
// Compute rolling hash
|
|
73
|
+
const computedRollingHash = await computeRollingHashFromWitness(genesisHash, eventWitnesses);
|
|
74
|
+
return {
|
|
75
|
+
genesisHash,
|
|
76
|
+
events: eventWitnesses,
|
|
77
|
+
computedRollingHash,
|
|
78
|
+
eventCount: eventWitnesses.length,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// =============================================================================
|
|
82
|
+
// HELPER FUNCTIONS
|
|
83
|
+
// =============================================================================
|
|
84
|
+
/**
|
|
85
|
+
* Build a witness for a single event.
|
|
86
|
+
*
|
|
87
|
+
* @param event - The trace event to convert
|
|
88
|
+
* @returns Promise resolving to the event witness
|
|
89
|
+
*/
|
|
90
|
+
async function buildEventWitness(event) {
|
|
91
|
+
// Remove the hash field to avoid circularity
|
|
92
|
+
const eventWithoutHash = removeHashField(event);
|
|
93
|
+
// Canonicalize for deterministic serialization
|
|
94
|
+
const canonical = canonicalize(eventWithoutHash);
|
|
95
|
+
// Convert to bytes for circuit
|
|
96
|
+
const eventData = new TextEncoder().encode(canonical);
|
|
97
|
+
// Compute hash with domain separation
|
|
98
|
+
const prefixedData = HASH_DOMAIN_EVENT + canonical;
|
|
99
|
+
const eventHash = await sha256StringHex(prefixedData);
|
|
100
|
+
return {
|
|
101
|
+
seq: event.seq,
|
|
102
|
+
eventData,
|
|
103
|
+
eventHash,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Compute rolling hash from event witnesses.
|
|
108
|
+
* Matches the algorithm in process-trace/rolling-hash.ts
|
|
109
|
+
*
|
|
110
|
+
* @param genesisHash - Initial hash state
|
|
111
|
+
* @param eventWitnesses - Array of event witnesses
|
|
112
|
+
* @returns Promise resolving to the final rolling hash
|
|
113
|
+
*/
|
|
114
|
+
async function computeRollingHashFromWitness(genesisHash, eventWitnesses) {
|
|
115
|
+
let currentHash = genesisHash;
|
|
116
|
+
for (const witness of eventWitnesses) {
|
|
117
|
+
// Rolling hash: H(domain + prevHash + "|" + eventHash)
|
|
118
|
+
const input = HASH_DOMAIN_ROLL + currentHash + "|" + witness.eventHash;
|
|
119
|
+
currentHash = await sha256StringHex(input);
|
|
120
|
+
}
|
|
121
|
+
return currentHash;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Remove the 'hash' field from an event object.
|
|
125
|
+
* Returns a shallow copy with all fields except 'hash'.
|
|
126
|
+
*
|
|
127
|
+
* @param event - Event to process
|
|
128
|
+
* @returns Event copy without the hash field
|
|
129
|
+
*/
|
|
130
|
+
function removeHashField(event) {
|
|
131
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
132
|
+
const { hash: _, ...rest } = event;
|
|
133
|
+
return rest;
|
|
134
|
+
}
|
|
135
|
+
// =============================================================================
|
|
136
|
+
// SERIALIZATION UTILITIES
|
|
137
|
+
// =============================================================================
|
|
138
|
+
/**
|
|
139
|
+
* Serialize a hash chain witness to a compact binary format.
|
|
140
|
+
* Used for transmitting witness data to the proof server.
|
|
141
|
+
*
|
|
142
|
+
* Format:
|
|
143
|
+
* - 4 bytes: event count (uint32 big-endian)
|
|
144
|
+
* - 32 bytes: genesis hash
|
|
145
|
+
* - For each event:
|
|
146
|
+
* - 4 bytes: event data length (uint32 big-endian)
|
|
147
|
+
* - N bytes: event data
|
|
148
|
+
* - 32 bytes: event hash
|
|
149
|
+
*
|
|
150
|
+
* @param witness - The witness to serialize
|
|
151
|
+
* @returns Serialized witness as Uint8Array
|
|
152
|
+
*/
|
|
153
|
+
export function serializeWitness(witness) {
|
|
154
|
+
// Calculate total size
|
|
155
|
+
let totalSize = 4 + 32; // count + genesis hash
|
|
156
|
+
for (const event of witness.events) {
|
|
157
|
+
totalSize += 4 + event.eventData.length + 32; // length + data + hash
|
|
158
|
+
}
|
|
159
|
+
const buffer = new Uint8Array(totalSize);
|
|
160
|
+
const view = new DataView(buffer.buffer);
|
|
161
|
+
let offset = 0;
|
|
162
|
+
// Write event count
|
|
163
|
+
view.setUint32(offset, witness.eventCount, false); // big-endian
|
|
164
|
+
offset += 4;
|
|
165
|
+
// Write genesis hash
|
|
166
|
+
const genesisBytes = hexToBytes(witness.genesisHash);
|
|
167
|
+
buffer.set(genesisBytes, offset);
|
|
168
|
+
offset += 32;
|
|
169
|
+
// Write each event
|
|
170
|
+
for (const event of witness.events) {
|
|
171
|
+
// Event data length
|
|
172
|
+
view.setUint32(offset, event.eventData.length, false);
|
|
173
|
+
offset += 4;
|
|
174
|
+
// Event data
|
|
175
|
+
buffer.set(event.eventData, offset);
|
|
176
|
+
offset += event.eventData.length;
|
|
177
|
+
// Event hash
|
|
178
|
+
const hashBytes = hexToBytes(event.eventHash);
|
|
179
|
+
buffer.set(hashBytes, offset);
|
|
180
|
+
offset += 32;
|
|
181
|
+
}
|
|
182
|
+
return buffer;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Compute the total size of a witness for resource estimation.
|
|
186
|
+
*
|
|
187
|
+
* @param witness - The witness to measure
|
|
188
|
+
* @returns Size in bytes
|
|
189
|
+
*/
|
|
190
|
+
export function computeWitnessSize(witness) {
|
|
191
|
+
let size = 4 + 32; // count + genesis hash
|
|
192
|
+
for (const event of witness.events) {
|
|
193
|
+
size += 4 + event.eventData.length + 32;
|
|
194
|
+
}
|
|
195
|
+
return size;
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Validate that a witness is well-formed.
|
|
199
|
+
*
|
|
200
|
+
* @param witness - The witness to validate
|
|
201
|
+
* @returns Array of validation errors (empty if valid)
|
|
202
|
+
*/
|
|
203
|
+
export function validateWitness(witness) {
|
|
204
|
+
const errors = [];
|
|
205
|
+
// Check genesis hash format
|
|
206
|
+
if (!/^[0-9a-f]{64}$/i.test(witness.genesisHash)) {
|
|
207
|
+
errors.push("Invalid genesis hash format (expected 64-char hex string)");
|
|
208
|
+
}
|
|
209
|
+
// Check event count matches
|
|
210
|
+
if (witness.eventCount !== witness.events.length) {
|
|
211
|
+
errors.push(`Event count mismatch: declared ${witness.eventCount}, actual ${witness.events.length}`);
|
|
212
|
+
}
|
|
213
|
+
// Check each event
|
|
214
|
+
for (let i = 0; i < witness.events.length; i++) {
|
|
215
|
+
const event = witness.events[i];
|
|
216
|
+
if (event === undefined) {
|
|
217
|
+
errors.push(`Event at index ${i} is undefined`);
|
|
218
|
+
continue;
|
|
219
|
+
}
|
|
220
|
+
// Check event hash format
|
|
221
|
+
if (!/^[0-9a-f]{64}$/i.test(event.eventHash)) {
|
|
222
|
+
errors.push(`Event ${i}: Invalid hash format`);
|
|
223
|
+
}
|
|
224
|
+
// Check event data is not empty
|
|
225
|
+
if (event.eventData.length === 0) {
|
|
226
|
+
errors.push(`Event ${i}: Empty event data`);
|
|
227
|
+
}
|
|
228
|
+
// Check sequence ordering
|
|
229
|
+
if (i > 0) {
|
|
230
|
+
const prevEvent = witness.events[i - 1];
|
|
231
|
+
if (prevEvent !== undefined && event.seq <= prevEvent.seq) {
|
|
232
|
+
errors.push(`Event ${i}: Sequence ${event.seq} not greater than previous ${prevEvent.seq}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return errors;
|
|
237
|
+
}
|
|
238
|
+
//# sourceMappingURL=witness-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"witness-builder.js","sourceRoot":"","sources":["../../src/midnight/witness-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Hash-chain validity proof generator.
|
|
3
|
+
*
|
|
4
|
+
* Location: packages/midnight-prover/src/proofs/hash-chain-proof.ts
|
|
5
|
+
*
|
|
6
|
+
* Summary:
|
|
7
|
+
* This module implements the HashChainProver class which generates and verifies
|
|
8
|
+
* ZK proofs that a sequence of trace events produces an expected rolling hash.
|
|
9
|
+
* The proof is bound to a Cardano anchor transaction for cross-chain verification.
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* The HashChainProver is the primary prover for PoI trace verification:
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const prover = new HashChainProver();
|
|
15
|
+
* const proof = await prover.generateProof({
|
|
16
|
+
* events: traceBundle.privateRun.events,
|
|
17
|
+
* genesisHash: await getGenesisHash(),
|
|
18
|
+
* expectedRootHash: traceBundle.rootHash,
|
|
19
|
+
* cardanoAnchorTxHash: anchorTxHash,
|
|
20
|
+
* });
|
|
21
|
+
* const isValid = await prover.verifyProof(proof);
|
|
22
|
+
* ```
|
|
23
|
+
*
|
|
24
|
+
* Related files:
|
|
25
|
+
* - witness-builder.ts: Builds witnesses for this prover
|
|
26
|
+
* - public-inputs.ts: Builds public inputs for this prover
|
|
27
|
+
* - prover-interface.ts: Abstract interface this implements
|
|
28
|
+
* - types.ts: Type definitions for inputs and outputs
|
|
29
|
+
*/
|
|
30
|
+
import type { HashChainInput, HashChainProof } from "../types.js";
|
|
31
|
+
/**
|
|
32
|
+
* Options for HashChainProver configuration.
|
|
33
|
+
*/
|
|
34
|
+
export interface HashChainProverOptions {
|
|
35
|
+
/**
|
|
36
|
+
* Enable debug logging.
|
|
37
|
+
*/
|
|
38
|
+
debug?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum events per proof (defaults to MAX_EVENTS_PER_PROOF).
|
|
41
|
+
*/
|
|
42
|
+
maxEvents?: number;
|
|
43
|
+
/**
|
|
44
|
+
* Simulated proving time in milliseconds (for mock mode).
|
|
45
|
+
* Set to 0 for instant proofs (useful in tests).
|
|
46
|
+
*/
|
|
47
|
+
simulatedProvingTimeMs?: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* HashChainProver generates and verifies ZK proofs for trace hash chains.
|
|
51
|
+
*
|
|
52
|
+
* This prover demonstrates that:
|
|
53
|
+
* 1. A sequence of events exists (private witness)
|
|
54
|
+
* 2. Processing them produces a specific rolling hash (public input)
|
|
55
|
+
* 3. This hash matches what was anchored on Cardano (cross-chain binding)
|
|
56
|
+
*
|
|
57
|
+
* Current implementation is a mock that simulates proof generation.
|
|
58
|
+
* Real Midnight integration will be added when the Compact runtime is available.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* const prover = new HashChainProver({ debug: true });
|
|
63
|
+
*
|
|
64
|
+
* const proof = await prover.generateProof({
|
|
65
|
+
* events: bundle.privateRun.events,
|
|
66
|
+
* genesisHash: "abc123...",
|
|
67
|
+
* expectedRootHash: bundle.rootHash,
|
|
68
|
+
* cardanoAnchorTxHash: "def456...",
|
|
69
|
+
* });
|
|
70
|
+
*
|
|
71
|
+
* console.log("Proof generated:", proof.proofId);
|
|
72
|
+
* console.log("Proving time:", proof.provingTimeMs, "ms");
|
|
73
|
+
*
|
|
74
|
+
* const isValid = await prover.verifyProof(proof);
|
|
75
|
+
* console.log("Proof valid:", isValid);
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
export declare class HashChainProver {
|
|
79
|
+
private readonly options;
|
|
80
|
+
/**
|
|
81
|
+
* Create a new HashChainProver.
|
|
82
|
+
*
|
|
83
|
+
* @param options - Configuration options
|
|
84
|
+
*/
|
|
85
|
+
constructor(options?: HashChainProverOptions);
|
|
86
|
+
/**
|
|
87
|
+
* Generate a hash-chain validity proof.
|
|
88
|
+
*
|
|
89
|
+
* This method:
|
|
90
|
+
* 1. Validates the input
|
|
91
|
+
* 2. Builds a witness from the events
|
|
92
|
+
* 3. Verifies the computed hash matches expected
|
|
93
|
+
* 4. Generates a mock ZK proof
|
|
94
|
+
* 5. Returns the proof with metrics
|
|
95
|
+
*
|
|
96
|
+
* @param input - Hash chain input with events and expected hash
|
|
97
|
+
* @returns Promise resolving to the generated proof
|
|
98
|
+
* @throws MidnightProverException on validation or generation failure
|
|
99
|
+
*/
|
|
100
|
+
generateProof(input: HashChainInput): Promise<HashChainProof>;
|
|
101
|
+
/**
|
|
102
|
+
* Verify a hash-chain proof.
|
|
103
|
+
*
|
|
104
|
+
* This method checks:
|
|
105
|
+
* 1. Proof format is valid
|
|
106
|
+
* 2. Public inputs are consistent
|
|
107
|
+
* 3. Mock proof data is correctly structured
|
|
108
|
+
*
|
|
109
|
+
* Note: In production, this would verify the actual ZK proof.
|
|
110
|
+
* Current mock implementation verifies structural integrity.
|
|
111
|
+
*
|
|
112
|
+
* @param proof - The proof to verify
|
|
113
|
+
* @returns Promise resolving to true if valid, false otherwise
|
|
114
|
+
*/
|
|
115
|
+
verifyProof(proof: HashChainProof): Promise<boolean>;
|
|
116
|
+
/**
|
|
117
|
+
* Compute the genesis hash for the rolling hash chain.
|
|
118
|
+
* This matches the algorithm in process-trace/rolling-hash.ts
|
|
119
|
+
*
|
|
120
|
+
* @returns Promise resolving to the genesis hash
|
|
121
|
+
*/
|
|
122
|
+
getGenesisHash(): Promise<string>;
|
|
123
|
+
/**
|
|
124
|
+
* Validate the input for proof generation.
|
|
125
|
+
*/
|
|
126
|
+
private validateInput;
|
|
127
|
+
/**
|
|
128
|
+
* Build the witness from input.
|
|
129
|
+
*/
|
|
130
|
+
private buildWitness;
|
|
131
|
+
/**
|
|
132
|
+
* Verify that the computed rolling hash matches the expected root hash.
|
|
133
|
+
*/
|
|
134
|
+
private verifyHashMatch;
|
|
135
|
+
/**
|
|
136
|
+
* Build public inputs for the proof.
|
|
137
|
+
*/
|
|
138
|
+
private buildPublicInputs;
|
|
139
|
+
/**
|
|
140
|
+
* Generate a mock ZK proof.
|
|
141
|
+
*
|
|
142
|
+
* This creates a simulated proof structure that includes:
|
|
143
|
+
* - A magic header identifying it as a mock proof
|
|
144
|
+
* - Hash of the witness (for integrity)
|
|
145
|
+
* - Serialized public inputs
|
|
146
|
+
* - Random "proof" bytes (placeholder for real proof data)
|
|
147
|
+
*
|
|
148
|
+
* In production, this would call the Midnight proof server.
|
|
149
|
+
*/
|
|
150
|
+
private generateMockProof;
|
|
151
|
+
/**
|
|
152
|
+
* Verify the structure of a mock proof.
|
|
153
|
+
*/
|
|
154
|
+
private verifyMockProofStructure;
|
|
155
|
+
/**
|
|
156
|
+
* Debug logging helper.
|
|
157
|
+
*/
|
|
158
|
+
private debug;
|
|
159
|
+
/**
|
|
160
|
+
* Delay helper for simulated proving time.
|
|
161
|
+
*/
|
|
162
|
+
private delay;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Create a new HashChainProver instance.
|
|
166
|
+
*
|
|
167
|
+
* @param options - Configuration options
|
|
168
|
+
* @returns A new HashChainProver instance
|
|
169
|
+
*/
|
|
170
|
+
export declare function createHashChainProver(options?: HashChainProverOptions): HashChainProver;
|
|
171
|
+
//# sourceMappingURL=hash-chain-proof.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash-chain-proof.d.ts","sourceRoot":"","sources":["../../src/proofs/hash-chain-proof.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAIH,OAAO,KAAK,EACV,cAAc,EACd,cAAc,EAEf,MAAM,aAAa,CAAC;AAmDrB;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,CAAC;IAEhB;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,qBAAa,eAAe;IAC1B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAmC;IAE3D;;;;OAIG;gBACS,OAAO,GAAE,sBAA2B;IAQhD;;;;;;;;;;;;;OAaG;IACG,aAAa,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,cAAc,CAAC;IA8CnE;;;;;;;;;;;;;OAaG;IACG,WAAW,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IAgD1D;;;;;OAKG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IASvC;;OAEG;IACH,OAAO,CAAC,aAAa;IAuErB;;OAEG;YACW,YAAY;IA+B1B;;OAEG;YACW,eAAe;IAiB7B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAWzB;;;;;;;;;;OAUG;YACW,iBAAiB;IA4D/B;;OAEG;YACW,wBAAwB;IAgDtC;;OAEG;IACH,OAAO,CAAC,KAAK;IAMb;;OAEG;IACH,OAAO,CAAC,KAAK;CAGd;AA8BD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,CAAC,EAAE,sBAAsB,GAC/B,eAAe,CAEjB"}
|