midnight-mcp 0.1.41 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -1
- package/dist/bin.d.ts +1 -0
- package/dist/bin.js +60 -0
- package/dist/chunk-HOWO4K5A.js +2197 -0
- package/dist/chunk-S7G4OHA4.js +8306 -0
- package/dist/db-YDGUWI5K.js +7 -0
- package/dist/index.d.ts +205 -3
- package/dist/index.js +28 -16
- package/package.json +16 -6
- package/dist/config/compact-version.d.ts +0 -183
- package/dist/config/compact-version.js +0 -423
- package/dist/db/index.d.ts +0 -3
- package/dist/db/index.js +0 -2
- package/dist/db/vectorStore.d.ts +0 -69
- package/dist/db/vectorStore.js +0 -196
- package/dist/pipeline/embeddings.d.ts +0 -25
- package/dist/pipeline/embeddings.js +0 -103
- package/dist/pipeline/github.d.ts +0 -84
- package/dist/pipeline/github.js +0 -399
- package/dist/pipeline/index.d.ts +0 -11
- package/dist/pipeline/index.js +0 -6
- package/dist/pipeline/indexer.d.ts +0 -41
- package/dist/pipeline/indexer.js +0 -254
- package/dist/pipeline/parser.d.ts +0 -46
- package/dist/pipeline/parser.js +0 -436
- package/dist/pipeline/releases.d.ts +0 -112
- package/dist/pipeline/releases.js +0 -298
- package/dist/pipeline/repository.d.ts +0 -372
- package/dist/pipeline/repository.js +0 -520
- package/dist/prompts/index.d.ts +0 -3
- package/dist/prompts/index.js +0 -2
- package/dist/prompts/templates.d.ts +0 -26
- package/dist/prompts/templates.js +0 -443
- package/dist/resources/code.d.ts +0 -15
- package/dist/resources/code.js +0 -122
- package/dist/resources/content/code-content.d.ts +0 -6
- package/dist/resources/content/code-content.js +0 -802
- package/dist/resources/content/docs-content.d.ts +0 -14
- package/dist/resources/content/docs-content.js +0 -1202
- package/dist/resources/content/index.d.ts +0 -6
- package/dist/resources/content/index.js +0 -6
- package/dist/resources/docs.d.ts +0 -15
- package/dist/resources/docs.js +0 -98
- package/dist/resources/index.d.ts +0 -6
- package/dist/resources/index.js +0 -13
- package/dist/resources/schemas.d.ts +0 -16
- package/dist/resources/schemas.js +0 -407
- package/dist/scripts/index-repos.d.ts +0 -12
- package/dist/scripts/index-repos.js +0 -53
- package/dist/server.d.ts +0 -43
- package/dist/server.js +0 -696
- package/dist/services/index.d.ts +0 -6
- package/dist/services/index.js +0 -6
- package/dist/services/sampling.d.ts +0 -62
- package/dist/services/sampling.js +0 -277
- package/dist/tools/analyze.d.ts +0 -106
- package/dist/tools/analyze.js +0 -431
- package/dist/tools/generation.d.ts +0 -9
- package/dist/tools/generation.js +0 -285
- package/dist/tools/health.d.ts +0 -120
- package/dist/tools/health.js +0 -365
- package/dist/tools/index.d.ts +0 -14
- package/dist/tools/index.js +0 -22
- package/dist/tools/meta.d.ts +0 -61
- package/dist/tools/meta.js +0 -282
- package/dist/tools/repository/constants.d.ts +0 -19
- package/dist/tools/repository/constants.js +0 -324
- package/dist/tools/repository/handlers.d.ts +0 -373
- package/dist/tools/repository/handlers.js +0 -724
- package/dist/tools/repository/index.d.ts +0 -9
- package/dist/tools/repository/index.js +0 -13
- package/dist/tools/repository/schemas.d.ts +0 -153
- package/dist/tools/repository/schemas.js +0 -106
- package/dist/tools/repository/tools.d.ts +0 -7
- package/dist/tools/repository/tools.js +0 -484
- package/dist/tools/repository/validation.d.ts +0 -106
- package/dist/tools/repository/validation.js +0 -820
- package/dist/tools/repository.d.ts +0 -6
- package/dist/tools/repository.js +0 -7
- package/dist/tools/search.d.ts +0 -76
- package/dist/tools/search.js +0 -423
- package/dist/types/index.d.ts +0 -2
- package/dist/types/index.js +0 -2
- package/dist/types/mcp.d.ts +0 -187
- package/dist/types/mcp.js +0 -6
- package/dist/utils/cache.d.ts +0 -77
- package/dist/utils/cache.js +0 -172
- package/dist/utils/config.d.ts +0 -70
- package/dist/utils/config.js +0 -294
- package/dist/utils/errors.d.ts +0 -111
- package/dist/utils/errors.js +0 -165
- package/dist/utils/health.d.ts +0 -29
- package/dist/utils/health.js +0 -132
- package/dist/utils/hosted-api.d.ts +0 -67
- package/dist/utils/hosted-api.js +0 -119
- package/dist/utils/index.d.ts +0 -16
- package/dist/utils/index.js +0 -15
- package/dist/utils/logger.d.ts +0 -48
- package/dist/utils/logger.js +0 -124
- package/dist/utils/rate-limit.d.ts +0 -61
- package/dist/utils/rate-limit.js +0 -148
- package/dist/utils/validation.d.ts +0 -52
- package/dist/utils/validation.js +0 -255
|
@@ -1,802 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Embedded code examples and templates
|
|
3
|
-
* Separated from code.ts for better maintainability
|
|
4
|
-
*/
|
|
5
|
-
export const EMBEDDED_CODE = {
|
|
6
|
-
"midnight://code/examples/counter": `// Counter Example Contract
|
|
7
|
-
// A simple contract demonstrating basic Compact concepts
|
|
8
|
-
|
|
9
|
-
include "std";
|
|
10
|
-
|
|
11
|
-
ledger {
|
|
12
|
-
// Public counter - visible to everyone
|
|
13
|
-
counter: Counter;
|
|
14
|
-
|
|
15
|
-
// Track last modifier (public)
|
|
16
|
-
lastModifier: Opaque<"address">;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
// Increment the counter
|
|
20
|
-
export circuit increment(amount: Field): Field {
|
|
21
|
-
// Validate input
|
|
22
|
-
assert(amount > 0, "Amount must be positive");
|
|
23
|
-
assert(amount <= 100, "Amount too large");
|
|
24
|
-
|
|
25
|
-
// Update counter
|
|
26
|
-
ledger.counter.increment(amount);
|
|
27
|
-
|
|
28
|
-
// Return new value
|
|
29
|
-
return ledger.counter.value();
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Decrement the counter
|
|
33
|
-
export circuit decrement(amount: Field): Field {
|
|
34
|
-
// Validate input
|
|
35
|
-
assert(amount > 0, "Amount must be positive");
|
|
36
|
-
assert(ledger.counter.value() >= amount, "Counter would go negative");
|
|
37
|
-
|
|
38
|
-
// Update counter
|
|
39
|
-
ledger.counter.decrement(amount);
|
|
40
|
-
|
|
41
|
-
// Return new value
|
|
42
|
-
return ledger.counter.value();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
// Read current value (view function)
|
|
46
|
-
export circuit getValue(): Field {
|
|
47
|
-
return ledger.counter.value();
|
|
48
|
-
}
|
|
49
|
-
`,
|
|
50
|
-
"midnight://code/examples/bboard": `// Bulletin Board Example Contract
|
|
51
|
-
// Demonstrates private messaging with selective disclosure
|
|
52
|
-
|
|
53
|
-
include "std";
|
|
54
|
-
|
|
55
|
-
ledger {
|
|
56
|
-
// Public: message count and IDs
|
|
57
|
-
messageCount: Counter;
|
|
58
|
-
messageIds: Set<Field>;
|
|
59
|
-
|
|
60
|
-
// Private: actual message contents
|
|
61
|
-
@private
|
|
62
|
-
messages: Map<Field, Opaque<"string">>;
|
|
63
|
-
|
|
64
|
-
// Private: message authors
|
|
65
|
-
@private
|
|
66
|
-
authors: Map<Field, Opaque<"address">>;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// Post a new message (content is private)
|
|
70
|
-
export circuit postMessage(content: Opaque<"string">, author: Opaque<"address">): Field {
|
|
71
|
-
// Generate unique message ID
|
|
72
|
-
const messageId = ledger.messageCount.value();
|
|
73
|
-
|
|
74
|
-
// Store message privately
|
|
75
|
-
ledger.messages.insert(messageId, content);
|
|
76
|
-
ledger.authors.insert(messageId, author);
|
|
77
|
-
|
|
78
|
-
// Update public counters
|
|
79
|
-
ledger.messageCount.increment(1);
|
|
80
|
-
ledger.messageIds.add(messageId);
|
|
81
|
-
|
|
82
|
-
return messageId;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
// Witness to fetch message content
|
|
86
|
-
witness getMessageContent(id: Field): Opaque<"string"> {
|
|
87
|
-
return ledger.messages.get(id);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
// Reveal a message publicly (owner's choice)
|
|
91
|
-
export circuit revealMessage(id: Field): Opaque<"string"> {
|
|
92
|
-
assert(ledger.messageIds.contains(id), "Message not found");
|
|
93
|
-
|
|
94
|
-
const content = getMessageContent(id);
|
|
95
|
-
return disclose(content);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Get total message count
|
|
99
|
-
export circuit getMessageCount(): Field {
|
|
100
|
-
return ledger.messageCount.value();
|
|
101
|
-
}
|
|
102
|
-
`,
|
|
103
|
-
"midnight://code/patterns/state-management": `// State Management Pattern
|
|
104
|
-
// Best practices for managing public and private state
|
|
105
|
-
|
|
106
|
-
include "std";
|
|
107
|
-
|
|
108
|
-
ledger {
|
|
109
|
-
// PUBLIC STATE
|
|
110
|
-
// - Use for data that should be transparent
|
|
111
|
-
// - Visible in blockchain explorers
|
|
112
|
-
// - Can be queried by anyone
|
|
113
|
-
|
|
114
|
-
totalSupply: Counter;
|
|
115
|
-
publicConfig: Field;
|
|
116
|
-
|
|
117
|
-
// PRIVATE STATE
|
|
118
|
-
// - Use for sensitive user data
|
|
119
|
-
// - Only owner can read
|
|
120
|
-
// - Requires witnesses to access in circuits
|
|
121
|
-
|
|
122
|
-
@private
|
|
123
|
-
userSecrets: Map<Opaque<"address">, Bytes<32>>;
|
|
124
|
-
|
|
125
|
-
@private
|
|
126
|
-
privateBalances: Map<Opaque<"address">, Field>;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
// Reading public state is straightforward
|
|
130
|
-
export circuit getTotalSupply(): Field {
|
|
131
|
-
return ledger.totalSupply.value();
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Reading private state requires a witness
|
|
135
|
-
witness getUserSecret(user: Opaque<"address">): Bytes<32> {
|
|
136
|
-
return ledger.userSecrets.get(user);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
// Using private state in a circuit
|
|
140
|
-
export circuit proveSecretKnowledge(
|
|
141
|
-
user: Opaque<"address">,
|
|
142
|
-
secretHash: Bytes<32>
|
|
143
|
-
): Boolean {
|
|
144
|
-
const secret = getUserSecret(user);
|
|
145
|
-
|
|
146
|
-
// Prove knowledge without revealing secret
|
|
147
|
-
assert(hash(secret) == secretHash);
|
|
148
|
-
return true;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
// Selective disclosure pattern
|
|
152
|
-
export circuit revealBalance(user: Opaque<"address">): Field {
|
|
153
|
-
const balance = getPrivateBalance(user);
|
|
154
|
-
// Explicitly reveal - user's choice
|
|
155
|
-
return disclose(balance);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
witness getPrivateBalance(user: Opaque<"address">): Field {
|
|
159
|
-
return ledger.privateBalances.get(user);
|
|
160
|
-
}
|
|
161
|
-
`,
|
|
162
|
-
"midnight://code/patterns/access-control": `// Access Control Pattern
|
|
163
|
-
// Implementing permissions and authorization
|
|
164
|
-
|
|
165
|
-
include "std";
|
|
166
|
-
|
|
167
|
-
ledger {
|
|
168
|
-
// Role definitions
|
|
169
|
-
owner: Opaque<"address">;
|
|
170
|
-
admins: Set<Opaque<"address">>;
|
|
171
|
-
|
|
172
|
-
// Access-controlled state
|
|
173
|
-
sensitiveData: Field;
|
|
174
|
-
|
|
175
|
-
@private
|
|
176
|
-
adminKeys: Map<Opaque<"address">, Bytes<32>>;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Witness to get caller identity
|
|
180
|
-
witness getCaller(): Opaque<"address"> {
|
|
181
|
-
return getCurrentCaller();
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
// Only owner can call
|
|
185
|
-
export circuit onlyOwnerAction(newValue: Field): Void {
|
|
186
|
-
const caller = getCaller();
|
|
187
|
-
assert(caller == ledger.owner, "Not owner");
|
|
188
|
-
|
|
189
|
-
ledger.sensitiveData = newValue;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
// Only admins can call
|
|
193
|
-
export circuit onlyAdminAction(data: Field): Void {
|
|
194
|
-
const caller = getCaller();
|
|
195
|
-
assert(ledger.admins.contains(caller), "Not admin");
|
|
196
|
-
|
|
197
|
-
// Admin action here
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Multi-sig pattern (require multiple approvals)
|
|
201
|
-
witness getApprovalCount(action: Bytes<32>): Field {
|
|
202
|
-
return countApprovals(action);
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
export circuit requireMultisig(action: Bytes<32>, threshold: Field): Boolean {
|
|
206
|
-
const approvals = getApprovalCount(action);
|
|
207
|
-
assert(approvals >= threshold, "Insufficient approvals");
|
|
208
|
-
return true;
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
// Time-locked action
|
|
212
|
-
witness getCurrentTime(): Field {
|
|
213
|
-
return getBlockTimestamp();
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
export circuit timeLockedAction(unlockTime: Field): Void {
|
|
217
|
-
const currentTime = getCurrentTime();
|
|
218
|
-
assert(currentTime >= unlockTime, "Action is timelocked");
|
|
219
|
-
|
|
220
|
-
// Perform action
|
|
221
|
-
}
|
|
222
|
-
`,
|
|
223
|
-
"midnight://code/patterns/privacy-preserving": `// Privacy-Preserving Patterns
|
|
224
|
-
// Techniques for maintaining privacy in smart contracts
|
|
225
|
-
|
|
226
|
-
include "std";
|
|
227
|
-
|
|
228
|
-
ledger {
|
|
229
|
-
// Commitment-based private balance
|
|
230
|
-
balanceCommitments: Map<Opaque<"address">, Field>;
|
|
231
|
-
|
|
232
|
-
// Nullifier set (prevents double-spending)
|
|
233
|
-
nullifiers: Set<Field>;
|
|
234
|
-
|
|
235
|
-
@private
|
|
236
|
-
secretBalances: Map<Opaque<"address">, Field>;
|
|
237
|
-
|
|
238
|
-
@private
|
|
239
|
-
secretNonces: Map<Opaque<"address">, Field>;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// PATTERN 1: Commitment Scheme
|
|
243
|
-
// Store commitments instead of values
|
|
244
|
-
|
|
245
|
-
export circuit deposit(
|
|
246
|
-
user: Opaque<"address">,
|
|
247
|
-
amount: Field,
|
|
248
|
-
nonce: Field
|
|
249
|
-
): Field {
|
|
250
|
-
// Create commitment: hash(amount, nonce, user)
|
|
251
|
-
const commitment = hash(amount, nonce, user);
|
|
252
|
-
|
|
253
|
-
// Store commitment (hides amount)
|
|
254
|
-
ledger.balanceCommitments.insert(user, commitment);
|
|
255
|
-
|
|
256
|
-
return commitment;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
export circuit proveBalance(
|
|
260
|
-
user: Opaque<"address">,
|
|
261
|
-
amount: Field,
|
|
262
|
-
nonce: Field,
|
|
263
|
-
minBalance: Field
|
|
264
|
-
): Boolean {
|
|
265
|
-
// Verify commitment
|
|
266
|
-
const expectedCommitment = hash(amount, nonce, user);
|
|
267
|
-
assert(ledger.balanceCommitments.get(user) == expectedCommitment);
|
|
268
|
-
|
|
269
|
-
// Prove property without revealing value
|
|
270
|
-
assert(amount >= minBalance);
|
|
271
|
-
return true;
|
|
272
|
-
}
|
|
273
|
-
|
|
274
|
-
// PATTERN 2: Nullifiers (Prevent Double-Spending)
|
|
275
|
-
|
|
276
|
-
witness generateNullifier(secret: Bytes<32>, action: Field): Field {
|
|
277
|
-
return hash(secret, action);
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
export circuit spendOnce(
|
|
281
|
-
secret: Bytes<32>,
|
|
282
|
-
action: Field
|
|
283
|
-
): Void {
|
|
284
|
-
const nullifier = generateNullifier(secret, action);
|
|
285
|
-
|
|
286
|
-
// Check nullifier hasn't been used
|
|
287
|
-
assert(!ledger.nullifiers.contains(nullifier), "Already spent");
|
|
288
|
-
|
|
289
|
-
// Mark as used
|
|
290
|
-
ledger.nullifiers.add(nullifier);
|
|
291
|
-
|
|
292
|
-
// Perform action
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
// PATTERN 3: Range Proofs
|
|
296
|
-
|
|
297
|
-
export circuit proveInRange(
|
|
298
|
-
@private value: Field,
|
|
299
|
-
min: Field,
|
|
300
|
-
max: Field
|
|
301
|
-
): Boolean {
|
|
302
|
-
// Prove value is in range without revealing it
|
|
303
|
-
assert(value >= min);
|
|
304
|
-
assert(value <= max);
|
|
305
|
-
return true;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
// PATTERN 4: Private Set Membership
|
|
309
|
-
|
|
310
|
-
export circuit proveMembership(
|
|
311
|
-
@private element: Field,
|
|
312
|
-
setRoot: Field,
|
|
313
|
-
@private proof: Array<Field>
|
|
314
|
-
): Boolean {
|
|
315
|
-
// Prove element is in set without revealing which element
|
|
316
|
-
const computedRoot = computeMerkleRoot(element, proof);
|
|
317
|
-
assert(computedRoot == setRoot);
|
|
318
|
-
return true;
|
|
319
|
-
}
|
|
320
|
-
|
|
321
|
-
witness computeMerkleRoot(element: Field, proof: Array<Field>): Field {
|
|
322
|
-
// Compute Merkle root from element and proof
|
|
323
|
-
return merkleCompute(element, proof);
|
|
324
|
-
}
|
|
325
|
-
`,
|
|
326
|
-
"midnight://code/templates/token": `// Privacy-Preserving Token Template
|
|
327
|
-
// Starter template for token contracts with privacy features
|
|
328
|
-
|
|
329
|
-
include "std";
|
|
330
|
-
|
|
331
|
-
ledger {
|
|
332
|
-
// Public token metadata
|
|
333
|
-
name: Opaque<"string">;
|
|
334
|
-
symbol: Opaque<"string">;
|
|
335
|
-
decimals: Field;
|
|
336
|
-
totalSupply: Counter;
|
|
337
|
-
|
|
338
|
-
// Private balances
|
|
339
|
-
@private
|
|
340
|
-
balances: Map<Opaque<"address">, Field>;
|
|
341
|
-
|
|
342
|
-
// Private allowances
|
|
343
|
-
@private
|
|
344
|
-
allowances: Map<Opaque<"address">, Map<Opaque<"address">, Field>>;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Witnesses for private state access
|
|
348
|
-
witness getBalance(account: Opaque<"address">): Field {
|
|
349
|
-
return ledger.balances.get(account) ?? 0;
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
witness getAllowance(owner: Opaque<"address">, spender: Opaque<"address">): Field {
|
|
353
|
-
return ledger.allowances.get(owner)?.get(spender) ?? 0;
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
witness getCaller(): Opaque<"address"> {
|
|
357
|
-
return getCurrentCaller();
|
|
358
|
-
}
|
|
359
|
-
|
|
360
|
-
// Transfer tokens privately
|
|
361
|
-
export circuit transfer(
|
|
362
|
-
to: Opaque<"address">,
|
|
363
|
-
amount: Field
|
|
364
|
-
): Boolean {
|
|
365
|
-
const from = getCaller();
|
|
366
|
-
const fromBalance = getBalance(from);
|
|
367
|
-
|
|
368
|
-
// Validate
|
|
369
|
-
assert(amount > 0, "Invalid amount");
|
|
370
|
-
assert(fromBalance >= amount, "Insufficient balance");
|
|
371
|
-
|
|
372
|
-
// Update balances privately
|
|
373
|
-
ledger.balances.insert(from, fromBalance - amount);
|
|
374
|
-
ledger.balances.insert(to, getBalance(to) + amount);
|
|
375
|
-
|
|
376
|
-
return true;
|
|
377
|
-
}
|
|
378
|
-
|
|
379
|
-
// Approve spender
|
|
380
|
-
export circuit approve(
|
|
381
|
-
spender: Opaque<"address">,
|
|
382
|
-
amount: Field
|
|
383
|
-
): Boolean {
|
|
384
|
-
const owner = getCaller();
|
|
385
|
-
|
|
386
|
-
// Get or create allowance map for owner
|
|
387
|
-
// Note: Simplified - actual implementation needs nested map handling
|
|
388
|
-
ledger.allowances.get(owner).insert(spender, amount);
|
|
389
|
-
|
|
390
|
-
return true;
|
|
391
|
-
}
|
|
392
|
-
|
|
393
|
-
// Transfer from approved account
|
|
394
|
-
export circuit transferFrom(
|
|
395
|
-
from: Opaque<"address">,
|
|
396
|
-
to: Opaque<"address">,
|
|
397
|
-
amount: Field
|
|
398
|
-
): Boolean {
|
|
399
|
-
const spender = getCaller();
|
|
400
|
-
const allowance = getAllowance(from, spender);
|
|
401
|
-
const fromBalance = getBalance(from);
|
|
402
|
-
|
|
403
|
-
// Validate
|
|
404
|
-
assert(amount > 0, "Invalid amount");
|
|
405
|
-
assert(allowance >= amount, "Insufficient allowance");
|
|
406
|
-
assert(fromBalance >= amount, "Insufficient balance");
|
|
407
|
-
|
|
408
|
-
// Update state
|
|
409
|
-
ledger.balances.insert(from, fromBalance - amount);
|
|
410
|
-
ledger.balances.insert(to, getBalance(to) + amount);
|
|
411
|
-
ledger.allowances.get(from).insert(spender, allowance - amount);
|
|
412
|
-
|
|
413
|
-
return true;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Reveal balance (user's choice)
|
|
417
|
-
export circuit revealMyBalance(): Field {
|
|
418
|
-
const caller = getCaller();
|
|
419
|
-
const balance = getBalance(caller);
|
|
420
|
-
return disclose(balance);
|
|
421
|
-
}
|
|
422
|
-
`,
|
|
423
|
-
"midnight://code/templates/voting": `// Private Voting Template
|
|
424
|
-
// Starter template for privacy-preserving voting contracts
|
|
425
|
-
|
|
426
|
-
include "std";
|
|
427
|
-
|
|
428
|
-
ledger {
|
|
429
|
-
// Public: proposal metadata
|
|
430
|
-
proposalCount: Counter;
|
|
431
|
-
proposals: Map<Field, Opaque<"string">>;
|
|
432
|
-
votingDeadlines: Map<Field, Field>;
|
|
433
|
-
|
|
434
|
-
// Public: vote tallies (revealed after voting ends)
|
|
435
|
-
finalTallies: Map<Field, Map<Field, Field>>; // proposalId -> optionId -> count
|
|
436
|
-
|
|
437
|
-
// Private: individual votes
|
|
438
|
-
@private
|
|
439
|
-
votes: Map<Field, Map<Opaque<"address">, Field>>; // proposalId -> voter -> option
|
|
440
|
-
|
|
441
|
-
// Nullifiers to prevent double voting
|
|
442
|
-
voteNullifiers: Set<Field>;
|
|
443
|
-
|
|
444
|
-
// Eligible voters
|
|
445
|
-
eligibleVoters: Set<Opaque<"address">>;
|
|
446
|
-
}
|
|
447
|
-
|
|
448
|
-
// Witnesses
|
|
449
|
-
witness getCaller(): Opaque<"address"> {
|
|
450
|
-
return getCurrentCaller();
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
witness getCurrentTime(): Field {
|
|
454
|
-
return getBlockTimestamp();
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
witness getVote(proposalId: Field, voter: Opaque<"address">): Field {
|
|
458
|
-
return ledger.votes.get(proposalId)?.get(voter) ?? 0;
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
witness computeNullifier(voter: Opaque<"address">, proposalId: Field): Field {
|
|
462
|
-
return hash(voter, proposalId);
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// Create a new proposal
|
|
466
|
-
export circuit createProposal(
|
|
467
|
-
description: Opaque<"string">,
|
|
468
|
-
deadline: Field,
|
|
469
|
-
options: Field
|
|
470
|
-
): Field {
|
|
471
|
-
const proposalId = ledger.proposalCount.value();
|
|
472
|
-
|
|
473
|
-
// Store proposal
|
|
474
|
-
ledger.proposals.insert(proposalId, description);
|
|
475
|
-
ledger.votingDeadlines.insert(proposalId, deadline);
|
|
476
|
-
|
|
477
|
-
// Initialize tally for each option
|
|
478
|
-
// (Simplified - actual implementation needs loop)
|
|
479
|
-
|
|
480
|
-
ledger.proposalCount.increment(1);
|
|
481
|
-
return proposalId;
|
|
482
|
-
}
|
|
483
|
-
|
|
484
|
-
// Cast a private vote
|
|
485
|
-
export circuit vote(
|
|
486
|
-
proposalId: Field,
|
|
487
|
-
option: Field
|
|
488
|
-
): Boolean {
|
|
489
|
-
const voter = getCaller();
|
|
490
|
-
const currentTime = getCurrentTime();
|
|
491
|
-
|
|
492
|
-
// Check eligibility
|
|
493
|
-
assert(ledger.eligibleVoters.contains(voter), "Not eligible to vote");
|
|
494
|
-
|
|
495
|
-
// Check deadline
|
|
496
|
-
const deadline = ledger.votingDeadlines.get(proposalId);
|
|
497
|
-
assert(currentTime < deadline, "Voting ended");
|
|
498
|
-
|
|
499
|
-
// Check for double voting using nullifier
|
|
500
|
-
const nullifier = computeNullifier(voter, proposalId);
|
|
501
|
-
assert(!ledger.voteNullifiers.contains(nullifier), "Already voted");
|
|
502
|
-
|
|
503
|
-
// Record vote privately
|
|
504
|
-
ledger.votes.get(proposalId).insert(voter, option);
|
|
505
|
-
|
|
506
|
-
// Add nullifier to prevent double voting
|
|
507
|
-
ledger.voteNullifiers.add(nullifier);
|
|
508
|
-
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
// Reveal individual vote (voter's choice)
|
|
513
|
-
export circuit revealMyVote(proposalId: Field): Field {
|
|
514
|
-
const voter = getCaller();
|
|
515
|
-
const myVote = getVote(proposalId, voter);
|
|
516
|
-
return disclose(myVote);
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
// Tally votes (after deadline)
|
|
520
|
-
// Note: This is simplified - real implementation would need
|
|
521
|
-
// a mechanism to privately aggregate votes
|
|
522
|
-
export circuit tallyVotes(proposalId: Field): Boolean {
|
|
523
|
-
const currentTime = getCurrentTime();
|
|
524
|
-
const deadline = ledger.votingDeadlines.get(proposalId);
|
|
525
|
-
|
|
526
|
-
assert(currentTime >= deadline, "Voting still active");
|
|
527
|
-
|
|
528
|
-
// In a real implementation, votes would be aggregated
|
|
529
|
-
// using homomorphic encryption or MPC
|
|
530
|
-
|
|
531
|
-
return true;
|
|
532
|
-
}
|
|
533
|
-
|
|
534
|
-
// Add eligible voter (admin only)
|
|
535
|
-
export circuit addVoter(voter: Opaque<"address">): Void {
|
|
536
|
-
// Add access control in real implementation
|
|
537
|
-
ledger.eligibleVoters.add(voter);
|
|
538
|
-
}
|
|
539
|
-
`,
|
|
540
|
-
"midnight://code/examples/nullifier": `// Nullifier Pattern Example
|
|
541
|
-
// Demonstrates how to create and use nullifiers to prevent double-spending/actions
|
|
542
|
-
|
|
543
|
-
include "std";
|
|
544
|
-
|
|
545
|
-
ledger {
|
|
546
|
-
// Set of used nullifiers - prevents replay attacks
|
|
547
|
-
usedNullifiers: Set<Bytes<32>>;
|
|
548
|
-
|
|
549
|
-
// Track claimed rewards
|
|
550
|
-
claimedRewards: Counter;
|
|
551
|
-
}
|
|
552
|
-
|
|
553
|
-
// Hash function for creating nullifiers
|
|
554
|
-
// Combines secret + public data to create unique identifier
|
|
555
|
-
witness computeNullifier(secret: Field, commitment: Field): Bytes<32> {
|
|
556
|
-
// Hash the secret with the commitment
|
|
557
|
-
// The nullifier reveals nothing about the secret
|
|
558
|
-
// but is unique per secret+commitment pair
|
|
559
|
-
return hash(secret, commitment);
|
|
560
|
-
}
|
|
561
|
-
|
|
562
|
-
// Alternative: nullifier from address and action ID
|
|
563
|
-
witness computeActionNullifier(
|
|
564
|
-
userSecret: Field,
|
|
565
|
-
actionId: Field
|
|
566
|
-
): Bytes<32> {
|
|
567
|
-
// Create nullifier: hash(secret || actionId)
|
|
568
|
-
return hash(userSecret, actionId);
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// Claim a reward (can only claim once per user)
|
|
572
|
-
export circuit claimReward(
|
|
573
|
-
secret: Field,
|
|
574
|
-
commitment: Field,
|
|
575
|
-
rewardAmount: Field
|
|
576
|
-
): Boolean {
|
|
577
|
-
// Compute the nullifier
|
|
578
|
-
const nullifier = computeNullifier(secret, commitment);
|
|
579
|
-
|
|
580
|
-
// Check nullifier hasn't been used (prevents double-claim)
|
|
581
|
-
assert(
|
|
582
|
-
!ledger.usedNullifiers.contains(nullifier),
|
|
583
|
-
"Reward already claimed"
|
|
584
|
-
);
|
|
585
|
-
|
|
586
|
-
// Mark nullifier as used
|
|
587
|
-
ledger.usedNullifiers.add(nullifier);
|
|
588
|
-
|
|
589
|
-
// Process reward
|
|
590
|
-
ledger.claimedRewards.increment(rewardAmount);
|
|
591
|
-
|
|
592
|
-
return true;
|
|
593
|
-
}
|
|
594
|
-
|
|
595
|
-
// Vote with nullifier (prevents double-voting)
|
|
596
|
-
export circuit voteWithNullifier(
|
|
597
|
-
voterSecret: Field,
|
|
598
|
-
proposalId: Field,
|
|
599
|
-
vote: Field
|
|
600
|
-
): Boolean {
|
|
601
|
-
// Create unique nullifier for this voter + proposal
|
|
602
|
-
const nullifier = computeActionNullifier(voterSecret, proposalId);
|
|
603
|
-
|
|
604
|
-
// Ensure hasn't voted on this proposal
|
|
605
|
-
assert(
|
|
606
|
-
!ledger.usedNullifiers.contains(nullifier),
|
|
607
|
-
"Already voted on this proposal"
|
|
608
|
-
);
|
|
609
|
-
|
|
610
|
-
// Record nullifier
|
|
611
|
-
ledger.usedNullifiers.add(nullifier);
|
|
612
|
-
|
|
613
|
-
// Process vote...
|
|
614
|
-
return true;
|
|
615
|
-
}
|
|
616
|
-
`,
|
|
617
|
-
"midnight://code/examples/hash": `// Hash Functions in Compact
|
|
618
|
-
// Examples of using hash functions for various purposes
|
|
619
|
-
|
|
620
|
-
include "std";
|
|
621
|
-
|
|
622
|
-
ledger {
|
|
623
|
-
commitments: Set<Bytes<32>>;
|
|
624
|
-
hashedData: Map<Field, Bytes<32>>;
|
|
625
|
-
}
|
|
626
|
-
|
|
627
|
-
// Basic hash function usage
|
|
628
|
-
witness simpleHash(data: Field): Bytes<32> {
|
|
629
|
-
// Hash a single field element
|
|
630
|
-
return hash(data);
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
// Hash multiple values together
|
|
634
|
-
witness hashMultiple(a: Field, b: Field, c: Field): Bytes<32> {
|
|
635
|
-
// Concatenate and hash
|
|
636
|
-
return hash(a, b, c);
|
|
637
|
-
}
|
|
638
|
-
|
|
639
|
-
// Create a commitment (hash of value + randomness)
|
|
640
|
-
witness createCommitment(value: Field, randomness: Field): Bytes<32> {
|
|
641
|
-
// Pedersen-style commitment: H(value || randomness)
|
|
642
|
-
return hash(value, randomness);
|
|
643
|
-
}
|
|
644
|
-
|
|
645
|
-
// Hash bytes data
|
|
646
|
-
witness hashBytes(data: Bytes<64>): Bytes<32> {
|
|
647
|
-
return hash(data);
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
// Create nullifier from secret
|
|
651
|
-
witness createNullifier(secret: Field, publicInput: Field): Bytes<32> {
|
|
652
|
-
// Nullifier = H(secret || publicInput)
|
|
653
|
-
// Reveals nothing about secret, but is deterministic
|
|
654
|
-
return hash(secret, publicInput);
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// Verify a commitment matches
|
|
658
|
-
export circuit verifyCommitment(
|
|
659
|
-
value: Field,
|
|
660
|
-
randomness: Field,
|
|
661
|
-
expectedCommitment: Bytes<32>
|
|
662
|
-
): Boolean {
|
|
663
|
-
const computed = createCommitment(value, randomness);
|
|
664
|
-
assert(computed == expectedCommitment, "Commitment mismatch");
|
|
665
|
-
return true;
|
|
666
|
-
}
|
|
667
|
-
|
|
668
|
-
// Store a hashed value
|
|
669
|
-
export circuit storeHashed(id: Field, data: Field): Bytes<32> {
|
|
670
|
-
const hashed = simpleHash(data);
|
|
671
|
-
ledger.hashedData.insert(id, hashed);
|
|
672
|
-
return hashed;
|
|
673
|
-
}
|
|
674
|
-
|
|
675
|
-
// Commit-reveal pattern
|
|
676
|
-
export circuit commit(commitment: Bytes<32>): Boolean {
|
|
677
|
-
assert(!ledger.commitments.contains(commitment), "Already committed");
|
|
678
|
-
ledger.commitments.add(commitment);
|
|
679
|
-
return true;
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
export circuit reveal(value: Field, randomness: Field): Field {
|
|
683
|
-
const commitment = createCommitment(value, randomness);
|
|
684
|
-
assert(ledger.commitments.contains(commitment), "No matching commitment");
|
|
685
|
-
return disclose(value);
|
|
686
|
-
}
|
|
687
|
-
`,
|
|
688
|
-
"midnight://code/examples/simple-counter": `// Simple Counter Contract
|
|
689
|
-
// Minimal example for learning Compact basics
|
|
690
|
-
|
|
691
|
-
include "std";
|
|
692
|
-
|
|
693
|
-
// Ledger state - stored on chain
|
|
694
|
-
ledger {
|
|
695
|
-
counter: Counter;
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
// Increment the counter by 1
|
|
699
|
-
export circuit increment(): Field {
|
|
700
|
-
ledger.counter.increment(1);
|
|
701
|
-
return ledger.counter.value();
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Decrement the counter by 1
|
|
705
|
-
export circuit decrement(): Field {
|
|
706
|
-
assert(ledger.counter.value() > 0, "Cannot go below zero");
|
|
707
|
-
ledger.counter.decrement(1);
|
|
708
|
-
return ledger.counter.value();
|
|
709
|
-
}
|
|
710
|
-
|
|
711
|
-
// Get current value
|
|
712
|
-
export circuit get(): Field {
|
|
713
|
-
return ledger.counter.value();
|
|
714
|
-
}
|
|
715
|
-
|
|
716
|
-
// Reset to zero (add access control in real apps)
|
|
717
|
-
export circuit reset(): Void {
|
|
718
|
-
const current = ledger.counter.value();
|
|
719
|
-
ledger.counter.decrement(current);
|
|
720
|
-
}
|
|
721
|
-
`,
|
|
722
|
-
"midnight://code/templates/basic": `// Basic Compact Contract Template
|
|
723
|
-
// Starting point for new contracts
|
|
724
|
-
|
|
725
|
-
include "std";
|
|
726
|
-
|
|
727
|
-
// ============================================
|
|
728
|
-
// LEDGER STATE
|
|
729
|
-
// ============================================
|
|
730
|
-
|
|
731
|
-
ledger {
|
|
732
|
-
// Public state (visible on-chain)
|
|
733
|
-
initialized: Boolean;
|
|
734
|
-
owner: Opaque<"address">;
|
|
735
|
-
|
|
736
|
-
// Private state (only owner can see)
|
|
737
|
-
@private
|
|
738
|
-
secretData: Field;
|
|
739
|
-
}
|
|
740
|
-
|
|
741
|
-
// ============================================
|
|
742
|
-
// INITIALIZATION
|
|
743
|
-
// ============================================
|
|
744
|
-
|
|
745
|
-
export circuit initialize(ownerAddress: Opaque<"address">): Boolean {
|
|
746
|
-
assert(!ledger.initialized, "Already initialized");
|
|
747
|
-
|
|
748
|
-
ledger.owner = ownerAddress;
|
|
749
|
-
ledger.initialized = true;
|
|
750
|
-
|
|
751
|
-
return true;
|
|
752
|
-
}
|
|
753
|
-
|
|
754
|
-
// ============================================
|
|
755
|
-
// ACCESS CONTROL
|
|
756
|
-
// ============================================
|
|
757
|
-
|
|
758
|
-
witness getCaller(): Opaque<"address"> {
|
|
759
|
-
// Returns the transaction sender
|
|
760
|
-
return context.caller;
|
|
761
|
-
}
|
|
762
|
-
|
|
763
|
-
witness isOwner(): Boolean {
|
|
764
|
-
return getCaller() == ledger.owner;
|
|
765
|
-
}
|
|
766
|
-
|
|
767
|
-
// ============================================
|
|
768
|
-
// PUBLIC FUNCTIONS
|
|
769
|
-
// ============================================
|
|
770
|
-
|
|
771
|
-
export circuit publicFunction(input: Field): Field {
|
|
772
|
-
assert(ledger.initialized, "Not initialized");
|
|
773
|
-
|
|
774
|
-
// Your logic here
|
|
775
|
-
return input * 2;
|
|
776
|
-
}
|
|
777
|
-
|
|
778
|
-
// ============================================
|
|
779
|
-
// OWNER-ONLY FUNCTIONS
|
|
780
|
-
// ============================================
|
|
781
|
-
|
|
782
|
-
export circuit setSecret(newSecret: Field): Void {
|
|
783
|
-
assert(isOwner(), "Only owner can set secret");
|
|
784
|
-
ledger.secretData = newSecret;
|
|
785
|
-
}
|
|
786
|
-
|
|
787
|
-
// ============================================
|
|
788
|
-
// PRIVATE DATA ACCESS
|
|
789
|
-
// ============================================
|
|
790
|
-
|
|
791
|
-
witness getSecret(): Field {
|
|
792
|
-
assert(isOwner(), "Only owner can view");
|
|
793
|
-
return ledger.secretData;
|
|
794
|
-
}
|
|
795
|
-
|
|
796
|
-
export circuit revealSecret(): Field {
|
|
797
|
-
assert(isOwner(), "Only owner can reveal");
|
|
798
|
-
return disclose(getSecret());
|
|
799
|
-
}
|
|
800
|
-
`,
|
|
801
|
-
};
|
|
802
|
-
//# sourceMappingURL=code-content.js.map
|