midnight-mcp 0.1.34 → 0.1.35
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.
|
@@ -65,4 +65,107 @@ export declare function getVersionInfo(): string;
|
|
|
65
65
|
* Check if a version is within supported range
|
|
66
66
|
*/
|
|
67
67
|
export declare function isVersionSupported(version: string): boolean;
|
|
68
|
+
/**
|
|
69
|
+
* Built-in functions vs patterns you must implement yourself
|
|
70
|
+
* CRITICAL: These are the actual stdlib functions available in Compact
|
|
71
|
+
*/
|
|
72
|
+
export declare const BUILTIN_FUNCTIONS: {
|
|
73
|
+
/** Actually built into the language/stdlib */
|
|
74
|
+
stdlib: {
|
|
75
|
+
name: string;
|
|
76
|
+
signature: string;
|
|
77
|
+
description: string;
|
|
78
|
+
}[];
|
|
79
|
+
/** NOT built-in - you must implement these patterns yourself */
|
|
80
|
+
notBuiltIn: {
|
|
81
|
+
name: string;
|
|
82
|
+
wrongUsage: string;
|
|
83
|
+
correctPattern: string;
|
|
84
|
+
description: string;
|
|
85
|
+
}[];
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Type compatibility rules - what types can be compared/operated together
|
|
89
|
+
*/
|
|
90
|
+
export declare const TYPE_COMPATIBILITY: {
|
|
91
|
+
comparisons: ({
|
|
92
|
+
types: string;
|
|
93
|
+
works: boolean;
|
|
94
|
+
note: string;
|
|
95
|
+
fix?: undefined;
|
|
96
|
+
} | {
|
|
97
|
+
types: string;
|
|
98
|
+
works: boolean;
|
|
99
|
+
fix: string;
|
|
100
|
+
note?: undefined;
|
|
101
|
+
})[];
|
|
102
|
+
arithmetic: ({
|
|
103
|
+
types: string;
|
|
104
|
+
works: boolean;
|
|
105
|
+
note: string;
|
|
106
|
+
fix?: undefined;
|
|
107
|
+
} | {
|
|
108
|
+
types: string;
|
|
109
|
+
works: boolean;
|
|
110
|
+
fix: string;
|
|
111
|
+
note?: undefined;
|
|
112
|
+
})[];
|
|
113
|
+
assignments: {
|
|
114
|
+
types: string;
|
|
115
|
+
works: boolean;
|
|
116
|
+
fix: string;
|
|
117
|
+
}[];
|
|
118
|
+
tips: string[];
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Ledger type limitations - what works in circuits vs TypeScript
|
|
122
|
+
*/
|
|
123
|
+
export declare const LEDGER_TYPE_LIMITS: {
|
|
124
|
+
Counter: {
|
|
125
|
+
circuitOperations: {
|
|
126
|
+
method: string;
|
|
127
|
+
works: boolean;
|
|
128
|
+
note: string;
|
|
129
|
+
}[];
|
|
130
|
+
typescriptAccess: string;
|
|
131
|
+
reason: string;
|
|
132
|
+
};
|
|
133
|
+
Map: {
|
|
134
|
+
circuitOperations: {
|
|
135
|
+
method: string;
|
|
136
|
+
works: boolean;
|
|
137
|
+
note: string;
|
|
138
|
+
}[];
|
|
139
|
+
typescriptAccess: string;
|
|
140
|
+
reason: string;
|
|
141
|
+
pattern: string;
|
|
142
|
+
};
|
|
143
|
+
Set: {
|
|
144
|
+
circuitOperations: {
|
|
145
|
+
method: string;
|
|
146
|
+
works: boolean;
|
|
147
|
+
note: string;
|
|
148
|
+
}[];
|
|
149
|
+
typescriptAccess: string;
|
|
150
|
+
reason: string;
|
|
151
|
+
};
|
|
152
|
+
MerkleTree: {
|
|
153
|
+
circuitOperations: {
|
|
154
|
+
method: string;
|
|
155
|
+
works: boolean;
|
|
156
|
+
note: string;
|
|
157
|
+
}[];
|
|
158
|
+
typescriptAccess: string;
|
|
159
|
+
pattern: string;
|
|
160
|
+
};
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Common compilation errors with their fixes
|
|
164
|
+
* Maps actual compiler error messages to solutions
|
|
165
|
+
*/
|
|
166
|
+
export declare const COMMON_ERRORS: {
|
|
167
|
+
error: string;
|
|
168
|
+
cause: string;
|
|
169
|
+
fix: string;
|
|
170
|
+
}[];
|
|
68
171
|
//# sourceMappingURL=compact-version.d.ts.map
|
|
@@ -92,4 +92,264 @@ export function isVersionSupported(version) {
|
|
|
92
92
|
const maxNum = maxMajor * 100 + maxMinor;
|
|
93
93
|
return versionNum >= minNum && versionNum <= maxNum;
|
|
94
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Built-in functions vs patterns you must implement yourself
|
|
97
|
+
* CRITICAL: These are the actual stdlib functions available in Compact
|
|
98
|
+
*/
|
|
99
|
+
export const BUILTIN_FUNCTIONS = {
|
|
100
|
+
/** Actually built into the language/stdlib */
|
|
101
|
+
stdlib: [
|
|
102
|
+
{
|
|
103
|
+
name: "persistentHash",
|
|
104
|
+
signature: "persistentHash<T>(value: T): Bytes<32>",
|
|
105
|
+
description: "Poseidon hash that produces consistent results across calls",
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
name: "persistentCommit",
|
|
109
|
+
signature: "persistentCommit<T>(value: T): Bytes<32>",
|
|
110
|
+
description: "Creates a hiding commitment to a value",
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
name: "pad",
|
|
114
|
+
signature: "pad(length: number, value: string): Bytes<N>",
|
|
115
|
+
description: "Pads a string to fixed-length bytes",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
name: "disclose",
|
|
119
|
+
signature: "disclose(value: T): T",
|
|
120
|
+
description: "Explicitly reveals a witness value (required in conditionals)",
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
name: "assert",
|
|
124
|
+
signature: "assert(condition: Boolean, message?: string): []",
|
|
125
|
+
description: "Fails circuit if condition is false",
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
name: "default",
|
|
129
|
+
signature: "default<T>(): T",
|
|
130
|
+
description: "Returns default value for a type (0 for numbers, empty for collections)",
|
|
131
|
+
},
|
|
132
|
+
],
|
|
133
|
+
/** NOT built-in - you must implement these patterns yourself */
|
|
134
|
+
notBuiltIn: [
|
|
135
|
+
{
|
|
136
|
+
name: "public_key",
|
|
137
|
+
wrongUsage: "public_key(sk) // ERROR: unbound identifier",
|
|
138
|
+
correctPattern: `// Derive public key using persistentHash
|
|
139
|
+
const pk = persistentHash<Vector<2, Bytes<32>>>([
|
|
140
|
+
pad(32, "midnight:pk:"),
|
|
141
|
+
sk
|
|
142
|
+
]);`,
|
|
143
|
+
description: "Public key derivation is NOT a builtin - use persistentHash pattern",
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
name: "verify_signature",
|
|
147
|
+
wrongUsage: "verify_signature(msg, sig, pk) // Does not exist",
|
|
148
|
+
correctPattern: `// Signature verification must be done via witnesses
|
|
149
|
+
// The prover verifies off-chain, then provides the boolean result
|
|
150
|
+
witness signature_valid(): Boolean;`,
|
|
151
|
+
description: "Signature verification is done off-chain in the prover",
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "random",
|
|
155
|
+
wrongUsage: "random() // Does not exist in ZK circuits",
|
|
156
|
+
correctPattern: `// Randomness must come from witnesses (prover-provided)
|
|
157
|
+
witness get_random_value(): Field;`,
|
|
158
|
+
description: "ZK circuits are deterministic - randomness must come from witnesses",
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
};
|
|
162
|
+
/**
|
|
163
|
+
* Type compatibility rules - what types can be compared/operated together
|
|
164
|
+
*/
|
|
165
|
+
export const TYPE_COMPATIBILITY = {
|
|
166
|
+
comparisons: [
|
|
167
|
+
{ types: "Field == Field", works: true, note: "Direct comparison" },
|
|
168
|
+
{
|
|
169
|
+
types: "Field == Uint<N>",
|
|
170
|
+
works: false,
|
|
171
|
+
fix: "Cast with `value as Field`",
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
types: "Field >= 0",
|
|
175
|
+
works: false,
|
|
176
|
+
fix: "Use bounded Uint<0..N> parameter instead",
|
|
177
|
+
},
|
|
178
|
+
{ types: "Uint<N> == Uint<N>", works: true, note: "Same-width comparison" },
|
|
179
|
+
{
|
|
180
|
+
types: "Uint<0..2> == Uint<0..2>",
|
|
181
|
+
works: true,
|
|
182
|
+
note: "Bounded integers",
|
|
183
|
+
},
|
|
184
|
+
{ types: "Bytes<32> == Bytes<32>", works: true, note: "Direct comparison" },
|
|
185
|
+
{ types: "Boolean == Boolean", works: true, note: "Direct comparison" },
|
|
186
|
+
],
|
|
187
|
+
arithmetic: [
|
|
188
|
+
{ types: "Field + Field", works: true, note: "Field arithmetic" },
|
|
189
|
+
{ types: "Field + Uint<N>", works: false, fix: "Cast Uint to Field first" },
|
|
190
|
+
{
|
|
191
|
+
types: "Uint<N> + Uint<N>",
|
|
192
|
+
works: true,
|
|
193
|
+
note: "Must fit in result width",
|
|
194
|
+
},
|
|
195
|
+
],
|
|
196
|
+
assignments: [
|
|
197
|
+
{
|
|
198
|
+
types: "Field = Uint<N>",
|
|
199
|
+
works: false,
|
|
200
|
+
fix: "Cast with `value as Field`",
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
types: "Uint<N> = Field",
|
|
204
|
+
works: false,
|
|
205
|
+
fix: "Use bounded param or explicit cast",
|
|
206
|
+
},
|
|
207
|
+
],
|
|
208
|
+
tips: [
|
|
209
|
+
"Use Uint<0..N> for circuit parameters that need range validation",
|
|
210
|
+
"Field is unbounded - use for hashes, commitments, general computation",
|
|
211
|
+
"Uint<N> is bounded - use when you need range checks",
|
|
212
|
+
"Casting with `as Field` is safe but loses range information",
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
/**
|
|
216
|
+
* Ledger type limitations - what works in circuits vs TypeScript
|
|
217
|
+
*/
|
|
218
|
+
export const LEDGER_TYPE_LIMITS = {
|
|
219
|
+
Counter: {
|
|
220
|
+
circuitOperations: [
|
|
221
|
+
{ method: ".increment(n)", works: true, note: "Adds n to counter" },
|
|
222
|
+
{
|
|
223
|
+
method: ".decrement(n)",
|
|
224
|
+
works: true,
|
|
225
|
+
note: "Subtracts n from counter",
|
|
226
|
+
},
|
|
227
|
+
{ method: ".resetToDefault()", works: true, note: "Resets to 0" },
|
|
228
|
+
{ method: ".value()", works: false, note: "NOT available in circuits" },
|
|
229
|
+
],
|
|
230
|
+
typescriptAccess: "Access counter value via `ledgerState.counter` in TypeScript SDK",
|
|
231
|
+
reason: "ZK circuits cannot read current ledger state - only modify it",
|
|
232
|
+
},
|
|
233
|
+
Map: {
|
|
234
|
+
circuitOperations: [
|
|
235
|
+
{
|
|
236
|
+
method: ".insert(key, value)",
|
|
237
|
+
works: true,
|
|
238
|
+
note: "Adds/updates entry",
|
|
239
|
+
},
|
|
240
|
+
{ method: ".remove(key)", works: true, note: "Removes entry" },
|
|
241
|
+
{
|
|
242
|
+
method: ".lookup(key)",
|
|
243
|
+
works: false,
|
|
244
|
+
note: "NOT available in circuits",
|
|
245
|
+
},
|
|
246
|
+
{
|
|
247
|
+
method: ".member(key)",
|
|
248
|
+
works: false,
|
|
249
|
+
note: "NOT available in circuits",
|
|
250
|
+
},
|
|
251
|
+
],
|
|
252
|
+
typescriptAccess: "Query map via `contractState.data.get(key)` in TypeScript SDK",
|
|
253
|
+
reason: "ZK circuits prove transitions, not current state. Use witnesses for reads.",
|
|
254
|
+
pattern: `// To read a map value in a circuit, use a witness:
|
|
255
|
+
witness get_stored_value(key: Bytes<32>): Field;
|
|
256
|
+
|
|
257
|
+
export circuit update_if_exists(key: Bytes<32>, new_value: Field): [] {
|
|
258
|
+
const current = get_stored_value(key); // Prover fetches from ledger
|
|
259
|
+
// ... use current value
|
|
260
|
+
data.insert(key, new_value); // Update is allowed
|
|
261
|
+
}`,
|
|
262
|
+
},
|
|
263
|
+
Set: {
|
|
264
|
+
circuitOperations: [
|
|
265
|
+
{ method: ".insert(value)", works: true, note: "Adds to set" },
|
|
266
|
+
{ method: ".remove(value)", works: true, note: "Removes from set" },
|
|
267
|
+
{
|
|
268
|
+
method: ".member(value)",
|
|
269
|
+
works: false,
|
|
270
|
+
note: "NOT available in circuits",
|
|
271
|
+
},
|
|
272
|
+
],
|
|
273
|
+
typescriptAccess: "Check membership via `contractState.set.has(value)` in TypeScript SDK",
|
|
274
|
+
reason: "Same as Map - use witnesses for membership checks",
|
|
275
|
+
},
|
|
276
|
+
MerkleTree: {
|
|
277
|
+
circuitOperations: [
|
|
278
|
+
{ method: ".insert(leaf)", works: true, note: "Adds leaf to tree" },
|
|
279
|
+
{ method: ".root()", works: false, note: "NOT available in circuits" },
|
|
280
|
+
],
|
|
281
|
+
typescriptAccess: "Get root via `contractState.tree.root` in TypeScript SDK",
|
|
282
|
+
pattern: `// To verify a merkle proof in circuit:
|
|
283
|
+
witness get_merkle_root(): Bytes<32>;
|
|
284
|
+
witness get_merkle_proof(leaf: Bytes<32>): Vector<32, Bytes<32>>;
|
|
285
|
+
|
|
286
|
+
// Verify proof using persistentHash to compute expected root`,
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
/**
|
|
290
|
+
* Common compilation errors with their fixes
|
|
291
|
+
* Maps actual compiler error messages to solutions
|
|
292
|
+
*/
|
|
293
|
+
export const COMMON_ERRORS = [
|
|
294
|
+
{
|
|
295
|
+
error: 'unbound identifier "public_key"',
|
|
296
|
+
cause: "Trying to use public_key() as if it's a builtin function",
|
|
297
|
+
fix: `Use persistentHash pattern instead:
|
|
298
|
+
const pk = persistentHash<Vector<2, Bytes<32>>>([pad(32, "midnight:pk:"), sk]);`,
|
|
299
|
+
},
|
|
300
|
+
{
|
|
301
|
+
error: "incompatible combination of types Field and Uint",
|
|
302
|
+
cause: "Comparing or operating on Field with Uint without casting",
|
|
303
|
+
fix: `Cast Uint to Field: (myUint as Field)
|
|
304
|
+
Or use bounded Uint<0..N> for parameters that need constraints`,
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
error: 'operation "value" undefined for ledger field type Counter',
|
|
308
|
+
cause: "Trying to read Counter.value() inside a circuit",
|
|
309
|
+
fix: `Counter values cannot be read in circuits. Options:
|
|
310
|
+
1. Use a witness: witness get_counter_value(): Uint<64>;
|
|
311
|
+
2. Read from TypeScript SDK: ledgerState.counter
|
|
312
|
+
3. Track the value in a separate Field ledger variable`,
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
error: "implicit disclosure of witness value",
|
|
316
|
+
cause: "Using witness value in conditional without disclose()",
|
|
317
|
+
fix: `Wrap witness comparisons in disclose():
|
|
318
|
+
if (disclose(witness_value == expected)) { ... }`,
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
error: 'parse error: found "{" looking for an identifier',
|
|
322
|
+
cause: "Using old ledger { } block syntax",
|
|
323
|
+
fix: `Use individual exports instead:
|
|
324
|
+
export ledger field1: Type1;
|
|
325
|
+
export ledger field2: Type2;`,
|
|
326
|
+
},
|
|
327
|
+
{
|
|
328
|
+
error: 'parse error: found "{" looking for ";"',
|
|
329
|
+
cause: "Using Void as return type (doesn't exist)",
|
|
330
|
+
fix: `Use empty tuple [] for no return value:
|
|
331
|
+
export circuit myCircuit(): [] { ... }`,
|
|
332
|
+
},
|
|
333
|
+
{
|
|
334
|
+
error: 'unbound identifier "Cell"',
|
|
335
|
+
cause: "Using deprecated Cell<T> wrapper (removed in 0.15)",
|
|
336
|
+
fix: `Remove Cell wrapper, just use the type directly:
|
|
337
|
+
export ledger myField: Field; // Not Cell<Field>`,
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
error: "member access requires struct type",
|
|
341
|
+
cause: "Trying to use .member() or .lookup() on Map/Set in circuit",
|
|
342
|
+
fix: `Map/Set queries are not available in circuits.
|
|
343
|
+
Use a witness to fetch the value from the prover:
|
|
344
|
+
witness lookup_value(key: Bytes<32>): Field;`,
|
|
345
|
+
},
|
|
346
|
+
{
|
|
347
|
+
error: "cannot prove assertion",
|
|
348
|
+
cause: "Assert condition cannot be proven true",
|
|
349
|
+
fix: `Check your logic. Common causes:
|
|
350
|
+
1. Witness returns unexpected value
|
|
351
|
+
2. Range check fails (use bounded Uint)
|
|
352
|
+
3. Logic error in circuit`,
|
|
353
|
+
},
|
|
354
|
+
];
|
|
95
355
|
//# sourceMappingURL=compact-version.js.map
|
|
@@ -225,6 +225,7 @@ constructor(initNonce: Bytes<32>) {
|
|
|
225
225
|
\`\`\`compact
|
|
226
226
|
witness local_secret_key(): Bytes<32>;
|
|
227
227
|
|
|
228
|
+
// IMPORTANT: public_key() is NOT a builtin - use this pattern
|
|
228
229
|
circuit get_public_key(sk: Bytes<32>): Bytes<32> {
|
|
229
230
|
return persistentHash<Vector<2, Bytes<32>>>([pad(32, "myapp:pk:"), sk]);
|
|
230
231
|
}
|
|
@@ -237,32 +238,47 @@ export circuit authenticated_action(): [] {
|
|
|
237
238
|
}
|
|
238
239
|
\`\`\`
|
|
239
240
|
|
|
240
|
-
### Commit-Reveal Pattern
|
|
241
|
+
### Commit-Reveal Pattern (COMPLETE, VALIDATED)
|
|
241
242
|
\`\`\`compact
|
|
243
|
+
pragma language_version >= 0.16 && <= 0.18;
|
|
244
|
+
|
|
245
|
+
import CompactStandardLibrary;
|
|
246
|
+
|
|
247
|
+
// Ledger state
|
|
242
248
|
export ledger commitment: Bytes<32>;
|
|
243
|
-
export ledger
|
|
249
|
+
export ledger revealed_value: Field;
|
|
250
|
+
export ledger is_revealed: Boolean;
|
|
244
251
|
|
|
245
|
-
|
|
246
|
-
witness
|
|
252
|
+
// Witnesses for off-chain storage
|
|
253
|
+
witness local_secret_key(): Bytes<32>;
|
|
254
|
+
witness store_secret_value(v: Field): [];
|
|
255
|
+
witness get_secret_value(): Field;
|
|
256
|
+
|
|
257
|
+
// Helper: compute commitment hash
|
|
258
|
+
circuit compute_commitment(value: Field, salt: Bytes<32>): Bytes<32> {
|
|
259
|
+
// Convert Field to Bytes for hashing
|
|
260
|
+
const value_bytes = value as Bytes<32>;
|
|
261
|
+
return persistentHash<Vector<2, Bytes<32>>>([value_bytes, salt]);
|
|
262
|
+
}
|
|
247
263
|
|
|
264
|
+
// Commit phase: store hash on-chain, value off-chain
|
|
248
265
|
export circuit commit(value: Field): [] {
|
|
249
|
-
const
|
|
250
|
-
|
|
251
|
-
commitment = disclose(
|
|
252
|
-
|
|
253
|
-
sk
|
|
254
|
-
]));
|
|
266
|
+
const salt = local_secret_key();
|
|
267
|
+
store_secret_value(value);
|
|
268
|
+
commitment = disclose(compute_commitment(value, salt));
|
|
269
|
+
is_revealed = false;
|
|
255
270
|
}
|
|
256
271
|
|
|
272
|
+
// Reveal phase: verify stored value matches commitment
|
|
257
273
|
export circuit reveal(): Field {
|
|
258
|
-
const
|
|
259
|
-
const value =
|
|
260
|
-
const expected =
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
274
|
+
const salt = local_secret_key();
|
|
275
|
+
const value = get_secret_value();
|
|
276
|
+
const expected = compute_commitment(value, salt);
|
|
277
|
+
assert(disclose(expected == commitment), "Value doesn't match commitment");
|
|
278
|
+
assert(disclose(!is_revealed), "Already revealed");
|
|
279
|
+
|
|
280
|
+
revealed_value = disclose(value);
|
|
281
|
+
is_revealed = true;
|
|
266
282
|
return disclose(value);
|
|
267
283
|
}
|
|
268
284
|
\`\`\`
|
|
@@ -296,22 +312,39 @@ export circuit check_broken(guess: Field): Boolean {
|
|
|
296
312
|
|
|
297
313
|
### Counter Operations
|
|
298
314
|
\`\`\`compact
|
|
315
|
+
// These work in circuits:
|
|
299
316
|
counter.increment(1);
|
|
300
317
|
counter.decrement(1);
|
|
301
|
-
|
|
318
|
+
counter.resetToDefault();
|
|
319
|
+
|
|
320
|
+
// ⚠️ DOES NOT WORK IN CIRCUITS:
|
|
321
|
+
// const val = counter.value(); // ERROR: operation undefined
|
|
322
|
+
// Instead, read counter value in TypeScript SDK: ledgerState.counter
|
|
302
323
|
\`\`\`
|
|
303
324
|
|
|
304
325
|
### Map Operations
|
|
305
326
|
\`\`\`compact
|
|
327
|
+
// These work in circuits:
|
|
306
328
|
balances.insert(address, 100);
|
|
307
|
-
|
|
308
|
-
|
|
329
|
+
balances.remove(address);
|
|
330
|
+
|
|
331
|
+
// ⚠️ DOES NOT WORK IN CIRCUITS:
|
|
332
|
+
// const balance = balances.lookup(address); // ERROR
|
|
333
|
+
// const exists = balances.member(address); // ERROR
|
|
334
|
+
// Instead, use witnesses to read values:
|
|
335
|
+
witness get_balance(addr: Bytes<32>): Uint<64>;
|
|
309
336
|
\`\`\`
|
|
310
337
|
|
|
311
338
|
### Set Operations
|
|
312
339
|
\`\`\`compact
|
|
340
|
+
// These work in circuits:
|
|
313
341
|
members.insert(address);
|
|
314
|
-
|
|
342
|
+
members.remove(address);
|
|
343
|
+
|
|
344
|
+
// ⚠️ DOES NOT WORK IN CIRCUITS:
|
|
345
|
+
// const isMember = members.member(address); // ERROR
|
|
346
|
+
// Use witness instead:
|
|
347
|
+
witness is_member(addr: Bytes<32>): Boolean;
|
|
315
348
|
\`\`\`
|
|
316
349
|
|
|
317
350
|
### Maybe Operations
|
|
@@ -326,9 +359,9 @@ if (opt.is_some) {
|
|
|
326
359
|
|
|
327
360
|
### Type Casting
|
|
328
361
|
\`\`\`compact
|
|
329
|
-
const
|
|
330
|
-
const
|
|
331
|
-
const
|
|
362
|
+
const bytes: Bytes<32> = myField as Bytes<32>; // Field to Bytes
|
|
363
|
+
const num: Uint<64> = myField as Uint<64>; // Field to Uint (bounds not checked!)
|
|
364
|
+
const field: Field = myUint as Field; // Uint to Field (safe)
|
|
332
365
|
\`\`\`
|
|
333
366
|
|
|
334
367
|
### Hashing
|
|
@@ -336,8 +369,8 @@ const num: Uint<64> = f as Uint<64>; // Field to Uint
|
|
|
336
369
|
// Persistent hash (same input = same output across calls)
|
|
337
370
|
const hash = persistentHash<Vector<2, Bytes<32>>>([data1, data2]);
|
|
338
371
|
|
|
339
|
-
//
|
|
340
|
-
const commit =
|
|
372
|
+
// Persistent commit (hiding commitment)
|
|
373
|
+
const commit = persistentCommit<Field>(value);
|
|
341
374
|
\`\`\`
|
|
342
375
|
|
|
343
376
|
---
|
|
@@ -159,6 +159,93 @@ export declare function compareSyntax(input: CompareSyntaxInput): Promise<{
|
|
|
159
159
|
*/
|
|
160
160
|
export declare function getLatestSyntax(input: GetLatestSyntaxInput): Promise<{
|
|
161
161
|
quickStartTemplate: string;
|
|
162
|
+
builtinFunctions: {
|
|
163
|
+
stdlib: {
|
|
164
|
+
name: string;
|
|
165
|
+
signature: string;
|
|
166
|
+
description: string;
|
|
167
|
+
}[];
|
|
168
|
+
notBuiltIn: {
|
|
169
|
+
name: string;
|
|
170
|
+
wrongUsage: string;
|
|
171
|
+
correctPattern: string;
|
|
172
|
+
description: string;
|
|
173
|
+
}[];
|
|
174
|
+
};
|
|
175
|
+
typeCompatibility: {
|
|
176
|
+
comparisons: ({
|
|
177
|
+
types: string;
|
|
178
|
+
works: boolean;
|
|
179
|
+
note: string;
|
|
180
|
+
fix?: undefined;
|
|
181
|
+
} | {
|
|
182
|
+
types: string;
|
|
183
|
+
works: boolean;
|
|
184
|
+
fix: string;
|
|
185
|
+
note?: undefined;
|
|
186
|
+
})[];
|
|
187
|
+
arithmetic: ({
|
|
188
|
+
types: string;
|
|
189
|
+
works: boolean;
|
|
190
|
+
note: string;
|
|
191
|
+
fix?: undefined;
|
|
192
|
+
} | {
|
|
193
|
+
types: string;
|
|
194
|
+
works: boolean;
|
|
195
|
+
fix: string;
|
|
196
|
+
note?: undefined;
|
|
197
|
+
})[];
|
|
198
|
+
assignments: {
|
|
199
|
+
types: string;
|
|
200
|
+
works: boolean;
|
|
201
|
+
fix: string;
|
|
202
|
+
}[];
|
|
203
|
+
tips: string[];
|
|
204
|
+
};
|
|
205
|
+
ledgerTypeLimits: {
|
|
206
|
+
Counter: {
|
|
207
|
+
circuitOperations: {
|
|
208
|
+
method: string;
|
|
209
|
+
works: boolean;
|
|
210
|
+
note: string;
|
|
211
|
+
}[];
|
|
212
|
+
typescriptAccess: string;
|
|
213
|
+
reason: string;
|
|
214
|
+
};
|
|
215
|
+
Map: {
|
|
216
|
+
circuitOperations: {
|
|
217
|
+
method: string;
|
|
218
|
+
works: boolean;
|
|
219
|
+
note: string;
|
|
220
|
+
}[];
|
|
221
|
+
typescriptAccess: string;
|
|
222
|
+
reason: string;
|
|
223
|
+
pattern: string;
|
|
224
|
+
};
|
|
225
|
+
Set: {
|
|
226
|
+
circuitOperations: {
|
|
227
|
+
method: string;
|
|
228
|
+
works: boolean;
|
|
229
|
+
note: string;
|
|
230
|
+
}[];
|
|
231
|
+
typescriptAccess: string;
|
|
232
|
+
reason: string;
|
|
233
|
+
};
|
|
234
|
+
MerkleTree: {
|
|
235
|
+
circuitOperations: {
|
|
236
|
+
method: string;
|
|
237
|
+
works: boolean;
|
|
238
|
+
note: string;
|
|
239
|
+
}[];
|
|
240
|
+
typescriptAccess: string;
|
|
241
|
+
pattern: string;
|
|
242
|
+
};
|
|
243
|
+
};
|
|
244
|
+
commonErrors: {
|
|
245
|
+
error: string;
|
|
246
|
+
cause: string;
|
|
247
|
+
fix: string;
|
|
248
|
+
}[];
|
|
162
249
|
commonMistakes: {
|
|
163
250
|
wrong: string;
|
|
164
251
|
correct: string;
|
|
@@ -8,7 +8,7 @@ import { logger, DEFAULT_REPOSITORIES, SelfCorrectionHints, } from "../../utils/
|
|
|
8
8
|
import { sendProgressNotification } from "../../server.js";
|
|
9
9
|
import { REPO_ALIASES, EXAMPLES } from "./constants.js";
|
|
10
10
|
import { EMBEDDED_DOCS } from "../../resources/content/docs-content.js";
|
|
11
|
-
import { COMPACT_VERSION, RECOMMENDED_PRAGMA, REFERENCE_CONTRACTS, } from "../../config/compact-version.js";
|
|
11
|
+
import { COMPACT_VERSION, RECOMMENDED_PRAGMA, REFERENCE_CONTRACTS, BUILTIN_FUNCTIONS, TYPE_COMPATIBILITY, LEDGER_TYPE_LIMITS, COMMON_ERRORS, } from "../../config/compact-version.js";
|
|
12
12
|
// Re-export validation handlers from validation.ts
|
|
13
13
|
export { extractContractStructure } from "./validation.js";
|
|
14
14
|
/**
|
|
@@ -356,6 +356,14 @@ witness local_secret_key(): Bytes<32>;
|
|
|
356
356
|
export circuit increment(): [] {
|
|
357
357
|
counter.increment(1);
|
|
358
358
|
}`,
|
|
359
|
+
// Built-in functions vs patterns (CRITICAL knowledge)
|
|
360
|
+
builtinFunctions: BUILTIN_FUNCTIONS,
|
|
361
|
+
// Type compatibility rules
|
|
362
|
+
typeCompatibility: TYPE_COMPATIBILITY,
|
|
363
|
+
// Ledger type limitations in circuits
|
|
364
|
+
ledgerTypeLimits: LEDGER_TYPE_LIMITS,
|
|
365
|
+
// Common compilation errors with fixes
|
|
366
|
+
commonErrors: COMMON_ERRORS,
|
|
359
367
|
// Common mistakes that cause compilation failures
|
|
360
368
|
commonMistakes: [
|
|
361
369
|
{
|
|
@@ -388,6 +396,21 @@ export circuit increment(): [] {
|
|
|
388
396
|
correct: "Field",
|
|
389
397
|
error: "unbound identifier Cell (deprecated)",
|
|
390
398
|
},
|
|
399
|
+
{
|
|
400
|
+
wrong: "public_key(sk)",
|
|
401
|
+
correct: 'persistentHash<Vector<2, Bytes<32>>>([pad(32, "midnight:pk:"), sk])',
|
|
402
|
+
error: 'unbound identifier "public_key"',
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
wrong: "counter.value()",
|
|
406
|
+
correct: "// Read via witness or TypeScript SDK",
|
|
407
|
+
error: 'operation "value" undefined for Counter',
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
wrong: "data.lookup(key)",
|
|
411
|
+
correct: "// Use witness: witness get_value(key): Type;",
|
|
412
|
+
error: "member access requires struct type",
|
|
413
|
+
},
|
|
391
414
|
],
|
|
392
415
|
syntaxReference: compactReference,
|
|
393
416
|
sections: [
|
|
@@ -396,6 +419,9 @@ export circuit increment(): [] {
|
|
|
396
419
|
"Imports",
|
|
397
420
|
"Ledger Declarations",
|
|
398
421
|
"Data Types",
|
|
422
|
+
"Built-in Functions",
|
|
423
|
+
"Type Compatibility",
|
|
424
|
+
"Ledger Type Limits",
|
|
399
425
|
"Circuits",
|
|
400
426
|
"Witnesses",
|
|
401
427
|
"Constructor",
|
|
@@ -403,6 +429,7 @@ export circuit increment(): [] {
|
|
|
403
429
|
"Common Operations",
|
|
404
430
|
"Assertions",
|
|
405
431
|
"Common Mistakes to Avoid",
|
|
432
|
+
"Common Errors & Fixes",
|
|
406
433
|
"Exports for TypeScript",
|
|
407
434
|
"Reference Contracts",
|
|
408
435
|
],
|
|
@@ -411,7 +438,13 @@ export circuit increment(): [] {
|
|
|
411
438
|
repo: rc.repo,
|
|
412
439
|
description: rc.description,
|
|
413
440
|
})),
|
|
414
|
-
note: `CRITICAL: Use quickStartTemplate as your base. Check commonMistakes before submitting code.
|
|
441
|
+
note: `CRITICAL: Use quickStartTemplate as your base. Check commonMistakes and commonErrors before submitting code.
|
|
442
|
+
KEY GOTCHAS:
|
|
443
|
+
1. public_key() is NOT a builtin - use persistentHash pattern
|
|
444
|
+
2. Counter.value() NOT available in circuits - use witnesses
|
|
445
|
+
3. Map.lookup()/Set.member() NOT available in circuits - use witnesses
|
|
446
|
+
4. Field vs Uint comparison requires casting
|
|
447
|
+
This reference is for Compact ${COMPACT_VERSION.min}-${COMPACT_VERSION.max} (last updated: ${COMPACT_VERSION.lastUpdated}).`,
|
|
415
448
|
};
|
|
416
449
|
}
|
|
417
450
|
}
|