@invisi-labs/protocol 1.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/dist/chunk-XTOQXQES.js +4011 -0
- package/dist/chunk-XTOQXQES.js.map +1 -0
- package/dist/contracts.cjs +4042 -0
- package/dist/contracts.cjs.map +1 -0
- package/dist/contracts.d.cts +12 -0
- package/dist/contracts.d.ts +12 -0
- package/dist/contracts.js +17 -0
- package/dist/contracts.js.map +1 -0
- package/dist/index.cjs +7207 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +948 -0
- package/dist/index.d.ts +948 -0
- package/dist/index.js +3613 -0
- package/dist/index.js.map +1 -0
- package/dist/types-RN45XzKc.d.cts +3193 -0
- package/dist/types-RN45XzKc.d.ts +3193 -0
- package/package.json +46 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,3613 @@
|
|
|
1
|
+
import {
|
|
2
|
+
invisiAddressRegistryAbi,
|
|
3
|
+
invisiFactoryAbi,
|
|
4
|
+
invisiProtocolAbi
|
|
5
|
+
} from "./chunk-XTOQXQES.js";
|
|
6
|
+
|
|
7
|
+
// src/AddressRegistry.ts
|
|
8
|
+
import { getAddress as getAddress6, keccak256 as keccak2566 } from "ethers";
|
|
9
|
+
import {
|
|
10
|
+
MissingCapabilityError as MissingCapabilityError2,
|
|
11
|
+
ReceivingAddress as ReceivingAddress3
|
|
12
|
+
} from "@invisi-labs/core";
|
|
13
|
+
|
|
14
|
+
// src/RegistrationOperation.ts
|
|
15
|
+
import { hexlify as hexlify2, Interface as Interface5 } from "ethers";
|
|
16
|
+
import {
|
|
17
|
+
computeWalletAuthorizationDigest as computeWalletAuthorizationDigest5,
|
|
18
|
+
MissingCapabilityError,
|
|
19
|
+
ReceivingAddress as ReceivingAddress2
|
|
20
|
+
} from "@invisi-labs/core";
|
|
21
|
+
|
|
22
|
+
// src/registry.ts
|
|
23
|
+
import {
|
|
24
|
+
Contract,
|
|
25
|
+
Interface,
|
|
26
|
+
concat,
|
|
27
|
+
getAddress,
|
|
28
|
+
getBytes,
|
|
29
|
+
hexlify,
|
|
30
|
+
isHexString,
|
|
31
|
+
keccak256,
|
|
32
|
+
toBeHex
|
|
33
|
+
} from "ethers";
|
|
34
|
+
import {
|
|
35
|
+
ReceivingAddress,
|
|
36
|
+
computeWalletAuthorizationDigest,
|
|
37
|
+
decodeAddress,
|
|
38
|
+
walletAuthorizationTypedData
|
|
39
|
+
} from "@invisi-labs/core";
|
|
40
|
+
var MAX_NONCE = (1n << 64n) - 1n;
|
|
41
|
+
var MASK128 = (1n << 128n) - 1n;
|
|
42
|
+
function uint64(value, name) {
|
|
43
|
+
if (typeof value !== "bigint" || value < 0n || value > MAX_NONCE)
|
|
44
|
+
throw new RangeError(`${name} must be uint64`);
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
function hexBytes(value, length) {
|
|
48
|
+
if (typeof value !== "string" || !isHexString(value) || value.length !== 2 + length * 2)
|
|
49
|
+
throw new Error(`Expected ${length} hexadecimal bytes`);
|
|
50
|
+
return getBytes(value);
|
|
51
|
+
}
|
|
52
|
+
function normalizeKeys(walletIdentity, keys) {
|
|
53
|
+
const decoded = decodeAddress(
|
|
54
|
+
ReceivingAddress.from({
|
|
55
|
+
walletIdentity,
|
|
56
|
+
viewingPublicKey: hexBytes(keys.viewingPublicKey, 33),
|
|
57
|
+
clueKey: hexBytes(keys.clueKey, 32)
|
|
58
|
+
}).toString()
|
|
59
|
+
);
|
|
60
|
+
if (decoded.kind !== "long") throw new Error("Expected full receiving address");
|
|
61
|
+
return {
|
|
62
|
+
viewingPublicKey: hexlify(decoded.viewingPublicKey),
|
|
63
|
+
clueKey: hexlify(decoded.clueKey)
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
function normalize(context, registration, options) {
|
|
67
|
+
uint64(context.chainId, "chainId");
|
|
68
|
+
const registryAddress = getAddress(context.registryAddress);
|
|
69
|
+
if (BigInt(registryAddress) === 0n) throw new Error("Registry address must be nonzero");
|
|
70
|
+
const walletIdentity = decodeAddress(
|
|
71
|
+
ReceivingAddress.fromIdentity(registration.walletIdentity).toString()
|
|
72
|
+
).walletIdentity;
|
|
73
|
+
const keys = normalizeKeys(walletIdentity, registration.keys);
|
|
74
|
+
const nonce = uint64(registration.nonce, "nonce"), deadline = uint64(registration.deadline, "deadline");
|
|
75
|
+
if (nonce === MAX_NONCE) throw new Error("Registry nonce exhausted");
|
|
76
|
+
if (options.update !== void 0 && typeof options.update !== "boolean")
|
|
77
|
+
throw new TypeError("update must be boolean");
|
|
78
|
+
if (!options.update && nonce !== 0n)
|
|
79
|
+
throw new Error("Initial registration requires nonce zero");
|
|
80
|
+
if (options.expectedNonce !== void 0 && uint64(options.expectedNonce, "expectedNonce") !== nonce)
|
|
81
|
+
throw new Error("Registry nonce mismatch");
|
|
82
|
+
if (context.now !== void 0 && deadline < uint64(context.now, "now"))
|
|
83
|
+
throw new Error("Registration expired");
|
|
84
|
+
return { registryAddress, registration: { walletIdentity, keys, nonce, deadline } };
|
|
85
|
+
}
|
|
86
|
+
function registrationAuthorizationRequest(context, registration, options = {}) {
|
|
87
|
+
const normalized = normalize(context, registration, options), r = normalized.registration;
|
|
88
|
+
const keysHash = BigInt(
|
|
89
|
+
keccak256(concat([r.keys.viewingPublicKey, r.keys.clueKey]))
|
|
90
|
+
);
|
|
91
|
+
return {
|
|
92
|
+
context: { chainId: context.chainId, protocolAddress: BigInt(normalized.registryAddress) },
|
|
93
|
+
operation: options.update ? "update-address" : "register-address",
|
|
94
|
+
capacity: 0,
|
|
95
|
+
words: [
|
|
96
|
+
context.chainId,
|
|
97
|
+
BigInt(normalized.registryAddress),
|
|
98
|
+
BigInt(r.walletIdentity),
|
|
99
|
+
r.nonce,
|
|
100
|
+
r.deadline,
|
|
101
|
+
keysHash >> 128n,
|
|
102
|
+
keysHash & MASK128
|
|
103
|
+
]
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
function registrationTypedData(context, registration, options = {}) {
|
|
107
|
+
return walletAuthorizationTypedData(
|
|
108
|
+
registrationAuthorizationRequest(context, registration, options)
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
function registrationPublicInputs(context, registration, options = {}) {
|
|
112
|
+
const request = registrationAuthorizationRequest(context, registration, options);
|
|
113
|
+
const digest = BigInt(computeWalletAuthorizationDigest(request));
|
|
114
|
+
return [
|
|
115
|
+
toBeHex(request.words[2], 32),
|
|
116
|
+
toBeHex(digest >> 128n, 32),
|
|
117
|
+
toBeHex(digest & MASK128, 32)
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
function buildRegistrationCalldata(context, registration, proof, options = {}) {
|
|
121
|
+
const normalized = normalize(context, registration, options);
|
|
122
|
+
if (typeof proof !== "string" || !isHexString(proof) || proof.length <= 2 || proof.length % 2 !== 0)
|
|
123
|
+
throw new Error("Registration proof must be nonempty hexadecimal bytes");
|
|
124
|
+
return {
|
|
125
|
+
to: normalized.registryAddress,
|
|
126
|
+
value: 0n,
|
|
127
|
+
callData: new Interface(invisiAddressRegistryAbi).encodeFunctionData(
|
|
128
|
+
options.update ? "updateKeys" : "registerKeys",
|
|
129
|
+
[
|
|
130
|
+
{
|
|
131
|
+
...normalized.registration,
|
|
132
|
+
walletIdentity: toBeHex(BigInt(normalized.registration.walletIdentity), 32)
|
|
133
|
+
},
|
|
134
|
+
proof
|
|
135
|
+
]
|
|
136
|
+
),
|
|
137
|
+
publicInputs: registrationPublicInputs(context, normalized.registration, options)
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
function createRegistryReceivingKeyLookup(client, registryAddress) {
|
|
141
|
+
const address = getAddress(registryAddress);
|
|
142
|
+
if (BigInt(address) === 0n) throw new Error("Registry address must be nonzero");
|
|
143
|
+
return async (walletIdentity) => {
|
|
144
|
+
const identity = decodeAddress(
|
|
145
|
+
ReceivingAddress.fromIdentity(walletIdentity).toString()
|
|
146
|
+
).walletIdentity;
|
|
147
|
+
const [keys, nonce] = await new Contract(
|
|
148
|
+
address,
|
|
149
|
+
invisiAddressRegistryAbi,
|
|
150
|
+
client
|
|
151
|
+
).getFunction("receivingKeysOf")(toBeHex(BigInt(identity), 32));
|
|
152
|
+
uint64(nonce, "registry nonce");
|
|
153
|
+
const normalized = normalizeKeys(identity, keys);
|
|
154
|
+
return {
|
|
155
|
+
viewingPublicKey: getBytes(normalized.viewingPublicKey),
|
|
156
|
+
clueKey: getBytes(normalized.clueKey)
|
|
157
|
+
};
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// src/witness.ts
|
|
162
|
+
import {
|
|
163
|
+
computeCreditCommitment,
|
|
164
|
+
computeCreditNullifier,
|
|
165
|
+
computeCreditSharedKeyHash,
|
|
166
|
+
computeNoteCommitment as computeNoteCommitment2,
|
|
167
|
+
computeNoteIdentity,
|
|
168
|
+
computeNoteNullifier,
|
|
169
|
+
computeWalletAuthorizationDigest as computeWalletAuthorizationDigest4,
|
|
170
|
+
normalizeCreditDeliveryState,
|
|
171
|
+
poseidonHash,
|
|
172
|
+
verifyWalletAuthorization
|
|
173
|
+
} from "@invisi-labs/core";
|
|
174
|
+
import {
|
|
175
|
+
LocalWitness
|
|
176
|
+
} from "@invisi-labs/prover";
|
|
177
|
+
|
|
178
|
+
// src/credit-create.ts
|
|
179
|
+
import {
|
|
180
|
+
AbiCoder as AbiCoder2,
|
|
181
|
+
dataLength as dataLength2,
|
|
182
|
+
getAddress as getAddress3,
|
|
183
|
+
Interface as Interface2,
|
|
184
|
+
isHexString as isHexString3,
|
|
185
|
+
keccak256 as keccak2563,
|
|
186
|
+
ParamType as ParamType2
|
|
187
|
+
} from "ethers";
|
|
188
|
+
import { computeWalletAuthorizationDigest as computeWalletAuthorizationDigest2, walletAuthorizationTypedData as walletAuthorizationTypedData2 } from "@invisi-labs/core";
|
|
189
|
+
|
|
190
|
+
// src/validation.ts
|
|
191
|
+
import {
|
|
192
|
+
AbiCoder,
|
|
193
|
+
dataLength,
|
|
194
|
+
getAddress as getAddress2,
|
|
195
|
+
isHexString as isHexString2,
|
|
196
|
+
keccak256 as keccak2562,
|
|
197
|
+
ParamType,
|
|
198
|
+
toBeHex as toBeHex2
|
|
199
|
+
} from "ethers";
|
|
200
|
+
var FIELD_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
201
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
202
|
+
var ZERO_WORD = toBeHex2(0n, 32);
|
|
203
|
+
var EMPTY_PERMIT = {
|
|
204
|
+
deadline: 0n,
|
|
205
|
+
v: 0,
|
|
206
|
+
r: ZERO_WORD,
|
|
207
|
+
s: ZERO_WORD
|
|
208
|
+
};
|
|
209
|
+
var EMPTY_FUNDING = {
|
|
210
|
+
payer: ZERO_ADDRESS,
|
|
211
|
+
amount: 0n,
|
|
212
|
+
sigNonce: 0n,
|
|
213
|
+
deadline: 0n,
|
|
214
|
+
signature: "0x",
|
|
215
|
+
permit: EMPTY_PERMIT
|
|
216
|
+
};
|
|
217
|
+
function uint(v, bits, name = "value") {
|
|
218
|
+
if (typeof v !== "bigint" && typeof v !== "number" && typeof v !== "string" || typeof v === "number" && !Number.isSafeInteger(v))
|
|
219
|
+
throw new Error(`${name} must be an integer`);
|
|
220
|
+
const n = BigInt(v);
|
|
221
|
+
if (n < 0n || n >= 1n << BigInt(bits)) throw new Error(`${name} exceeds u${bits}`);
|
|
222
|
+
return n;
|
|
223
|
+
}
|
|
224
|
+
function field(v, name = "field") {
|
|
225
|
+
const n = uint(v, 256, name);
|
|
226
|
+
if (n >= FIELD_MODULUS) throw new Error(`${name} is noncanonical field`);
|
|
227
|
+
return n;
|
|
228
|
+
}
|
|
229
|
+
var word = (v) => toBeHex2(typeof v === "bigint" ? v : BigInt(v), 32);
|
|
230
|
+
function dense(v, name) {
|
|
231
|
+
if (!Array.isArray(v)) throw new Error(`${name} must be array`);
|
|
232
|
+
for (let i = 0; i < v.length; i++)
|
|
233
|
+
if (!Object.hasOwn(v, i) || v[i] === void 0 || v[i] === null)
|
|
234
|
+
throw new Error(`${name} has missing or sparse entries`);
|
|
235
|
+
return v;
|
|
236
|
+
}
|
|
237
|
+
function known(v, keys, name = "params") {
|
|
238
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || Object.keys(v).some((k) => !keys.includes(k)))
|
|
239
|
+
throw new Error(`${name} has unsupported fields`);
|
|
240
|
+
}
|
|
241
|
+
function notes(v, name) {
|
|
242
|
+
const r = dense(v, name).map((v2) => word(field(v2, name)));
|
|
243
|
+
if (r.some((v2) => BigInt(v2) === 0n) || new Set(r).size !== r.length)
|
|
244
|
+
throw new Error(`duplicate or zero ${name}`);
|
|
245
|
+
return r;
|
|
246
|
+
}
|
|
247
|
+
function envelope(v, length, version) {
|
|
248
|
+
if (!isHexString2(v) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(v) || dataLength(v) !== length)
|
|
249
|
+
throw new Error(`ciphertext must be ${length} bytes`);
|
|
250
|
+
if (version !== void 0 && Number.parseInt(v.slice(2, 4), 16) !== version)
|
|
251
|
+
throw new Error("unsupported ciphertext envelope version");
|
|
252
|
+
return v;
|
|
253
|
+
}
|
|
254
|
+
function normalizeContext(c) {
|
|
255
|
+
return {
|
|
256
|
+
...c,
|
|
257
|
+
chainId: uint(c.chainId, 64, "chainId"),
|
|
258
|
+
protocolAddress: getAddress2(c.protocolAddress),
|
|
259
|
+
tokenAddress: getAddress2(c.tokenAddress)
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function checkDeadline(c, value) {
|
|
263
|
+
const n = uint(value, 64, "deadline");
|
|
264
|
+
if (c.now !== void 0 && n < uint(c.now, 64, "now")) throw new Error("deadline has expired");
|
|
265
|
+
return n;
|
|
266
|
+
}
|
|
267
|
+
function normalizeSources(sources, inputCount, capacity) {
|
|
268
|
+
dense(sources, "sources");
|
|
269
|
+
if (inputCount < 0 || inputCount > capacity || sources.length > inputCount || (inputCount === 0 ? sources.length !== 0 : sources.length === 0))
|
|
270
|
+
throw new Error("source count must be 1..inputCount, or empty for zero inputs");
|
|
271
|
+
let previous = 0n;
|
|
272
|
+
return sources.map((s) => {
|
|
273
|
+
known(s, ["treeId", "merkleRoot"], "source");
|
|
274
|
+
const treeId = uint(s.treeId, 64, "treeId"), merkleRoot = word(field(s.merkleRoot, "merkleRoot"));
|
|
275
|
+
if (treeId === 0n || treeId <= previous || BigInt(merkleRoot) === 0n)
|
|
276
|
+
throw new Error("sources must have positive roots and strictly ascending tree IDs");
|
|
277
|
+
previous = treeId;
|
|
278
|
+
return { treeId, merkleRoot };
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
var pad = (v, n) => [
|
|
282
|
+
...v,
|
|
283
|
+
...Array(n - v.length).fill(0n)
|
|
284
|
+
];
|
|
285
|
+
function normalizeDelivery(value, options = {}) {
|
|
286
|
+
known(value, ["ciphertext", "clue"], "delivery");
|
|
287
|
+
if (options.empty) {
|
|
288
|
+
if (value.ciphertext !== "0x" || value.clue !== "0x")
|
|
289
|
+
throw new Error("absent output requires an empty delivery");
|
|
290
|
+
return { ciphertext: "0x", clue: "0x" };
|
|
291
|
+
}
|
|
292
|
+
const ciphertext = envelope(
|
|
293
|
+
value.ciphertext,
|
|
294
|
+
options.credit ? 400 : 158,
|
|
295
|
+
options.credit ? 3 : 1
|
|
296
|
+
);
|
|
297
|
+
const clue = envelope(value.clue, 68);
|
|
298
|
+
if (clue.slice(130, 132).toLowerCase() !== "18") throw new Error("clue precision must be 24");
|
|
299
|
+
return { ciphertext, clue };
|
|
300
|
+
}
|
|
301
|
+
var deliveriesHash = (v) => keccak2562(
|
|
302
|
+
AbiCoder.defaultAbiCoder().encode(
|
|
303
|
+
[
|
|
304
|
+
{
|
|
305
|
+
type: "tuple[]",
|
|
306
|
+
components: [
|
|
307
|
+
{ name: "ciphertext", type: "bytes" },
|
|
308
|
+
{ name: "clue", type: "bytes" }
|
|
309
|
+
]
|
|
310
|
+
}
|
|
311
|
+
].map((parameter) => ParamType.from(parameter)),
|
|
312
|
+
[dense(v, "deliveries")]
|
|
313
|
+
)
|
|
314
|
+
);
|
|
315
|
+
function normalizeFunding(input = {}) {
|
|
316
|
+
const f = { ...EMPTY_FUNDING, ...input };
|
|
317
|
+
getAddress2(f.payer);
|
|
318
|
+
uint(f.amount, 128, "depositAmount");
|
|
319
|
+
uint(f.sigNonce, 256, "sigNonce");
|
|
320
|
+
uint(f.deadline, 256, "funding deadline");
|
|
321
|
+
if (!isHexString2(f.signature) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(f.signature))
|
|
322
|
+
throw new Error("invalid signature bytes");
|
|
323
|
+
const p = f.permit;
|
|
324
|
+
uint(p.deadline, 256);
|
|
325
|
+
uint(p.v, 8);
|
|
326
|
+
for (const v of [p.r, p.s])
|
|
327
|
+
if (!isHexString2(v) || dataLength(v) !== 32) throw new Error("permit r/s must be bytes32");
|
|
328
|
+
if (f.amount === 0n !== (BigInt(f.payer) === 0n))
|
|
329
|
+
throw new Error("deposit amount and payer must both be zero or positive");
|
|
330
|
+
if (f.amount === 0n && (f.sigNonce !== 0n || f.deadline !== 0n || f.signature !== "0x" || p.deadline !== 0n || p.v !== 0 || BigInt(p.r) !== 0n || BigInt(p.s) !== 0n))
|
|
331
|
+
throw new Error("zero funding must be entirely empty");
|
|
332
|
+
return { ...f, payer: getAddress2(f.payer) };
|
|
333
|
+
}
|
|
334
|
+
function validateFundingSubmission(f, caller, now) {
|
|
335
|
+
if (f.signature !== "0x" && now !== void 0 && uint(now, 64, "now") > f.deadline)
|
|
336
|
+
throw new Error("funding authorization has expired");
|
|
337
|
+
if (f.signature === "0x" && (f.sigNonce !== 0n || f.deadline !== 0n || caller !== void 0 && f.amount > 0n && getAddress2(caller) !== f.payer))
|
|
338
|
+
throw new Error("direct funding requires payer caller and zero nonce/deadline");
|
|
339
|
+
}
|
|
340
|
+
var getEIP712Domain = (c) => ({
|
|
341
|
+
name: "InvisibleProtocol",
|
|
342
|
+
version: "1",
|
|
343
|
+
chainId: uint(c.chainId, 64),
|
|
344
|
+
verifyingContract: getAddress2(c.protocolAddress)
|
|
345
|
+
});
|
|
346
|
+
var fundingFields = [
|
|
347
|
+
{ name: "requestHash", type: "bytes32" },
|
|
348
|
+
{ name: "payer", type: "address" },
|
|
349
|
+
{ name: "amount", type: "uint256" },
|
|
350
|
+
{ name: "sigNonce", type: "uint256" },
|
|
351
|
+
{ name: "deadline", type: "uint256" }
|
|
352
|
+
];
|
|
353
|
+
|
|
354
|
+
// src/credit-create.ts
|
|
355
|
+
var creationTuple = [
|
|
356
|
+
"(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline)"
|
|
357
|
+
][0];
|
|
358
|
+
var CREATE_CREDIT_FIELDS = [
|
|
359
|
+
"token",
|
|
360
|
+
"sources",
|
|
361
|
+
"nullifiers",
|
|
362
|
+
"creditCommitment",
|
|
363
|
+
"changeCommitment",
|
|
364
|
+
"owner",
|
|
365
|
+
"expiry",
|
|
366
|
+
"deadline"
|
|
367
|
+
];
|
|
368
|
+
function validateCreateCreditRequest(c, p, cs, funding = {}) {
|
|
369
|
+
known(p, CREATE_CREDIT_FIELDS);
|
|
370
|
+
if (getAddress3(p.token) !== getAddress3(c.tokenAddress))
|
|
371
|
+
throw new Error("request token mismatch");
|
|
372
|
+
const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), sources = normalizeSources(p.sources, ns.length, 10), creditCommitment = word(field(p.creditCommitment)), changeCommitment = word(field(p.changeCommitment)), owner = getAddress3(p.owner), expiry = uint(p.expiry, 64, "expiry"), deadline = checkDeadline(c, p.deadline), f = normalizeFunding(funding);
|
|
373
|
+
if (BigInt(creditCommitment) === 0n || creditCommitment === changeCommitment)
|
|
374
|
+
throw new Error("zero or duplicate commitment");
|
|
375
|
+
if (BigInt(owner) === 0n || expiry === 0n || c.now !== void 0 && expiry <= c.now)
|
|
376
|
+
throw new Error("owner must be nonzero and expiry future");
|
|
377
|
+
if (dense(cs, "deliveries").length !== 3) throw new Error("deliveries count mismatch");
|
|
378
|
+
const deliveries = cs.map(
|
|
379
|
+
(v, i) => normalizeDelivery(v, { credit: i < 2, empty: i === 2 && BigInt(changeCommitment) === 0n })
|
|
380
|
+
);
|
|
381
|
+
if (ns.length === 0 && f.amount === 0n)
|
|
382
|
+
throw new Error("empty inputs require positive funding");
|
|
383
|
+
return {
|
|
384
|
+
...ctx,
|
|
385
|
+
sources,
|
|
386
|
+
nullifiers: ns,
|
|
387
|
+
actualCount: ns.length,
|
|
388
|
+
sourceCount: sources.length,
|
|
389
|
+
creditCommitment,
|
|
390
|
+
changeCommitment,
|
|
391
|
+
owner,
|
|
392
|
+
expiry,
|
|
393
|
+
deadline,
|
|
394
|
+
deliveries,
|
|
395
|
+
funding: f
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
function createCreditBaseInputs(c, p, cs, f = {}) {
|
|
399
|
+
const r = validateCreateCreditRequest(c, p, cs, f), h = BigInt(deliveriesHash(cs));
|
|
400
|
+
return [
|
|
401
|
+
r.chainId,
|
|
402
|
+
BigInt(r.protocolAddress),
|
|
403
|
+
BigInt(r.tokenAddress),
|
|
404
|
+
BigInt(r.owner),
|
|
405
|
+
BigInt(r.actualCount),
|
|
406
|
+
BigInt(r.sourceCount),
|
|
407
|
+
...pad(
|
|
408
|
+
r.sources.map((s) => s.treeId),
|
|
409
|
+
10
|
|
410
|
+
),
|
|
411
|
+
...pad(
|
|
412
|
+
r.sources.map((s) => BigInt(s.merkleRoot)),
|
|
413
|
+
10
|
|
414
|
+
),
|
|
415
|
+
...pad(r.nullifiers.map(BigInt), 10),
|
|
416
|
+
BigInt(r.creditCommitment),
|
|
417
|
+
BigInt(r.changeCommitment),
|
|
418
|
+
h >> 128n,
|
|
419
|
+
h & (1n << 128n) - 1n,
|
|
420
|
+
r.expiry,
|
|
421
|
+
r.deadline,
|
|
422
|
+
r.funding.amount,
|
|
423
|
+
BigInt(r.funding.payer)
|
|
424
|
+
].map(word);
|
|
425
|
+
}
|
|
426
|
+
function createCreditPublicInputs(c, p, deliveries, funding = {}) {
|
|
427
|
+
const base = createCreditBaseInputs(c, p, deliveries, funding);
|
|
428
|
+
const digest = BigInt(
|
|
429
|
+
computeWalletAuthorizationDigest2({
|
|
430
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
431
|
+
operation: "create-credit",
|
|
432
|
+
capacity: 10,
|
|
433
|
+
words: base.map(BigInt)
|
|
434
|
+
})
|
|
435
|
+
);
|
|
436
|
+
return [...base, word(digest >> 128n), word(digest & (1n << 128n) - 1n)];
|
|
437
|
+
}
|
|
438
|
+
var hashContext = {
|
|
439
|
+
chainId: 0n,
|
|
440
|
+
protocolAddress: ZERO_ADDRESS,
|
|
441
|
+
tokenAddress: ZERO_ADDRESS
|
|
442
|
+
};
|
|
443
|
+
function createCreditRequestHash(p, cs, f = {}) {
|
|
444
|
+
const r = validateCreateCreditRequest({ ...hashContext, tokenAddress: p.token }, p, cs, f);
|
|
445
|
+
return keccak2563(
|
|
446
|
+
AbiCoder2.defaultAbiCoder().encode(
|
|
447
|
+
[
|
|
448
|
+
{ type: "bytes32" },
|
|
449
|
+
creationTuple,
|
|
450
|
+
{ type: "bytes32" },
|
|
451
|
+
{ type: "address" },
|
|
452
|
+
{ type: "uint256" }
|
|
453
|
+
].map((parameter) => ParamType2.from(parameter)),
|
|
454
|
+
[
|
|
455
|
+
keccak2563(new TextEncoder().encode("InvisiCreateCredit")),
|
|
456
|
+
p,
|
|
457
|
+
deliveriesHash(cs),
|
|
458
|
+
r.funding.payer,
|
|
459
|
+
r.funding.amount
|
|
460
|
+
]
|
|
461
|
+
)
|
|
462
|
+
);
|
|
463
|
+
}
|
|
464
|
+
function encodeCreateCreditTypedData(c, p, deliveries, funding = {}) {
|
|
465
|
+
return walletAuthorizationTypedData2({
|
|
466
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
467
|
+
operation: "create-credit",
|
|
468
|
+
capacity: 10,
|
|
469
|
+
words: createCreditBaseInputs(c, p, deliveries, funding).map(BigInt)
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
function encodeCreateCreditFundingTypedData(c, p, cs, f) {
|
|
473
|
+
const r = validateCreateCreditRequest(c, p, cs, f);
|
|
474
|
+
if (r.funding.amount === 0n) throw new Error("funding authorization requires positive deposit");
|
|
475
|
+
return {
|
|
476
|
+
domain: getEIP712Domain(c),
|
|
477
|
+
primaryType: "FundTransact",
|
|
478
|
+
types: { FundTransact: fundingFields },
|
|
479
|
+
message: {
|
|
480
|
+
requestHash: createCreditRequestHash(p, cs, f),
|
|
481
|
+
payer: r.funding.payer,
|
|
482
|
+
amount: r.funding.amount,
|
|
483
|
+
sigNonce: r.funding.sigNonce,
|
|
484
|
+
deadline: r.funding.deadline
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
function buildCreateCreditCalldata(p) {
|
|
489
|
+
const r = validateCreateCreditRequest(p.context, p.params, p.deliveries, p.funding);
|
|
490
|
+
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
491
|
+
return {
|
|
492
|
+
data: new Interface2(invisiProtocolAbi).encodeFunctionData("createCredit", [
|
|
493
|
+
encodeCreditProof(p.proof),
|
|
494
|
+
p.params,
|
|
495
|
+
p.deliveries,
|
|
496
|
+
r.funding
|
|
497
|
+
]),
|
|
498
|
+
approveAmount: r.funding.amount
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
function encodeCreditProof(proof) {
|
|
502
|
+
if (!isHexString3(proof) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(proof) || dataLength2(proof) === 0)
|
|
503
|
+
throw new Error("empty or malformed Credit proof");
|
|
504
|
+
return AbiCoder2.defaultAbiCoder().encode(
|
|
505
|
+
["uint8", "bytes"].map((parameter) => ParamType2.from(parameter)),
|
|
506
|
+
[0, proof]
|
|
507
|
+
);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
// src/credit-lifecycle.ts
|
|
511
|
+
import { AbiCoder as AbiCoder3, getAddress as getAddress4, Interface as Interface3, keccak256 as keccak2564, ParamType as ParamType3 } from "ethers";
|
|
512
|
+
import {
|
|
513
|
+
computeWalletAuthorizationDigest as computeWalletAuthorizationDigest3,
|
|
514
|
+
walletAuthorizationTypedData as walletAuthorizationTypedData3
|
|
515
|
+
} from "@invisi-labs/core";
|
|
516
|
+
var CREDIT_DRAW_CAPACITIES = [1, 12, 50, 120];
|
|
517
|
+
function selectCreditDrawCircuit(count) {
|
|
518
|
+
if (!Number.isInteger(count) || count < 1 || count > 120)
|
|
519
|
+
throw new Error("draw requires 1..120 credits");
|
|
520
|
+
const maxSize = CREDIT_DRAW_CAPACITIES.find((n) => count <= n);
|
|
521
|
+
return {
|
|
522
|
+
name: `credit_draw_slots${maxSize}`,
|
|
523
|
+
maxSize,
|
|
524
|
+
publicInputCount: 6 * maxSize + 12,
|
|
525
|
+
totalBits: 126 + Math.ceil(Math.log2(maxSize))
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
function validateCreditDrawRequest(c, p, cs) {
|
|
529
|
+
known(p, [
|
|
530
|
+
"token",
|
|
531
|
+
"sources",
|
|
532
|
+
"nullifiers",
|
|
533
|
+
"remainderCommitments",
|
|
534
|
+
"expiries",
|
|
535
|
+
"recoveryAmounts",
|
|
536
|
+
"spender",
|
|
537
|
+
"totalAmount",
|
|
538
|
+
"deadline"
|
|
539
|
+
]);
|
|
540
|
+
if (getAddress4(p.token) !== getAddress4(c.tokenAddress))
|
|
541
|
+
throw new Error("request token mismatch");
|
|
542
|
+
const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), profile = selectCreditDrawCircuit(ns.length), sources = normalizeSources(p.sources, ns.length, profile.maxSize);
|
|
543
|
+
for (const [key, v] of Object.entries({
|
|
544
|
+
remainderCommitments: p.remainderCommitments,
|
|
545
|
+
expiries: p.expiries,
|
|
546
|
+
recoveryAmounts: p.recoveryAmounts
|
|
547
|
+
}))
|
|
548
|
+
if (dense(v, key).length !== ns.length) throw new Error(`${key} count mismatch`);
|
|
549
|
+
const remainderCommitments = p.remainderCommitments.map((v) => word(field(v))), recoveryAmounts = p.recoveryAmounts.map((v) => word(field(v))), expiries = p.expiries.map((v) => uint(v, 64, "expiry")), positives = remainderCommitments.filter((v) => BigInt(v) !== 0n);
|
|
550
|
+
if (new Set(positives).size !== positives.length)
|
|
551
|
+
throw new Error("duplicate remainder commitment");
|
|
552
|
+
for (let i = 0; i < ns.length; i++) {
|
|
553
|
+
if (expiries[i] === 0n || c.now !== void 0 && expiries[i] <= c.now)
|
|
554
|
+
throw new Error("expiry must be future");
|
|
555
|
+
if (BigInt(remainderCommitments[i]) === 0n && BigInt(recoveryAmounts[i]) !== 0n)
|
|
556
|
+
throw new Error("full draw requires zero recovery amount");
|
|
557
|
+
}
|
|
558
|
+
const spender = getAddress4(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
|
|
559
|
+
if (BigInt(spender) === 0n || totalAmount === 0n)
|
|
560
|
+
throw new Error("spender and total amount must be positive");
|
|
561
|
+
if (dense(cs, "deliveries").length !== 2 * ns.length)
|
|
562
|
+
throw new Error("deliveries count mismatch");
|
|
563
|
+
const deliveries = cs.map(
|
|
564
|
+
(v, i) => BigInt(remainderCommitments[Math.floor(i / 2)]) === 0n ? normalizeDelivery(v, { empty: true }) : normalizeDelivery(v, { credit: true })
|
|
565
|
+
);
|
|
566
|
+
return {
|
|
567
|
+
...ctx,
|
|
568
|
+
sources,
|
|
569
|
+
nullifiers: ns,
|
|
570
|
+
remainderCommitments,
|
|
571
|
+
recoveryAmounts,
|
|
572
|
+
expiries,
|
|
573
|
+
spender,
|
|
574
|
+
totalAmount,
|
|
575
|
+
deadline: checkDeadline(c, p.deadline),
|
|
576
|
+
deliveries,
|
|
577
|
+
profile
|
|
578
|
+
};
|
|
579
|
+
}
|
|
580
|
+
function creditDrawBaseInputs(c, p, cs) {
|
|
581
|
+
const r = validateCreditDrawRequest(c, p, cs), n = r.profile.maxSize, h = BigInt(deliveriesHash(cs));
|
|
582
|
+
return [
|
|
583
|
+
r.chainId,
|
|
584
|
+
BigInt(r.protocolAddress),
|
|
585
|
+
BigInt(r.tokenAddress),
|
|
586
|
+
BigInt(r.spender),
|
|
587
|
+
BigInt(r.nullifiers.length),
|
|
588
|
+
BigInt(r.sources.length),
|
|
589
|
+
...pad(
|
|
590
|
+
r.sources.map((s) => s.treeId),
|
|
591
|
+
n
|
|
592
|
+
),
|
|
593
|
+
...pad(
|
|
594
|
+
r.sources.map((s) => BigInt(s.merkleRoot)),
|
|
595
|
+
n
|
|
596
|
+
),
|
|
597
|
+
...pad(r.nullifiers.map(BigInt), n),
|
|
598
|
+
...pad(r.remainderCommitments.map(BigInt), n),
|
|
599
|
+
...pad(r.expiries, n),
|
|
600
|
+
r.totalAmount,
|
|
601
|
+
r.deadline,
|
|
602
|
+
h >> 128n,
|
|
603
|
+
h & (1n << 128n) - 1n,
|
|
604
|
+
...pad(r.recoveryAmounts.map(BigInt), n)
|
|
605
|
+
].map(word);
|
|
606
|
+
}
|
|
607
|
+
function validateCancelCreditRequest(c, p) {
|
|
608
|
+
known(p, ["token", "source", "nullifier", "owner", "amount", "deadline"]);
|
|
609
|
+
if (getAddress4(p.token) !== getAddress4(c.tokenAddress))
|
|
610
|
+
throw new Error("request token mismatch");
|
|
611
|
+
const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = getAddress4(p.owner), amount = uint(p.amount, 126, "amount");
|
|
612
|
+
if (BigInt(owner) === 0n || amount === 0n) throw new Error("owner and amount must be positive");
|
|
613
|
+
return {
|
|
614
|
+
...ctx,
|
|
615
|
+
source,
|
|
616
|
+
nullifier,
|
|
617
|
+
owner,
|
|
618
|
+
amount,
|
|
619
|
+
deadline: checkDeadline(c, p.deadline)
|
|
620
|
+
};
|
|
621
|
+
}
|
|
622
|
+
function cancelCreditBaseInputs(c, p) {
|
|
623
|
+
const r = validateCancelCreditRequest(c, p);
|
|
624
|
+
return [
|
|
625
|
+
r.chainId,
|
|
626
|
+
BigInt(r.protocolAddress),
|
|
627
|
+
BigInt(r.tokenAddress),
|
|
628
|
+
BigInt(r.owner),
|
|
629
|
+
r.source.treeId,
|
|
630
|
+
BigInt(r.source.merkleRoot),
|
|
631
|
+
BigInt(r.nullifier),
|
|
632
|
+
r.amount,
|
|
633
|
+
r.deadline
|
|
634
|
+
].map(word);
|
|
635
|
+
}
|
|
636
|
+
function validateTopUpCreditRequest(c, p, cs, funding = {}) {
|
|
637
|
+
known(p, ["token", "creation", "creditSource", "creditNullifier", "previousExpiry"]);
|
|
638
|
+
const creation = validateCreateCreditRequest(c, p.creation, cs, funding), creditSource = normalizeSources([p.creditSource], 1, 1)[0], creditNullifier = notes([p.creditNullifier], "creditNullifier")[0], previousExpiry = uint(p.previousExpiry, 64, "previousExpiry");
|
|
639
|
+
if (previousExpiry === 0n || c.now !== void 0 && previousExpiry <= c.now)
|
|
640
|
+
throw new Error("previous Credit has expired");
|
|
641
|
+
if (creation.expiry < previousExpiry) throw new Error("expiry must not decrease");
|
|
642
|
+
if (creation.nullifiers.includes(creditNullifier))
|
|
643
|
+
throw new Error("duplicate credit and ordinary nullifier");
|
|
644
|
+
return { creation, creditSource, creditNullifier, previousExpiry };
|
|
645
|
+
}
|
|
646
|
+
function topUpCreditBaseInputs(c, p, cs, f = {}) {
|
|
647
|
+
const r = validateTopUpCreditRequest(c, p, cs, f);
|
|
648
|
+
return [
|
|
649
|
+
...createCreditBaseInputs(c, p.creation, cs, f),
|
|
650
|
+
word(r.creditSource.treeId),
|
|
651
|
+
r.creditSource.merkleRoot,
|
|
652
|
+
r.creditNullifier,
|
|
653
|
+
word(r.previousExpiry)
|
|
654
|
+
];
|
|
655
|
+
}
|
|
656
|
+
var cancelTuple = [
|
|
657
|
+
"(address token,(uint256 treeId,bytes32 merkleRoot) source,bytes32 nullifier,address owner,uint256 amount,uint256 deadline)"
|
|
658
|
+
][0];
|
|
659
|
+
var topTuple = [
|
|
660
|
+
"((address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32 creditCommitment,bytes32 changeCommitment,address owner,uint256 expiry,uint256 deadline) creation,(uint256 treeId,bytes32 merkleRoot) creditSource,bytes32 creditNullifier,uint256 previousExpiry)"
|
|
661
|
+
][0];
|
|
662
|
+
var hashContext2 = {
|
|
663
|
+
chainId: 0n,
|
|
664
|
+
protocolAddress: ZERO_ADDRESS,
|
|
665
|
+
tokenAddress: ZERO_ADDRESS
|
|
666
|
+
};
|
|
667
|
+
function cancelCreditRequestHash(p) {
|
|
668
|
+
validateCancelCreditRequest({ ...hashContext2, tokenAddress: p.token }, p);
|
|
669
|
+
return keccak2564(
|
|
670
|
+
AbiCoder3.defaultAbiCoder().encode(
|
|
671
|
+
[{ type: "bytes32" }, cancelTuple].map((parameter) => ParamType3.from(parameter)),
|
|
672
|
+
[keccak2564(new TextEncoder().encode("InvisiCancelCredit")), p]
|
|
673
|
+
)
|
|
674
|
+
);
|
|
675
|
+
}
|
|
676
|
+
function topUpCreditRequestHash(p, cs, f = {}) {
|
|
677
|
+
const r = validateTopUpCreditRequest(
|
|
678
|
+
{ ...hashContext2, tokenAddress: p.creation.token },
|
|
679
|
+
p,
|
|
680
|
+
cs,
|
|
681
|
+
f
|
|
682
|
+
);
|
|
683
|
+
return keccak2564(
|
|
684
|
+
AbiCoder3.defaultAbiCoder().encode(
|
|
685
|
+
[
|
|
686
|
+
{ type: "bytes32" },
|
|
687
|
+
topTuple,
|
|
688
|
+
{ type: "bytes32" },
|
|
689
|
+
{ type: "address" },
|
|
690
|
+
{ type: "uint256" }
|
|
691
|
+
].map((parameter) => ParamType3.from(parameter)),
|
|
692
|
+
[
|
|
693
|
+
keccak2564(new TextEncoder().encode("InvisiTopUpCredit")),
|
|
694
|
+
p,
|
|
695
|
+
deliveriesHash(cs),
|
|
696
|
+
r.creation.funding.payer,
|
|
697
|
+
r.creation.funding.amount
|
|
698
|
+
]
|
|
699
|
+
)
|
|
700
|
+
);
|
|
701
|
+
}
|
|
702
|
+
function authorize(c, operation, capacity, words) {
|
|
703
|
+
return walletAuthorizationTypedData3({
|
|
704
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
705
|
+
operation,
|
|
706
|
+
capacity,
|
|
707
|
+
words: words.map(BigInt)
|
|
708
|
+
});
|
|
709
|
+
}
|
|
710
|
+
function appendDigest(c, operation, capacity, words) {
|
|
711
|
+
const digest = BigInt(
|
|
712
|
+
computeWalletAuthorizationDigest3({
|
|
713
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
714
|
+
operation,
|
|
715
|
+
capacity,
|
|
716
|
+
words: words.map(BigInt)
|
|
717
|
+
})
|
|
718
|
+
);
|
|
719
|
+
return [...words, word(digest >> 128n), word(digest & (1n << 128n) - 1n)];
|
|
720
|
+
}
|
|
721
|
+
function encodeCancelCreditTypedData(c, p) {
|
|
722
|
+
return authorize(c, "cancel-credit", 1, cancelCreditBaseInputs(c, p));
|
|
723
|
+
}
|
|
724
|
+
function encodeTopUpCreditTypedData(c, p, deliveries, funding = {}) {
|
|
725
|
+
return authorize(c, "top-up-credit", 10, topUpCreditBaseInputs(c, p, deliveries, funding));
|
|
726
|
+
}
|
|
727
|
+
function encodeCreditDrawTypedData(c, p, deliveries) {
|
|
728
|
+
return authorize(
|
|
729
|
+
c,
|
|
730
|
+
"credit-draw",
|
|
731
|
+
selectCreditDrawCircuit(p.nullifiers.length).maxSize,
|
|
732
|
+
creditDrawBaseInputs(c, p, deliveries)
|
|
733
|
+
);
|
|
734
|
+
}
|
|
735
|
+
function creditDrawPublicInputs(c, p, deliveries) {
|
|
736
|
+
return appendDigest(
|
|
737
|
+
c,
|
|
738
|
+
"credit-draw",
|
|
739
|
+
selectCreditDrawCircuit(p.nullifiers.length).maxSize,
|
|
740
|
+
creditDrawBaseInputs(c, p, deliveries)
|
|
741
|
+
);
|
|
742
|
+
}
|
|
743
|
+
function cancelCreditPublicInputs(c, p) {
|
|
744
|
+
return appendDigest(c, "cancel-credit", 1, cancelCreditBaseInputs(c, p));
|
|
745
|
+
}
|
|
746
|
+
function topUpCreditPublicInputs(c, p, deliveries, funding = {}) {
|
|
747
|
+
return appendDigest(c, "top-up-credit", 10, topUpCreditBaseInputs(c, p, deliveries, funding));
|
|
748
|
+
}
|
|
749
|
+
function encodeTopUpCreditFundingTypedData(c, p, cs, f) {
|
|
750
|
+
const r = validateTopUpCreditRequest(c, p, cs, f), funding = r.creation.funding;
|
|
751
|
+
if (funding.amount === 0n) throw new Error("funding authorization requires positive deposit");
|
|
752
|
+
return {
|
|
753
|
+
domain: getEIP712Domain(c),
|
|
754
|
+
primaryType: "FundTransact",
|
|
755
|
+
types: { FundTransact: fundingFields },
|
|
756
|
+
message: {
|
|
757
|
+
requestHash: topUpCreditRequestHash(p, cs, f),
|
|
758
|
+
payer: funding.payer,
|
|
759
|
+
amount: funding.amount,
|
|
760
|
+
sigNonce: funding.sigNonce,
|
|
761
|
+
deadline: funding.deadline
|
|
762
|
+
}
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
function buildCreditDrawCalldata(p) {
|
|
766
|
+
validateCreditDrawRequest(p.context, p.params, p.deliveries);
|
|
767
|
+
return {
|
|
768
|
+
data: new Interface3(invisiProtocolAbi).encodeFunctionData("creditDraw", [
|
|
769
|
+
encodeCreditProof(p.proof),
|
|
770
|
+
p.params,
|
|
771
|
+
p.deliveries
|
|
772
|
+
]),
|
|
773
|
+
nullifiers: p.params.nullifiers,
|
|
774
|
+
totalAmount: p.params.totalAmount
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
function buildCancelCreditCalldata(p) {
|
|
778
|
+
validateCancelCreditRequest(p.context, p.params);
|
|
779
|
+
return {
|
|
780
|
+
data: new Interface3(invisiProtocolAbi).encodeFunctionData("cancelCredit", [
|
|
781
|
+
encodeCreditProof(p.proof),
|
|
782
|
+
p.params
|
|
783
|
+
])
|
|
784
|
+
};
|
|
785
|
+
}
|
|
786
|
+
function buildTopUpCreditCalldata(p) {
|
|
787
|
+
const r = validateTopUpCreditRequest(p.context, p.params, p.deliveries, p.funding);
|
|
788
|
+
validateFundingSubmission(r.creation.funding, p.caller, p.context.now);
|
|
789
|
+
return {
|
|
790
|
+
data: new Interface3(invisiProtocolAbi).encodeFunctionData("topUpCredit", [
|
|
791
|
+
encodeCreditProof(p.proof),
|
|
792
|
+
p.params,
|
|
793
|
+
p.deliveries,
|
|
794
|
+
r.creation.funding
|
|
795
|
+
]),
|
|
796
|
+
approveAmount: r.creation.funding.amount
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
// src/funds.ts
|
|
801
|
+
import { AbiCoder as AbiCoder4, getAddress as getAddress5, Interface as Interface4, keccak256 as keccak2565, ParamType as ParamType4, TypedDataEncoder } from "ethers";
|
|
802
|
+
import { computeNoteCommitment, walletAuthorizationTypedData as walletAuthorizationTypedData4 } from "@invisi-labs/core";
|
|
803
|
+
var TRANSACT_CAPACITIES = [14, 56, 112, 168];
|
|
804
|
+
function selectTransactCapacity(inputs, outputs) {
|
|
805
|
+
if (!Number.isInteger(inputs) || !Number.isInteger(outputs) || inputs < 0 || outputs < 0 || inputs + outputs < 1 || inputs === 0 && outputs < 2 || inputs + outputs > 168)
|
|
806
|
+
throw new Error("unsupported transact shape");
|
|
807
|
+
return TRANSACT_CAPACITIES.find((n) => inputs + outputs <= n);
|
|
808
|
+
}
|
|
809
|
+
function normalizeTransactRequest(c, p, cs, funding = {}) {
|
|
810
|
+
const ctx = normalizeContext(c);
|
|
811
|
+
if (getAddress5(p.token) !== ctx.tokenAddress)
|
|
812
|
+
throw new Error("request token mismatch");
|
|
813
|
+
known(p, [
|
|
814
|
+
"token",
|
|
815
|
+
"sources",
|
|
816
|
+
"nullifiers",
|
|
817
|
+
"outputCommitments",
|
|
818
|
+
"withdrawalAddress",
|
|
819
|
+
"withdrawalAmount",
|
|
820
|
+
"deadline"
|
|
821
|
+
]);
|
|
822
|
+
const ns = notes(p.nullifiers, "nullifiers"), os = notes(p.outputCommitments, "outputCommitments"), capacity = selectTransactCapacity(ns.length, os.length);
|
|
823
|
+
const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map((v) => normalizeDelivery(v));
|
|
824
|
+
if (deliveries.length !== os.length) throw new Error("deliveries count mismatch");
|
|
825
|
+
const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = getAddress5(p.withdrawalAddress), f = normalizeFunding(funding);
|
|
826
|
+
if (withdrawalAmount === 0n !== (BigInt(withdrawalAddress) === 0n) || os.length === 0 && withdrawalAmount === 0n)
|
|
827
|
+
throw new Error("invalid withdrawal");
|
|
828
|
+
if (ns.length === 0 && (f.amount === 0n || withdrawalAmount !== 0n))
|
|
829
|
+
throw new Error("zero inputs require positive funding and zero withdrawal");
|
|
830
|
+
return {
|
|
831
|
+
...ctx,
|
|
832
|
+
capacity,
|
|
833
|
+
sources,
|
|
834
|
+
nullifiers: ns,
|
|
835
|
+
outputCommitments: os,
|
|
836
|
+
inputCount: ns.length,
|
|
837
|
+
outputCount: os.length,
|
|
838
|
+
sourceCount: sources.length,
|
|
839
|
+
inputTreeIds: pad(
|
|
840
|
+
sources.map((s) => s.treeId),
|
|
841
|
+
capacity
|
|
842
|
+
),
|
|
843
|
+
merkleRoots: pad(
|
|
844
|
+
sources.map((s) => BigInt(s.merkleRoot)),
|
|
845
|
+
capacity
|
|
846
|
+
),
|
|
847
|
+
slotValues: pad([...ns, ...os].map(BigInt), capacity),
|
|
848
|
+
deliveries,
|
|
849
|
+
deliveriesHash: deliveriesHash(deliveries),
|
|
850
|
+
withdrawalAddress,
|
|
851
|
+
withdrawalAmount,
|
|
852
|
+
deadline: checkDeadline(c, p.deadline),
|
|
853
|
+
depositAmount: f.amount,
|
|
854
|
+
depositPayer: f.payer,
|
|
855
|
+
funding: f
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
function transactPublicInputs(c, p, cs, f = {}) {
|
|
859
|
+
const r = normalizeTransactRequest(c, p, cs, f), h = BigInt(r.deliveriesHash);
|
|
860
|
+
return [
|
|
861
|
+
r.chainId,
|
|
862
|
+
BigInt(r.protocolAddress),
|
|
863
|
+
BigInt(r.tokenAddress),
|
|
864
|
+
BigInt(r.inputCount),
|
|
865
|
+
BigInt(r.outputCount),
|
|
866
|
+
BigInt(r.sourceCount),
|
|
867
|
+
...r.inputTreeIds,
|
|
868
|
+
...r.merkleRoots,
|
|
869
|
+
...r.slotValues,
|
|
870
|
+
h >> 128n,
|
|
871
|
+
h & (1n << 128n) - 1n,
|
|
872
|
+
BigInt(r.withdrawalAddress),
|
|
873
|
+
r.withdrawalAmount,
|
|
874
|
+
r.deadline,
|
|
875
|
+
r.depositAmount,
|
|
876
|
+
BigInt(r.depositPayer)
|
|
877
|
+
].map(word);
|
|
878
|
+
}
|
|
879
|
+
function encodeTransactTypedData(c, p, deliveries, f = {}) {
|
|
880
|
+
const r = normalizeTransactRequest(c, p, deliveries, f);
|
|
881
|
+
return walletAuthorizationTypedData4({
|
|
882
|
+
context: { chainId: r.chainId, protocolAddress: BigInt(r.protocolAddress) },
|
|
883
|
+
operation: "transact",
|
|
884
|
+
capacity: r.capacity,
|
|
885
|
+
words: transactPublicInputs(c, p, deliveries, f).map(BigInt)
|
|
886
|
+
});
|
|
887
|
+
}
|
|
888
|
+
var singleTuple = [
|
|
889
|
+
"(address token,bytes32 merkleRoot,bytes32[] nullifiers,bytes32[] outputCommitments,uint256 inputTreeId,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline)"
|
|
890
|
+
][0];
|
|
891
|
+
var crossTuple = [
|
|
892
|
+
"(address token,(uint256 treeId,bytes32 merkleRoot)[] sources,bytes32[] nullifiers,bytes32[] outputCommitments,address withdrawalAddress,uint256 withdrawalAmount,uint256 deadline)"
|
|
893
|
+
][0];
|
|
894
|
+
function transactFundingRequestHash(proof, p, cs) {
|
|
895
|
+
const single = {
|
|
896
|
+
token: p.token,
|
|
897
|
+
merkleRoot: p.sources[0]?.merkleRoot ?? word(0n),
|
|
898
|
+
nullifiers: p.nullifiers,
|
|
899
|
+
outputCommitments: p.outputCommitments,
|
|
900
|
+
inputTreeId: p.sources[0]?.treeId ?? 0n,
|
|
901
|
+
withdrawalAddress: p.withdrawalAddress,
|
|
902
|
+
withdrawalAmount: p.withdrawalAmount,
|
|
903
|
+
deadline: p.deadline
|
|
904
|
+
};
|
|
905
|
+
return p.sources.length > 1 ? keccak2565(
|
|
906
|
+
AbiCoder4.defaultAbiCoder().encode(
|
|
907
|
+
[{ type: "bytes32" }, { type: "bytes32" }, crossTuple, { type: "bytes32" }].map(
|
|
908
|
+
(parameter) => ParamType4.from(parameter)
|
|
909
|
+
),
|
|
910
|
+
[
|
|
911
|
+
keccak2565(new TextEncoder().encode("InvisiCrossTreeTransact")),
|
|
912
|
+
keccak2565(proof),
|
|
913
|
+
p,
|
|
914
|
+
deliveriesHash(cs)
|
|
915
|
+
]
|
|
916
|
+
)
|
|
917
|
+
) : keccak2565(
|
|
918
|
+
AbiCoder4.defaultAbiCoder().encode(
|
|
919
|
+
[{ type: "bytes32" }, singleTuple, { type: "bytes32" }].map(
|
|
920
|
+
(parameter) => ParamType4.from(parameter)
|
|
921
|
+
),
|
|
922
|
+
[keccak2565(proof), single, deliveriesHash(cs)]
|
|
923
|
+
)
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
function encodeTransactFundingTypedData(c, proof, p, cs, funding) {
|
|
927
|
+
normalizeTransactRequest(c, p, cs, funding);
|
|
928
|
+
const f = normalizeFunding(funding);
|
|
929
|
+
if (f.amount === 0n) throw new Error("funding authorization requires positive deposit");
|
|
930
|
+
return {
|
|
931
|
+
domain: getEIP712Domain(c),
|
|
932
|
+
primaryType: "FundTransact",
|
|
933
|
+
types: { FundTransact: fundingFields },
|
|
934
|
+
message: {
|
|
935
|
+
requestHash: transactFundingRequestHash(proof, p, cs),
|
|
936
|
+
payer: f.payer,
|
|
937
|
+
amount: f.amount,
|
|
938
|
+
sigNonce: f.sigNonce,
|
|
939
|
+
deadline: f.deadline
|
|
940
|
+
}
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
function buildTransactCalldata(p) {
|
|
944
|
+
const r = normalizeTransactRequest(p.context, p.params, p.deliveries, p.funding);
|
|
945
|
+
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
946
|
+
const request = {
|
|
947
|
+
params: {
|
|
948
|
+
token: r.tokenAddress,
|
|
949
|
+
sources: r.sources,
|
|
950
|
+
nullifiers: r.nullifiers,
|
|
951
|
+
outputCommitments: r.outputCommitments,
|
|
952
|
+
withdrawalAddress: r.withdrawalAddress,
|
|
953
|
+
withdrawalAmount: r.withdrawalAmount,
|
|
954
|
+
deadline: r.deadline
|
|
955
|
+
},
|
|
956
|
+
deliveries: p.deliveries,
|
|
957
|
+
funding: r.funding
|
|
958
|
+
};
|
|
959
|
+
const abi = invisiProtocolAbi.filter(
|
|
960
|
+
(item) => item.type === "function" && item.name === "transact" && item.inputs.length === 2 && item.inputs[1]?.type === "tuple"
|
|
961
|
+
);
|
|
962
|
+
const data = new Interface4(abi).encodeFunctionData("transact", [p.proof, request]);
|
|
963
|
+
return { data, capacity: r.capacity, approveAmount: r.depositAmount };
|
|
964
|
+
}
|
|
965
|
+
function buildTransactAggregateCalldata(p) {
|
|
966
|
+
if (![4, 8, 12].includes(dense(p.requests, "requests").length))
|
|
967
|
+
throw new Error("aggregate requires 4, 8 or 12 requests");
|
|
968
|
+
for (const request of p.requests) {
|
|
969
|
+
const r = normalizeTransactRequest(
|
|
970
|
+
{ ...p.context, tokenAddress: request.params.token },
|
|
971
|
+
request.params,
|
|
972
|
+
request.deliveries,
|
|
973
|
+
request.funding
|
|
974
|
+
);
|
|
975
|
+
if (r.capacity !== 14) throw new Error("aggregate supports only capacity 14");
|
|
976
|
+
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
977
|
+
}
|
|
978
|
+
return {
|
|
979
|
+
data: new Interface4(
|
|
980
|
+
invisiProtocolAbi.filter(
|
|
981
|
+
(item) => item.type === "function" && item.name === "transact" && item.inputs[1]?.type === "tuple[]"
|
|
982
|
+
)
|
|
983
|
+
).encodeFunctionData("transact", [p.proof, p.requests]),
|
|
984
|
+
capacity: 14
|
|
985
|
+
};
|
|
986
|
+
}
|
|
987
|
+
async function validateShieldRequest(p) {
|
|
988
|
+
normalizeContext(p.context);
|
|
989
|
+
if (getAddress5(p.params.token) !== getAddress5(p.context.tokenAddress))
|
|
990
|
+
throw new Error("request token mismatch");
|
|
991
|
+
known(p.params, ["token", "outputCommitments", "deadline"]);
|
|
992
|
+
checkDeadline(p.context, p.params.deadline);
|
|
993
|
+
const outputs = dense(p.outputs, "outputs"), commitments = notes(p.params.outputCommitments, "outputCommitments"), cs = dense(p.deliveries, "deliveries"), f = normalizeFunding(p.funding);
|
|
994
|
+
if (outputs.length < 1 || outputs.length > 10 || commitments.length !== outputs.length || cs.length !== outputs.length)
|
|
995
|
+
throw new Error("shield requires 1..10 outputs and matching deliveries");
|
|
996
|
+
let total = 0n;
|
|
997
|
+
for (const [i, o] of outputs.entries()) {
|
|
998
|
+
known(o, ["identity", "amount"], "output");
|
|
999
|
+
uint(o.amount, 128, "amount");
|
|
1000
|
+
if (o.amount === 0n) throw new Error("amount must be positive");
|
|
1001
|
+
field(o.identity);
|
|
1002
|
+
normalizeDelivery(cs[i]);
|
|
1003
|
+
if (await computeNoteCommitment(
|
|
1004
|
+
p.context.chainId,
|
|
1005
|
+
o.identity,
|
|
1006
|
+
BigInt(p.context.tokenAddress),
|
|
1007
|
+
o.amount
|
|
1008
|
+
) !== commitments[i])
|
|
1009
|
+
throw new Error("output commitment mismatch");
|
|
1010
|
+
total += o.amount;
|
|
1011
|
+
}
|
|
1012
|
+
if (total !== f.amount) throw new Error("funding must equal output total");
|
|
1013
|
+
return f;
|
|
1014
|
+
}
|
|
1015
|
+
function shieldFundingRequestHash(params, outputs, cs) {
|
|
1016
|
+
const outputHash = keccak2565(
|
|
1017
|
+
AbiCoder4.defaultAbiCoder().encode(
|
|
1018
|
+
["(bytes32 identity,uint256 amount)[]"].map((parameter) => ParamType4.from(parameter)),
|
|
1019
|
+
[outputs]
|
|
1020
|
+
)
|
|
1021
|
+
);
|
|
1022
|
+
return keccak2565(
|
|
1023
|
+
AbiCoder4.defaultAbiCoder().encode(
|
|
1024
|
+
[
|
|
1025
|
+
"bytes32",
|
|
1026
|
+
"(address token,bytes32[] outputCommitments,uint256 deadline)",
|
|
1027
|
+
"bytes32",
|
|
1028
|
+
"bytes32"
|
|
1029
|
+
].map((parameter) => ParamType4.from(parameter)),
|
|
1030
|
+
[
|
|
1031
|
+
keccak2565(new TextEncoder().encode("InvisiShield")),
|
|
1032
|
+
params,
|
|
1033
|
+
outputHash,
|
|
1034
|
+
deliveriesHash(cs)
|
|
1035
|
+
]
|
|
1036
|
+
)
|
|
1037
|
+
);
|
|
1038
|
+
}
|
|
1039
|
+
async function encodeShieldFundingTypedData(p) {
|
|
1040
|
+
const f = await validateShieldRequest(p);
|
|
1041
|
+
return {
|
|
1042
|
+
domain: getEIP712Domain(p.context),
|
|
1043
|
+
primaryType: "FundShield",
|
|
1044
|
+
types: { FundShield: fundingFields },
|
|
1045
|
+
message: {
|
|
1046
|
+
requestHash: shieldFundingRequestHash(p.params, p.outputs, p.deliveries),
|
|
1047
|
+
payer: f.payer,
|
|
1048
|
+
amount: f.amount,
|
|
1049
|
+
sigNonce: f.sigNonce,
|
|
1050
|
+
deadline: f.deadline
|
|
1051
|
+
}
|
|
1052
|
+
};
|
|
1053
|
+
}
|
|
1054
|
+
async function buildShieldCalldata(p) {
|
|
1055
|
+
const f = await validateShieldRequest(p);
|
|
1056
|
+
validateFundingSubmission(f, p.caller, p.context.now);
|
|
1057
|
+
return {
|
|
1058
|
+
data: new Interface4(invisiProtocolAbi).encodeFunctionData("shield", [
|
|
1059
|
+
p.params,
|
|
1060
|
+
p.outputs,
|
|
1061
|
+
p.deliveries,
|
|
1062
|
+
f
|
|
1063
|
+
]),
|
|
1064
|
+
approveAmount: f.amount
|
|
1065
|
+
};
|
|
1066
|
+
}
|
|
1067
|
+
function transactUserPublicInputs(c, p, cs, f = {}) {
|
|
1068
|
+
const words = transactPublicInputs(c, p, cs, f), digest = BigInt(
|
|
1069
|
+
((typed) => TypedDataEncoder.hash(
|
|
1070
|
+
typed.domain,
|
|
1071
|
+
Object.fromEntries(
|
|
1072
|
+
Object.entries(typed.types).map(([name, fields]) => [
|
|
1073
|
+
name,
|
|
1074
|
+
[...fields]
|
|
1075
|
+
])
|
|
1076
|
+
),
|
|
1077
|
+
typed.message
|
|
1078
|
+
))(encodeTransactTypedData(c, p, cs, f))
|
|
1079
|
+
);
|
|
1080
|
+
return [...words, word(digest >> 128n), word(digest & (1n << 128n) - 1n)];
|
|
1081
|
+
}
|
|
1082
|
+
function aggregateMemberRequestHash(c, r) {
|
|
1083
|
+
const capacity = selectTransactCapacity(
|
|
1084
|
+
r.params.nullifiers.length,
|
|
1085
|
+
r.params.outputCommitments.length
|
|
1086
|
+
);
|
|
1087
|
+
if (capacity !== 14) throw new Error("aggregate supports only capacity 14");
|
|
1088
|
+
return keccak2565(
|
|
1089
|
+
AbiCoder4.defaultAbiCoder().encode(
|
|
1090
|
+
["bytes32", "uint256", "bytes32[]"].map((parameter) => ParamType4.from(parameter)),
|
|
1091
|
+
[
|
|
1092
|
+
keccak2565(new TextEncoder().encode("InvisiAtomicBatchMemberV1")),
|
|
1093
|
+
BigInt(capacity),
|
|
1094
|
+
transactPublicInputs(c, r.params, r.deliveries, r.funding)
|
|
1095
|
+
]
|
|
1096
|
+
)
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
function aggregatePublicInputs(c, requests) {
|
|
1100
|
+
if (![4, 8, 12].includes(dense(requests, "requests").length))
|
|
1101
|
+
throw new Error("aggregate requires 4, 8 or 12 requests");
|
|
1102
|
+
return requests.flatMap((r) => {
|
|
1103
|
+
const context = { ...c, tokenAddress: r.params.token };
|
|
1104
|
+
aggregateMemberRequestHash(context, r);
|
|
1105
|
+
return [word(14n), ...transactPublicInputs(context, r.params, r.deliveries, r.funding)];
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
function encodeAggregateFundingTypedData(c, r) {
|
|
1109
|
+
const f = normalizeFunding(r.funding);
|
|
1110
|
+
if (f.amount === 0n) throw new Error("funding authorization requires positive deposit");
|
|
1111
|
+
return {
|
|
1112
|
+
domain: getEIP712Domain(c),
|
|
1113
|
+
primaryType: "FundTransact",
|
|
1114
|
+
types: { FundTransact: fundingFields },
|
|
1115
|
+
message: {
|
|
1116
|
+
requestHash: aggregateMemberRequestHash(c, r),
|
|
1117
|
+
payer: f.payer,
|
|
1118
|
+
amount: f.amount,
|
|
1119
|
+
sigNonce: f.sigNonce,
|
|
1120
|
+
deadline: f.deadline
|
|
1121
|
+
}
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// src/witness-layouts.json
|
|
1126
|
+
var witness_layouts_default = {
|
|
1127
|
+
transact_user_slots14: {
|
|
1128
|
+
artifactSha256: "486a749ae3944ae83a7ff2d298e7469b18737d88553a7d99c4782f22f7332996",
|
|
1129
|
+
keys: {
|
|
1130
|
+
evm: "7b3e65d5201246e733a1816489d80acb219a98e8606e1b81e6d48ff0c1fd537a",
|
|
1131
|
+
"noir-recursive": "148957e28e6339a8ce1121851fb7a232e31f4c5b741e415733b8d627f4b62649"
|
|
1132
|
+
},
|
|
1133
|
+
publicInputCount: 57,
|
|
1134
|
+
public: [
|
|
1135
|
+
{
|
|
1136
|
+
name: "chain_id",
|
|
1137
|
+
count: 1,
|
|
1138
|
+
array: false
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
name: "protocol_address",
|
|
1142
|
+
count: 1,
|
|
1143
|
+
array: false
|
|
1144
|
+
},
|
|
1145
|
+
{
|
|
1146
|
+
name: "token_address",
|
|
1147
|
+
count: 1,
|
|
1148
|
+
array: false
|
|
1149
|
+
},
|
|
1150
|
+
{
|
|
1151
|
+
name: "input_count",
|
|
1152
|
+
count: 1,
|
|
1153
|
+
array: false
|
|
1154
|
+
},
|
|
1155
|
+
{
|
|
1156
|
+
name: "output_count",
|
|
1157
|
+
count: 1,
|
|
1158
|
+
array: false
|
|
1159
|
+
},
|
|
1160
|
+
{
|
|
1161
|
+
name: "source_count",
|
|
1162
|
+
count: 1,
|
|
1163
|
+
array: false
|
|
1164
|
+
},
|
|
1165
|
+
{
|
|
1166
|
+
name: "input_tree_ids",
|
|
1167
|
+
count: 14,
|
|
1168
|
+
array: true
|
|
1169
|
+
},
|
|
1170
|
+
{
|
|
1171
|
+
name: "merkle_roots",
|
|
1172
|
+
count: 14,
|
|
1173
|
+
array: true
|
|
1174
|
+
},
|
|
1175
|
+
{
|
|
1176
|
+
name: "slot_values",
|
|
1177
|
+
count: 14,
|
|
1178
|
+
array: true
|
|
1179
|
+
},
|
|
1180
|
+
{
|
|
1181
|
+
name: "delivery_hash_high",
|
|
1182
|
+
count: 1,
|
|
1183
|
+
array: false
|
|
1184
|
+
},
|
|
1185
|
+
{
|
|
1186
|
+
name: "delivery_hash_low",
|
|
1187
|
+
count: 1,
|
|
1188
|
+
array: false
|
|
1189
|
+
},
|
|
1190
|
+
{
|
|
1191
|
+
name: "withdrawal_address",
|
|
1192
|
+
count: 1,
|
|
1193
|
+
array: false
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
name: "withdrawal_amount",
|
|
1197
|
+
count: 1,
|
|
1198
|
+
array: false
|
|
1199
|
+
},
|
|
1200
|
+
{
|
|
1201
|
+
name: "deadline",
|
|
1202
|
+
count: 1,
|
|
1203
|
+
array: false
|
|
1204
|
+
},
|
|
1205
|
+
{
|
|
1206
|
+
name: "deposit_amount",
|
|
1207
|
+
count: 1,
|
|
1208
|
+
array: false
|
|
1209
|
+
},
|
|
1210
|
+
{
|
|
1211
|
+
name: "deposit_payer",
|
|
1212
|
+
count: 1,
|
|
1213
|
+
array: false
|
|
1214
|
+
},
|
|
1215
|
+
{
|
|
1216
|
+
name: "auth_digest_high",
|
|
1217
|
+
count: 1,
|
|
1218
|
+
array: false
|
|
1219
|
+
},
|
|
1220
|
+
{
|
|
1221
|
+
name: "auth_digest_low",
|
|
1222
|
+
count: 1,
|
|
1223
|
+
array: false
|
|
1224
|
+
}
|
|
1225
|
+
],
|
|
1226
|
+
private: [
|
|
1227
|
+
"wallet_identity",
|
|
1228
|
+
"public_key_x",
|
|
1229
|
+
"public_key_y",
|
|
1230
|
+
"signature",
|
|
1231
|
+
"output_wallet_identities",
|
|
1232
|
+
"amounts",
|
|
1233
|
+
"nonces",
|
|
1234
|
+
"leaf_indices",
|
|
1235
|
+
"merkle_paths",
|
|
1236
|
+
"input_source_indices"
|
|
1237
|
+
]
|
|
1238
|
+
},
|
|
1239
|
+
transact_user_slots56: {
|
|
1240
|
+
artifactSha256: "169db2ff23c15adb14756edf9bb99bbd343df807b3e1c7f1f510070897e653cf",
|
|
1241
|
+
keys: {
|
|
1242
|
+
evm: "cbf54de94bff266bf846f9722c0f3ffa1fb7a0f9f478466f193de0e9123ce7f5"
|
|
1243
|
+
},
|
|
1244
|
+
publicInputCount: 183,
|
|
1245
|
+
public: [
|
|
1246
|
+
{
|
|
1247
|
+
name: "chain_id",
|
|
1248
|
+
count: 1,
|
|
1249
|
+
array: false
|
|
1250
|
+
},
|
|
1251
|
+
{
|
|
1252
|
+
name: "protocol_address",
|
|
1253
|
+
count: 1,
|
|
1254
|
+
array: false
|
|
1255
|
+
},
|
|
1256
|
+
{
|
|
1257
|
+
name: "token_address",
|
|
1258
|
+
count: 1,
|
|
1259
|
+
array: false
|
|
1260
|
+
},
|
|
1261
|
+
{
|
|
1262
|
+
name: "input_count",
|
|
1263
|
+
count: 1,
|
|
1264
|
+
array: false
|
|
1265
|
+
},
|
|
1266
|
+
{
|
|
1267
|
+
name: "output_count",
|
|
1268
|
+
count: 1,
|
|
1269
|
+
array: false
|
|
1270
|
+
},
|
|
1271
|
+
{
|
|
1272
|
+
name: "source_count",
|
|
1273
|
+
count: 1,
|
|
1274
|
+
array: false
|
|
1275
|
+
},
|
|
1276
|
+
{
|
|
1277
|
+
name: "input_tree_ids",
|
|
1278
|
+
count: 56,
|
|
1279
|
+
array: true
|
|
1280
|
+
},
|
|
1281
|
+
{
|
|
1282
|
+
name: "merkle_roots",
|
|
1283
|
+
count: 56,
|
|
1284
|
+
array: true
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
name: "slot_values",
|
|
1288
|
+
count: 56,
|
|
1289
|
+
array: true
|
|
1290
|
+
},
|
|
1291
|
+
{
|
|
1292
|
+
name: "delivery_hash_high",
|
|
1293
|
+
count: 1,
|
|
1294
|
+
array: false
|
|
1295
|
+
},
|
|
1296
|
+
{
|
|
1297
|
+
name: "delivery_hash_low",
|
|
1298
|
+
count: 1,
|
|
1299
|
+
array: false
|
|
1300
|
+
},
|
|
1301
|
+
{
|
|
1302
|
+
name: "withdrawal_address",
|
|
1303
|
+
count: 1,
|
|
1304
|
+
array: false
|
|
1305
|
+
},
|
|
1306
|
+
{
|
|
1307
|
+
name: "withdrawal_amount",
|
|
1308
|
+
count: 1,
|
|
1309
|
+
array: false
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
name: "deadline",
|
|
1313
|
+
count: 1,
|
|
1314
|
+
array: false
|
|
1315
|
+
},
|
|
1316
|
+
{
|
|
1317
|
+
name: "deposit_amount",
|
|
1318
|
+
count: 1,
|
|
1319
|
+
array: false
|
|
1320
|
+
},
|
|
1321
|
+
{
|
|
1322
|
+
name: "deposit_payer",
|
|
1323
|
+
count: 1,
|
|
1324
|
+
array: false
|
|
1325
|
+
},
|
|
1326
|
+
{
|
|
1327
|
+
name: "auth_digest_high",
|
|
1328
|
+
count: 1,
|
|
1329
|
+
array: false
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
name: "auth_digest_low",
|
|
1333
|
+
count: 1,
|
|
1334
|
+
array: false
|
|
1335
|
+
}
|
|
1336
|
+
],
|
|
1337
|
+
private: [
|
|
1338
|
+
"wallet_identity",
|
|
1339
|
+
"public_key_x",
|
|
1340
|
+
"public_key_y",
|
|
1341
|
+
"signature",
|
|
1342
|
+
"output_wallet_identities",
|
|
1343
|
+
"amounts",
|
|
1344
|
+
"nonces",
|
|
1345
|
+
"leaf_indices",
|
|
1346
|
+
"merkle_paths",
|
|
1347
|
+
"input_source_indices"
|
|
1348
|
+
]
|
|
1349
|
+
},
|
|
1350
|
+
transact_user_slots112: {
|
|
1351
|
+
artifactSha256: "221bbbd6ff0c7d7dec74677e52484f082b3e176bb0fa47f3236064e396d73739",
|
|
1352
|
+
keys: {
|
|
1353
|
+
evm: "67b2d361b023f193ecdb5a9aefbe2840349ee5ce848ab4101416734f3a7e91e9"
|
|
1354
|
+
},
|
|
1355
|
+
publicInputCount: 351,
|
|
1356
|
+
public: [
|
|
1357
|
+
{
|
|
1358
|
+
name: "chain_id",
|
|
1359
|
+
count: 1,
|
|
1360
|
+
array: false
|
|
1361
|
+
},
|
|
1362
|
+
{
|
|
1363
|
+
name: "protocol_address",
|
|
1364
|
+
count: 1,
|
|
1365
|
+
array: false
|
|
1366
|
+
},
|
|
1367
|
+
{
|
|
1368
|
+
name: "token_address",
|
|
1369
|
+
count: 1,
|
|
1370
|
+
array: false
|
|
1371
|
+
},
|
|
1372
|
+
{
|
|
1373
|
+
name: "input_count",
|
|
1374
|
+
count: 1,
|
|
1375
|
+
array: false
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
name: "output_count",
|
|
1379
|
+
count: 1,
|
|
1380
|
+
array: false
|
|
1381
|
+
},
|
|
1382
|
+
{
|
|
1383
|
+
name: "source_count",
|
|
1384
|
+
count: 1,
|
|
1385
|
+
array: false
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
name: "input_tree_ids",
|
|
1389
|
+
count: 112,
|
|
1390
|
+
array: true
|
|
1391
|
+
},
|
|
1392
|
+
{
|
|
1393
|
+
name: "merkle_roots",
|
|
1394
|
+
count: 112,
|
|
1395
|
+
array: true
|
|
1396
|
+
},
|
|
1397
|
+
{
|
|
1398
|
+
name: "slot_values",
|
|
1399
|
+
count: 112,
|
|
1400
|
+
array: true
|
|
1401
|
+
},
|
|
1402
|
+
{
|
|
1403
|
+
name: "delivery_hash_high",
|
|
1404
|
+
count: 1,
|
|
1405
|
+
array: false
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
name: "delivery_hash_low",
|
|
1409
|
+
count: 1,
|
|
1410
|
+
array: false
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
name: "withdrawal_address",
|
|
1414
|
+
count: 1,
|
|
1415
|
+
array: false
|
|
1416
|
+
},
|
|
1417
|
+
{
|
|
1418
|
+
name: "withdrawal_amount",
|
|
1419
|
+
count: 1,
|
|
1420
|
+
array: false
|
|
1421
|
+
},
|
|
1422
|
+
{
|
|
1423
|
+
name: "deadline",
|
|
1424
|
+
count: 1,
|
|
1425
|
+
array: false
|
|
1426
|
+
},
|
|
1427
|
+
{
|
|
1428
|
+
name: "deposit_amount",
|
|
1429
|
+
count: 1,
|
|
1430
|
+
array: false
|
|
1431
|
+
},
|
|
1432
|
+
{
|
|
1433
|
+
name: "deposit_payer",
|
|
1434
|
+
count: 1,
|
|
1435
|
+
array: false
|
|
1436
|
+
},
|
|
1437
|
+
{
|
|
1438
|
+
name: "auth_digest_high",
|
|
1439
|
+
count: 1,
|
|
1440
|
+
array: false
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
name: "auth_digest_low",
|
|
1444
|
+
count: 1,
|
|
1445
|
+
array: false
|
|
1446
|
+
}
|
|
1447
|
+
],
|
|
1448
|
+
private: [
|
|
1449
|
+
"wallet_identity",
|
|
1450
|
+
"public_key_x",
|
|
1451
|
+
"public_key_y",
|
|
1452
|
+
"signature",
|
|
1453
|
+
"output_wallet_identities",
|
|
1454
|
+
"amounts",
|
|
1455
|
+
"nonces",
|
|
1456
|
+
"leaf_indices",
|
|
1457
|
+
"merkle_paths",
|
|
1458
|
+
"input_source_indices"
|
|
1459
|
+
]
|
|
1460
|
+
},
|
|
1461
|
+
transact_user_slots168: {
|
|
1462
|
+
artifactSha256: "d479253eaaacc973806a84e142e2362d873bba0f150ce050d32b8d9b2947adc8",
|
|
1463
|
+
keys: {
|
|
1464
|
+
evm: "c50e72b0718c6393f82f5a67e248ba093d0db56ece42bbf092da93e9369c2624"
|
|
1465
|
+
},
|
|
1466
|
+
publicInputCount: 519,
|
|
1467
|
+
public: [
|
|
1468
|
+
{
|
|
1469
|
+
name: "chain_id",
|
|
1470
|
+
count: 1,
|
|
1471
|
+
array: false
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
name: "protocol_address",
|
|
1475
|
+
count: 1,
|
|
1476
|
+
array: false
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
name: "token_address",
|
|
1480
|
+
count: 1,
|
|
1481
|
+
array: false
|
|
1482
|
+
},
|
|
1483
|
+
{
|
|
1484
|
+
name: "input_count",
|
|
1485
|
+
count: 1,
|
|
1486
|
+
array: false
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
name: "output_count",
|
|
1490
|
+
count: 1,
|
|
1491
|
+
array: false
|
|
1492
|
+
},
|
|
1493
|
+
{
|
|
1494
|
+
name: "source_count",
|
|
1495
|
+
count: 1,
|
|
1496
|
+
array: false
|
|
1497
|
+
},
|
|
1498
|
+
{
|
|
1499
|
+
name: "input_tree_ids",
|
|
1500
|
+
count: 168,
|
|
1501
|
+
array: true
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
name: "merkle_roots",
|
|
1505
|
+
count: 168,
|
|
1506
|
+
array: true
|
|
1507
|
+
},
|
|
1508
|
+
{
|
|
1509
|
+
name: "slot_values",
|
|
1510
|
+
count: 168,
|
|
1511
|
+
array: true
|
|
1512
|
+
},
|
|
1513
|
+
{
|
|
1514
|
+
name: "delivery_hash_high",
|
|
1515
|
+
count: 1,
|
|
1516
|
+
array: false
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
name: "delivery_hash_low",
|
|
1520
|
+
count: 1,
|
|
1521
|
+
array: false
|
|
1522
|
+
},
|
|
1523
|
+
{
|
|
1524
|
+
name: "withdrawal_address",
|
|
1525
|
+
count: 1,
|
|
1526
|
+
array: false
|
|
1527
|
+
},
|
|
1528
|
+
{
|
|
1529
|
+
name: "withdrawal_amount",
|
|
1530
|
+
count: 1,
|
|
1531
|
+
array: false
|
|
1532
|
+
},
|
|
1533
|
+
{
|
|
1534
|
+
name: "deadline",
|
|
1535
|
+
count: 1,
|
|
1536
|
+
array: false
|
|
1537
|
+
},
|
|
1538
|
+
{
|
|
1539
|
+
name: "deposit_amount",
|
|
1540
|
+
count: 1,
|
|
1541
|
+
array: false
|
|
1542
|
+
},
|
|
1543
|
+
{
|
|
1544
|
+
name: "deposit_payer",
|
|
1545
|
+
count: 1,
|
|
1546
|
+
array: false
|
|
1547
|
+
},
|
|
1548
|
+
{
|
|
1549
|
+
name: "auth_digest_high",
|
|
1550
|
+
count: 1,
|
|
1551
|
+
array: false
|
|
1552
|
+
},
|
|
1553
|
+
{
|
|
1554
|
+
name: "auth_digest_low",
|
|
1555
|
+
count: 1,
|
|
1556
|
+
array: false
|
|
1557
|
+
}
|
|
1558
|
+
],
|
|
1559
|
+
private: [
|
|
1560
|
+
"wallet_identity",
|
|
1561
|
+
"public_key_x",
|
|
1562
|
+
"public_key_y",
|
|
1563
|
+
"signature",
|
|
1564
|
+
"output_wallet_identities",
|
|
1565
|
+
"amounts",
|
|
1566
|
+
"nonces",
|
|
1567
|
+
"leaf_indices",
|
|
1568
|
+
"merkle_paths",
|
|
1569
|
+
"input_source_indices"
|
|
1570
|
+
]
|
|
1571
|
+
},
|
|
1572
|
+
transact_aggregate_14_4: {
|
|
1573
|
+
artifactSha256: "4fe7c63fb80cba35af4c4525fbabcfb75033286e681afbdcb3fb043c03456246",
|
|
1574
|
+
keys: {
|
|
1575
|
+
evm: "664d4ff0de6b8c876ce990ea368d7a59cee411463c24dd5621d64c8949554674"
|
|
1576
|
+
},
|
|
1577
|
+
publicInputCount: 229,
|
|
1578
|
+
public: [
|
|
1579
|
+
{
|
|
1580
|
+
name: "statements",
|
|
1581
|
+
count: 4,
|
|
1582
|
+
array: true
|
|
1583
|
+
},
|
|
1584
|
+
{
|
|
1585
|
+
name: "inner_vk_commitment",
|
|
1586
|
+
count: 1,
|
|
1587
|
+
array: false
|
|
1588
|
+
}
|
|
1589
|
+
],
|
|
1590
|
+
private: [
|
|
1591
|
+
"verification_key",
|
|
1592
|
+
"key_hash",
|
|
1593
|
+
"proofs"
|
|
1594
|
+
]
|
|
1595
|
+
},
|
|
1596
|
+
transact_aggregate_14_8: {
|
|
1597
|
+
artifactSha256: "0a266ad4bb4c6dce42b1e851fcbb34b1becae1edd6bf6af82d7b9ed7184576df",
|
|
1598
|
+
keys: {
|
|
1599
|
+
evm: "042139122d0eee8beeaa9c18397276fa5a2872218495fa16ca438fbdd80fa3e1"
|
|
1600
|
+
},
|
|
1601
|
+
publicInputCount: 457,
|
|
1602
|
+
public: [
|
|
1603
|
+
{
|
|
1604
|
+
name: "statements",
|
|
1605
|
+
count: 8,
|
|
1606
|
+
array: true
|
|
1607
|
+
},
|
|
1608
|
+
{
|
|
1609
|
+
name: "inner_vk_commitment",
|
|
1610
|
+
count: 1,
|
|
1611
|
+
array: false
|
|
1612
|
+
}
|
|
1613
|
+
],
|
|
1614
|
+
private: [
|
|
1615
|
+
"verification_key",
|
|
1616
|
+
"key_hash",
|
|
1617
|
+
"proofs"
|
|
1618
|
+
]
|
|
1619
|
+
},
|
|
1620
|
+
transact_aggregate_14_12: {
|
|
1621
|
+
artifactSha256: "738849e83eb4a78eb69cb6e20a86f6f27ba3784d04a83abd338f84de5c20d7d2",
|
|
1622
|
+
keys: {
|
|
1623
|
+
evm: "539928b264aea4d07a41e772d5d5a7b7666a6883decb985c27ca7422e7f8ea1f"
|
|
1624
|
+
},
|
|
1625
|
+
publicInputCount: 685,
|
|
1626
|
+
public: [
|
|
1627
|
+
{
|
|
1628
|
+
name: "statements",
|
|
1629
|
+
count: 12,
|
|
1630
|
+
array: true
|
|
1631
|
+
},
|
|
1632
|
+
{
|
|
1633
|
+
name: "inner_vk_commitment",
|
|
1634
|
+
count: 1,
|
|
1635
|
+
array: false
|
|
1636
|
+
}
|
|
1637
|
+
],
|
|
1638
|
+
private: [
|
|
1639
|
+
"verification_key",
|
|
1640
|
+
"key_hash",
|
|
1641
|
+
"proofs"
|
|
1642
|
+
]
|
|
1643
|
+
},
|
|
1644
|
+
create_credit: {
|
|
1645
|
+
artifactSha256: "078c6d2da1ed2d6bd27fab28af9970261fe626a0b22ae56ad170e5d15b1b05ba",
|
|
1646
|
+
keys: {
|
|
1647
|
+
evm: "8285456447e92833a4fa9c330b9c667a3a1b9e48649578082041b9738f037c8f"
|
|
1648
|
+
},
|
|
1649
|
+
publicInputCount: 46,
|
|
1650
|
+
public: [
|
|
1651
|
+
{
|
|
1652
|
+
name: "chain_id",
|
|
1653
|
+
count: 1,
|
|
1654
|
+
array: false
|
|
1655
|
+
},
|
|
1656
|
+
{
|
|
1657
|
+
name: "protocol_address",
|
|
1658
|
+
count: 1,
|
|
1659
|
+
array: false
|
|
1660
|
+
},
|
|
1661
|
+
{
|
|
1662
|
+
name: "token_address",
|
|
1663
|
+
count: 1,
|
|
1664
|
+
array: false
|
|
1665
|
+
},
|
|
1666
|
+
{
|
|
1667
|
+
name: "owner_address",
|
|
1668
|
+
count: 1,
|
|
1669
|
+
array: false
|
|
1670
|
+
},
|
|
1671
|
+
{
|
|
1672
|
+
name: "actual_count",
|
|
1673
|
+
count: 1,
|
|
1674
|
+
array: false
|
|
1675
|
+
},
|
|
1676
|
+
{
|
|
1677
|
+
name: "source_count",
|
|
1678
|
+
count: 1,
|
|
1679
|
+
array: false
|
|
1680
|
+
},
|
|
1681
|
+
{
|
|
1682
|
+
name: "input_tree_ids",
|
|
1683
|
+
count: 10,
|
|
1684
|
+
array: true
|
|
1685
|
+
},
|
|
1686
|
+
{
|
|
1687
|
+
name: "merkle_roots",
|
|
1688
|
+
count: 10,
|
|
1689
|
+
array: true
|
|
1690
|
+
},
|
|
1691
|
+
{
|
|
1692
|
+
name: "nullifiers",
|
|
1693
|
+
count: 10,
|
|
1694
|
+
array: true
|
|
1695
|
+
},
|
|
1696
|
+
{
|
|
1697
|
+
name: "credit_commitment",
|
|
1698
|
+
count: 1,
|
|
1699
|
+
array: false
|
|
1700
|
+
},
|
|
1701
|
+
{
|
|
1702
|
+
name: "change_commitment",
|
|
1703
|
+
count: 1,
|
|
1704
|
+
array: false
|
|
1705
|
+
},
|
|
1706
|
+
{
|
|
1707
|
+
name: "delivery_hash_high",
|
|
1708
|
+
count: 1,
|
|
1709
|
+
array: false
|
|
1710
|
+
},
|
|
1711
|
+
{
|
|
1712
|
+
name: "delivery_hash_low",
|
|
1713
|
+
count: 1,
|
|
1714
|
+
array: false
|
|
1715
|
+
},
|
|
1716
|
+
{
|
|
1717
|
+
name: "expiry",
|
|
1718
|
+
count: 1,
|
|
1719
|
+
array: false
|
|
1720
|
+
},
|
|
1721
|
+
{
|
|
1722
|
+
name: "deadline",
|
|
1723
|
+
count: 1,
|
|
1724
|
+
array: false
|
|
1725
|
+
},
|
|
1726
|
+
{
|
|
1727
|
+
name: "deposit_amount",
|
|
1728
|
+
count: 1,
|
|
1729
|
+
array: false
|
|
1730
|
+
},
|
|
1731
|
+
{
|
|
1732
|
+
name: "deposit_payer",
|
|
1733
|
+
count: 1,
|
|
1734
|
+
array: false
|
|
1735
|
+
},
|
|
1736
|
+
{
|
|
1737
|
+
name: "auth_digest_high",
|
|
1738
|
+
count: 1,
|
|
1739
|
+
array: false
|
|
1740
|
+
},
|
|
1741
|
+
{
|
|
1742
|
+
name: "auth_digest_low",
|
|
1743
|
+
count: 1,
|
|
1744
|
+
array: false
|
|
1745
|
+
}
|
|
1746
|
+
],
|
|
1747
|
+
private: [
|
|
1748
|
+
"input_amounts",
|
|
1749
|
+
"input_nonces",
|
|
1750
|
+
"leaf_indices",
|
|
1751
|
+
"merkle_paths",
|
|
1752
|
+
"input_source_indices",
|
|
1753
|
+
"public_key_x",
|
|
1754
|
+
"public_key_y",
|
|
1755
|
+
"signature",
|
|
1756
|
+
"spender_payout",
|
|
1757
|
+
"spender_wallet_identity",
|
|
1758
|
+
"owner_wallet_identity",
|
|
1759
|
+
"credit_amount",
|
|
1760
|
+
"credit_nonce",
|
|
1761
|
+
"credit_shared_key",
|
|
1762
|
+
"change_amount",
|
|
1763
|
+
"change_nonce"
|
|
1764
|
+
]
|
|
1765
|
+
},
|
|
1766
|
+
credit_draw_slots1: {
|
|
1767
|
+
artifactSha256: "2b9da9d3d1dbd411d9be1bbe2b34305ac5dce7c7d18e3857d8e2be7dd9bf7c21",
|
|
1768
|
+
keys: {
|
|
1769
|
+
evm: "613699a440f50a0937e4c57e5152b5fdea42c31b10157d6b93226fef313df553"
|
|
1770
|
+
},
|
|
1771
|
+
publicInputCount: 18,
|
|
1772
|
+
public: [
|
|
1773
|
+
{
|
|
1774
|
+
name: "chain_id",
|
|
1775
|
+
count: 1,
|
|
1776
|
+
array: false
|
|
1777
|
+
},
|
|
1778
|
+
{
|
|
1779
|
+
name: "protocol_address",
|
|
1780
|
+
count: 1,
|
|
1781
|
+
array: false
|
|
1782
|
+
},
|
|
1783
|
+
{
|
|
1784
|
+
name: "token_address",
|
|
1785
|
+
count: 1,
|
|
1786
|
+
array: false
|
|
1787
|
+
},
|
|
1788
|
+
{
|
|
1789
|
+
name: "spender_address",
|
|
1790
|
+
count: 1,
|
|
1791
|
+
array: false
|
|
1792
|
+
},
|
|
1793
|
+
{
|
|
1794
|
+
name: "actual_count",
|
|
1795
|
+
count: 1,
|
|
1796
|
+
array: false
|
|
1797
|
+
},
|
|
1798
|
+
{
|
|
1799
|
+
name: "source_count",
|
|
1800
|
+
count: 1,
|
|
1801
|
+
array: false
|
|
1802
|
+
},
|
|
1803
|
+
{
|
|
1804
|
+
name: "tree_ids",
|
|
1805
|
+
count: 1,
|
|
1806
|
+
array: true
|
|
1807
|
+
},
|
|
1808
|
+
{
|
|
1809
|
+
name: "roots",
|
|
1810
|
+
count: 1,
|
|
1811
|
+
array: true
|
|
1812
|
+
},
|
|
1813
|
+
{
|
|
1814
|
+
name: "nullifiers",
|
|
1815
|
+
count: 1,
|
|
1816
|
+
array: true
|
|
1817
|
+
},
|
|
1818
|
+
{
|
|
1819
|
+
name: "remainder_commitments",
|
|
1820
|
+
count: 1,
|
|
1821
|
+
array: true
|
|
1822
|
+
},
|
|
1823
|
+
{
|
|
1824
|
+
name: "expiries",
|
|
1825
|
+
count: 1,
|
|
1826
|
+
array: true
|
|
1827
|
+
},
|
|
1828
|
+
{
|
|
1829
|
+
name: "total_amount",
|
|
1830
|
+
count: 1,
|
|
1831
|
+
array: false
|
|
1832
|
+
},
|
|
1833
|
+
{
|
|
1834
|
+
name: "deadline",
|
|
1835
|
+
count: 1,
|
|
1836
|
+
array: false
|
|
1837
|
+
},
|
|
1838
|
+
{
|
|
1839
|
+
name: "delivery_hash_high",
|
|
1840
|
+
count: 1,
|
|
1841
|
+
array: false
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
name: "delivery_hash_low",
|
|
1845
|
+
count: 1,
|
|
1846
|
+
array: false
|
|
1847
|
+
},
|
|
1848
|
+
{
|
|
1849
|
+
name: "recovery_amounts",
|
|
1850
|
+
count: 1,
|
|
1851
|
+
array: true
|
|
1852
|
+
},
|
|
1853
|
+
{
|
|
1854
|
+
name: "auth_digest_high",
|
|
1855
|
+
count: 1,
|
|
1856
|
+
array: false
|
|
1857
|
+
},
|
|
1858
|
+
{
|
|
1859
|
+
name: "auth_digest_low",
|
|
1860
|
+
count: 1,
|
|
1861
|
+
array: false
|
|
1862
|
+
}
|
|
1863
|
+
],
|
|
1864
|
+
private: [
|
|
1865
|
+
"public_key_x",
|
|
1866
|
+
"public_key_y",
|
|
1867
|
+
"signature",
|
|
1868
|
+
"spender_wallet_identity",
|
|
1869
|
+
"owner_payouts",
|
|
1870
|
+
"owner_wallet_identities",
|
|
1871
|
+
"input_amounts",
|
|
1872
|
+
"input_nonces",
|
|
1873
|
+
"credit_shared_keys",
|
|
1874
|
+
"leaf_indices",
|
|
1875
|
+
"merkle_paths",
|
|
1876
|
+
"input_source_indices",
|
|
1877
|
+
"draw_amounts"
|
|
1878
|
+
]
|
|
1879
|
+
},
|
|
1880
|
+
credit_draw_slots12: {
|
|
1881
|
+
artifactSha256: "92b741e161a99c05b8810bc24cee6bafc1cebc85347ea47fe511ee6c8f7065be",
|
|
1882
|
+
keys: {
|
|
1883
|
+
evm: "a5ae214784fe6e523977ef4e283a6d217fc3f4ec0c5a40effb275693a74ee5ce"
|
|
1884
|
+
},
|
|
1885
|
+
publicInputCount: 84,
|
|
1886
|
+
public: [
|
|
1887
|
+
{
|
|
1888
|
+
name: "chain_id",
|
|
1889
|
+
count: 1,
|
|
1890
|
+
array: false
|
|
1891
|
+
},
|
|
1892
|
+
{
|
|
1893
|
+
name: "protocol_address",
|
|
1894
|
+
count: 1,
|
|
1895
|
+
array: false
|
|
1896
|
+
},
|
|
1897
|
+
{
|
|
1898
|
+
name: "token_address",
|
|
1899
|
+
count: 1,
|
|
1900
|
+
array: false
|
|
1901
|
+
},
|
|
1902
|
+
{
|
|
1903
|
+
name: "spender_address",
|
|
1904
|
+
count: 1,
|
|
1905
|
+
array: false
|
|
1906
|
+
},
|
|
1907
|
+
{
|
|
1908
|
+
name: "actual_count",
|
|
1909
|
+
count: 1,
|
|
1910
|
+
array: false
|
|
1911
|
+
},
|
|
1912
|
+
{
|
|
1913
|
+
name: "source_count",
|
|
1914
|
+
count: 1,
|
|
1915
|
+
array: false
|
|
1916
|
+
},
|
|
1917
|
+
{
|
|
1918
|
+
name: "tree_ids",
|
|
1919
|
+
count: 12,
|
|
1920
|
+
array: true
|
|
1921
|
+
},
|
|
1922
|
+
{
|
|
1923
|
+
name: "roots",
|
|
1924
|
+
count: 12,
|
|
1925
|
+
array: true
|
|
1926
|
+
},
|
|
1927
|
+
{
|
|
1928
|
+
name: "nullifiers",
|
|
1929
|
+
count: 12,
|
|
1930
|
+
array: true
|
|
1931
|
+
},
|
|
1932
|
+
{
|
|
1933
|
+
name: "remainder_commitments",
|
|
1934
|
+
count: 12,
|
|
1935
|
+
array: true
|
|
1936
|
+
},
|
|
1937
|
+
{
|
|
1938
|
+
name: "expiries",
|
|
1939
|
+
count: 12,
|
|
1940
|
+
array: true
|
|
1941
|
+
},
|
|
1942
|
+
{
|
|
1943
|
+
name: "total_amount",
|
|
1944
|
+
count: 1,
|
|
1945
|
+
array: false
|
|
1946
|
+
},
|
|
1947
|
+
{
|
|
1948
|
+
name: "deadline",
|
|
1949
|
+
count: 1,
|
|
1950
|
+
array: false
|
|
1951
|
+
},
|
|
1952
|
+
{
|
|
1953
|
+
name: "delivery_hash_high",
|
|
1954
|
+
count: 1,
|
|
1955
|
+
array: false
|
|
1956
|
+
},
|
|
1957
|
+
{
|
|
1958
|
+
name: "delivery_hash_low",
|
|
1959
|
+
count: 1,
|
|
1960
|
+
array: false
|
|
1961
|
+
},
|
|
1962
|
+
{
|
|
1963
|
+
name: "recovery_amounts",
|
|
1964
|
+
count: 12,
|
|
1965
|
+
array: true
|
|
1966
|
+
},
|
|
1967
|
+
{
|
|
1968
|
+
name: "auth_digest_high",
|
|
1969
|
+
count: 1,
|
|
1970
|
+
array: false
|
|
1971
|
+
},
|
|
1972
|
+
{
|
|
1973
|
+
name: "auth_digest_low",
|
|
1974
|
+
count: 1,
|
|
1975
|
+
array: false
|
|
1976
|
+
}
|
|
1977
|
+
],
|
|
1978
|
+
private: [
|
|
1979
|
+
"public_key_x",
|
|
1980
|
+
"public_key_y",
|
|
1981
|
+
"signature",
|
|
1982
|
+
"spender_wallet_identity",
|
|
1983
|
+
"owner_payouts",
|
|
1984
|
+
"owner_wallet_identities",
|
|
1985
|
+
"input_amounts",
|
|
1986
|
+
"input_nonces",
|
|
1987
|
+
"credit_shared_keys",
|
|
1988
|
+
"leaf_indices",
|
|
1989
|
+
"merkle_paths",
|
|
1990
|
+
"input_source_indices",
|
|
1991
|
+
"draw_amounts"
|
|
1992
|
+
]
|
|
1993
|
+
},
|
|
1994
|
+
credit_draw_slots50: {
|
|
1995
|
+
artifactSha256: "9c6a23d5dbca3a1aeed461c908f228e89642550775cbc519d633bb1c984a3d04",
|
|
1996
|
+
keys: {
|
|
1997
|
+
evm: "f0b192e2cb312148c7a16fae3acaed9efb01b0c6a1b381ce03468f00b4ef0f2a"
|
|
1998
|
+
},
|
|
1999
|
+
publicInputCount: 312,
|
|
2000
|
+
public: [
|
|
2001
|
+
{
|
|
2002
|
+
name: "chain_id",
|
|
2003
|
+
count: 1,
|
|
2004
|
+
array: false
|
|
2005
|
+
},
|
|
2006
|
+
{
|
|
2007
|
+
name: "protocol_address",
|
|
2008
|
+
count: 1,
|
|
2009
|
+
array: false
|
|
2010
|
+
},
|
|
2011
|
+
{
|
|
2012
|
+
name: "token_address",
|
|
2013
|
+
count: 1,
|
|
2014
|
+
array: false
|
|
2015
|
+
},
|
|
2016
|
+
{
|
|
2017
|
+
name: "spender_address",
|
|
2018
|
+
count: 1,
|
|
2019
|
+
array: false
|
|
2020
|
+
},
|
|
2021
|
+
{
|
|
2022
|
+
name: "actual_count",
|
|
2023
|
+
count: 1,
|
|
2024
|
+
array: false
|
|
2025
|
+
},
|
|
2026
|
+
{
|
|
2027
|
+
name: "source_count",
|
|
2028
|
+
count: 1,
|
|
2029
|
+
array: false
|
|
2030
|
+
},
|
|
2031
|
+
{
|
|
2032
|
+
name: "tree_ids",
|
|
2033
|
+
count: 50,
|
|
2034
|
+
array: true
|
|
2035
|
+
},
|
|
2036
|
+
{
|
|
2037
|
+
name: "roots",
|
|
2038
|
+
count: 50,
|
|
2039
|
+
array: true
|
|
2040
|
+
},
|
|
2041
|
+
{
|
|
2042
|
+
name: "nullifiers",
|
|
2043
|
+
count: 50,
|
|
2044
|
+
array: true
|
|
2045
|
+
},
|
|
2046
|
+
{
|
|
2047
|
+
name: "remainder_commitments",
|
|
2048
|
+
count: 50,
|
|
2049
|
+
array: true
|
|
2050
|
+
},
|
|
2051
|
+
{
|
|
2052
|
+
name: "expiries",
|
|
2053
|
+
count: 50,
|
|
2054
|
+
array: true
|
|
2055
|
+
},
|
|
2056
|
+
{
|
|
2057
|
+
name: "total_amount",
|
|
2058
|
+
count: 1,
|
|
2059
|
+
array: false
|
|
2060
|
+
},
|
|
2061
|
+
{
|
|
2062
|
+
name: "deadline",
|
|
2063
|
+
count: 1,
|
|
2064
|
+
array: false
|
|
2065
|
+
},
|
|
2066
|
+
{
|
|
2067
|
+
name: "delivery_hash_high",
|
|
2068
|
+
count: 1,
|
|
2069
|
+
array: false
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
name: "delivery_hash_low",
|
|
2073
|
+
count: 1,
|
|
2074
|
+
array: false
|
|
2075
|
+
},
|
|
2076
|
+
{
|
|
2077
|
+
name: "recovery_amounts",
|
|
2078
|
+
count: 50,
|
|
2079
|
+
array: true
|
|
2080
|
+
},
|
|
2081
|
+
{
|
|
2082
|
+
name: "auth_digest_high",
|
|
2083
|
+
count: 1,
|
|
2084
|
+
array: false
|
|
2085
|
+
},
|
|
2086
|
+
{
|
|
2087
|
+
name: "auth_digest_low",
|
|
2088
|
+
count: 1,
|
|
2089
|
+
array: false
|
|
2090
|
+
}
|
|
2091
|
+
],
|
|
2092
|
+
private: [
|
|
2093
|
+
"public_key_x",
|
|
2094
|
+
"public_key_y",
|
|
2095
|
+
"signature",
|
|
2096
|
+
"spender_wallet_identity",
|
|
2097
|
+
"owner_payouts",
|
|
2098
|
+
"owner_wallet_identities",
|
|
2099
|
+
"input_amounts",
|
|
2100
|
+
"input_nonces",
|
|
2101
|
+
"credit_shared_keys",
|
|
2102
|
+
"leaf_indices",
|
|
2103
|
+
"merkle_paths",
|
|
2104
|
+
"input_source_indices",
|
|
2105
|
+
"draw_amounts"
|
|
2106
|
+
]
|
|
2107
|
+
},
|
|
2108
|
+
credit_draw_slots120: {
|
|
2109
|
+
artifactSha256: "69686a4f0a8a98d8cef06485b0de1804ca2e8f47ce0244287a03ceef4d67625a",
|
|
2110
|
+
keys: {
|
|
2111
|
+
evm: "6f32ca89775f332a9193af9b1e25641ef14fda9fbdd2685c33ee775d3c170b92"
|
|
2112
|
+
},
|
|
2113
|
+
publicInputCount: 732,
|
|
2114
|
+
public: [
|
|
2115
|
+
{
|
|
2116
|
+
name: "chain_id",
|
|
2117
|
+
count: 1,
|
|
2118
|
+
array: false
|
|
2119
|
+
},
|
|
2120
|
+
{
|
|
2121
|
+
name: "protocol_address",
|
|
2122
|
+
count: 1,
|
|
2123
|
+
array: false
|
|
2124
|
+
},
|
|
2125
|
+
{
|
|
2126
|
+
name: "token_address",
|
|
2127
|
+
count: 1,
|
|
2128
|
+
array: false
|
|
2129
|
+
},
|
|
2130
|
+
{
|
|
2131
|
+
name: "spender_address",
|
|
2132
|
+
count: 1,
|
|
2133
|
+
array: false
|
|
2134
|
+
},
|
|
2135
|
+
{
|
|
2136
|
+
name: "actual_count",
|
|
2137
|
+
count: 1,
|
|
2138
|
+
array: false
|
|
2139
|
+
},
|
|
2140
|
+
{
|
|
2141
|
+
name: "source_count",
|
|
2142
|
+
count: 1,
|
|
2143
|
+
array: false
|
|
2144
|
+
},
|
|
2145
|
+
{
|
|
2146
|
+
name: "tree_ids",
|
|
2147
|
+
count: 120,
|
|
2148
|
+
array: true
|
|
2149
|
+
},
|
|
2150
|
+
{
|
|
2151
|
+
name: "roots",
|
|
2152
|
+
count: 120,
|
|
2153
|
+
array: true
|
|
2154
|
+
},
|
|
2155
|
+
{
|
|
2156
|
+
name: "nullifiers",
|
|
2157
|
+
count: 120,
|
|
2158
|
+
array: true
|
|
2159
|
+
},
|
|
2160
|
+
{
|
|
2161
|
+
name: "remainder_commitments",
|
|
2162
|
+
count: 120,
|
|
2163
|
+
array: true
|
|
2164
|
+
},
|
|
2165
|
+
{
|
|
2166
|
+
name: "expiries",
|
|
2167
|
+
count: 120,
|
|
2168
|
+
array: true
|
|
2169
|
+
},
|
|
2170
|
+
{
|
|
2171
|
+
name: "total_amount",
|
|
2172
|
+
count: 1,
|
|
2173
|
+
array: false
|
|
2174
|
+
},
|
|
2175
|
+
{
|
|
2176
|
+
name: "deadline",
|
|
2177
|
+
count: 1,
|
|
2178
|
+
array: false
|
|
2179
|
+
},
|
|
2180
|
+
{
|
|
2181
|
+
name: "delivery_hash_high",
|
|
2182
|
+
count: 1,
|
|
2183
|
+
array: false
|
|
2184
|
+
},
|
|
2185
|
+
{
|
|
2186
|
+
name: "delivery_hash_low",
|
|
2187
|
+
count: 1,
|
|
2188
|
+
array: false
|
|
2189
|
+
},
|
|
2190
|
+
{
|
|
2191
|
+
name: "recovery_amounts",
|
|
2192
|
+
count: 120,
|
|
2193
|
+
array: true
|
|
2194
|
+
},
|
|
2195
|
+
{
|
|
2196
|
+
name: "auth_digest_high",
|
|
2197
|
+
count: 1,
|
|
2198
|
+
array: false
|
|
2199
|
+
},
|
|
2200
|
+
{
|
|
2201
|
+
name: "auth_digest_low",
|
|
2202
|
+
count: 1,
|
|
2203
|
+
array: false
|
|
2204
|
+
}
|
|
2205
|
+
],
|
|
2206
|
+
private: [
|
|
2207
|
+
"public_key_x",
|
|
2208
|
+
"public_key_y",
|
|
2209
|
+
"signature",
|
|
2210
|
+
"spender_wallet_identity",
|
|
2211
|
+
"owner_payouts",
|
|
2212
|
+
"owner_wallet_identities",
|
|
2213
|
+
"input_amounts",
|
|
2214
|
+
"input_nonces",
|
|
2215
|
+
"credit_shared_keys",
|
|
2216
|
+
"leaf_indices",
|
|
2217
|
+
"merkle_paths",
|
|
2218
|
+
"input_source_indices",
|
|
2219
|
+
"draw_amounts"
|
|
2220
|
+
]
|
|
2221
|
+
},
|
|
2222
|
+
credit_cancel: {
|
|
2223
|
+
artifactSha256: "ff278a04f22d2886c9f27f7785a0b8fc317dd242fd4aa9d0d9398d18b7513daf",
|
|
2224
|
+
keys: {
|
|
2225
|
+
evm: "1f8a3c20cb081d6a90962556da3124919cc4e5675e59ad31562af39299da02fb"
|
|
2226
|
+
},
|
|
2227
|
+
publicInputCount: 11,
|
|
2228
|
+
public: [
|
|
2229
|
+
{
|
|
2230
|
+
name: "chain_id",
|
|
2231
|
+
count: 1,
|
|
2232
|
+
array: false
|
|
2233
|
+
},
|
|
2234
|
+
{
|
|
2235
|
+
name: "protocol_address",
|
|
2236
|
+
count: 1,
|
|
2237
|
+
array: false
|
|
2238
|
+
},
|
|
2239
|
+
{
|
|
2240
|
+
name: "token_address",
|
|
2241
|
+
count: 1,
|
|
2242
|
+
array: false
|
|
2243
|
+
},
|
|
2244
|
+
{
|
|
2245
|
+
name: "owner_address",
|
|
2246
|
+
count: 1,
|
|
2247
|
+
array: false
|
|
2248
|
+
},
|
|
2249
|
+
{
|
|
2250
|
+
name: "tree_id",
|
|
2251
|
+
count: 1,
|
|
2252
|
+
array: false
|
|
2253
|
+
},
|
|
2254
|
+
{
|
|
2255
|
+
name: "merkle_root",
|
|
2256
|
+
count: 1,
|
|
2257
|
+
array: false
|
|
2258
|
+
},
|
|
2259
|
+
{
|
|
2260
|
+
name: "nullifier",
|
|
2261
|
+
count: 1,
|
|
2262
|
+
array: false
|
|
2263
|
+
},
|
|
2264
|
+
{
|
|
2265
|
+
name: "amount",
|
|
2266
|
+
count: 1,
|
|
2267
|
+
array: false
|
|
2268
|
+
},
|
|
2269
|
+
{
|
|
2270
|
+
name: "deadline",
|
|
2271
|
+
count: 1,
|
|
2272
|
+
array: false
|
|
2273
|
+
},
|
|
2274
|
+
{
|
|
2275
|
+
name: "auth_digest_high",
|
|
2276
|
+
count: 1,
|
|
2277
|
+
array: false
|
|
2278
|
+
},
|
|
2279
|
+
{
|
|
2280
|
+
name: "auth_digest_low",
|
|
2281
|
+
count: 1,
|
|
2282
|
+
array: false
|
|
2283
|
+
}
|
|
2284
|
+
],
|
|
2285
|
+
private: [
|
|
2286
|
+
"public_key_x",
|
|
2287
|
+
"public_key_y",
|
|
2288
|
+
"signature",
|
|
2289
|
+
"spender_payout",
|
|
2290
|
+
"spender_wallet_identity",
|
|
2291
|
+
"owner_wallet_identity",
|
|
2292
|
+
"input_nonce",
|
|
2293
|
+
"expiry",
|
|
2294
|
+
"credit_shared_key",
|
|
2295
|
+
"leaf_index",
|
|
2296
|
+
"merkle_path"
|
|
2297
|
+
]
|
|
2298
|
+
},
|
|
2299
|
+
credit_top_up: {
|
|
2300
|
+
artifactSha256: "fbe662363d9814983f7940f74369117cd6c84783945fbf527b0ed48d011b58a4",
|
|
2301
|
+
keys: {
|
|
2302
|
+
evm: "44436f31414497a708355426da051ee48ba63fdebcb6cfd72347c37c34c98c50"
|
|
2303
|
+
},
|
|
2304
|
+
publicInputCount: 50,
|
|
2305
|
+
public: [
|
|
2306
|
+
{
|
|
2307
|
+
name: "chain_id",
|
|
2308
|
+
count: 1,
|
|
2309
|
+
array: false
|
|
2310
|
+
},
|
|
2311
|
+
{
|
|
2312
|
+
name: "protocol_address",
|
|
2313
|
+
count: 1,
|
|
2314
|
+
array: false
|
|
2315
|
+
},
|
|
2316
|
+
{
|
|
2317
|
+
name: "token_address",
|
|
2318
|
+
count: 1,
|
|
2319
|
+
array: false
|
|
2320
|
+
},
|
|
2321
|
+
{
|
|
2322
|
+
name: "owner_address",
|
|
2323
|
+
count: 1,
|
|
2324
|
+
array: false
|
|
2325
|
+
},
|
|
2326
|
+
{
|
|
2327
|
+
name: "actual_count",
|
|
2328
|
+
count: 1,
|
|
2329
|
+
array: false
|
|
2330
|
+
},
|
|
2331
|
+
{
|
|
2332
|
+
name: "source_count",
|
|
2333
|
+
count: 1,
|
|
2334
|
+
array: false
|
|
2335
|
+
},
|
|
2336
|
+
{
|
|
2337
|
+
name: "input_tree_ids",
|
|
2338
|
+
count: 10,
|
|
2339
|
+
array: true
|
|
2340
|
+
},
|
|
2341
|
+
{
|
|
2342
|
+
name: "merkle_roots",
|
|
2343
|
+
count: 10,
|
|
2344
|
+
array: true
|
|
2345
|
+
},
|
|
2346
|
+
{
|
|
2347
|
+
name: "nullifiers",
|
|
2348
|
+
count: 10,
|
|
2349
|
+
array: true
|
|
2350
|
+
},
|
|
2351
|
+
{
|
|
2352
|
+
name: "credit_commitment",
|
|
2353
|
+
count: 1,
|
|
2354
|
+
array: false
|
|
2355
|
+
},
|
|
2356
|
+
{
|
|
2357
|
+
name: "change_commitment",
|
|
2358
|
+
count: 1,
|
|
2359
|
+
array: false
|
|
2360
|
+
},
|
|
2361
|
+
{
|
|
2362
|
+
name: "delivery_hash_high",
|
|
2363
|
+
count: 1,
|
|
2364
|
+
array: false
|
|
2365
|
+
},
|
|
2366
|
+
{
|
|
2367
|
+
name: "delivery_hash_low",
|
|
2368
|
+
count: 1,
|
|
2369
|
+
array: false
|
|
2370
|
+
},
|
|
2371
|
+
{
|
|
2372
|
+
name: "expiry",
|
|
2373
|
+
count: 1,
|
|
2374
|
+
array: false
|
|
2375
|
+
},
|
|
2376
|
+
{
|
|
2377
|
+
name: "deadline",
|
|
2378
|
+
count: 1,
|
|
2379
|
+
array: false
|
|
2380
|
+
},
|
|
2381
|
+
{
|
|
2382
|
+
name: "deposit_amount",
|
|
2383
|
+
count: 1,
|
|
2384
|
+
array: false
|
|
2385
|
+
},
|
|
2386
|
+
{
|
|
2387
|
+
name: "deposit_payer",
|
|
2388
|
+
count: 1,
|
|
2389
|
+
array: false
|
|
2390
|
+
},
|
|
2391
|
+
{
|
|
2392
|
+
name: "credit_tree_id",
|
|
2393
|
+
count: 1,
|
|
2394
|
+
array: false
|
|
2395
|
+
},
|
|
2396
|
+
{
|
|
2397
|
+
name: "credit_merkle_root",
|
|
2398
|
+
count: 1,
|
|
2399
|
+
array: false
|
|
2400
|
+
},
|
|
2401
|
+
{
|
|
2402
|
+
name: "credit_nullifier",
|
|
2403
|
+
count: 1,
|
|
2404
|
+
array: false
|
|
2405
|
+
},
|
|
2406
|
+
{
|
|
2407
|
+
name: "previous_expiry",
|
|
2408
|
+
count: 1,
|
|
2409
|
+
array: false
|
|
2410
|
+
},
|
|
2411
|
+
{
|
|
2412
|
+
name: "auth_digest_high",
|
|
2413
|
+
count: 1,
|
|
2414
|
+
array: false
|
|
2415
|
+
},
|
|
2416
|
+
{
|
|
2417
|
+
name: "auth_digest_low",
|
|
2418
|
+
count: 1,
|
|
2419
|
+
array: false
|
|
2420
|
+
}
|
|
2421
|
+
],
|
|
2422
|
+
private: [
|
|
2423
|
+
"input_amounts",
|
|
2424
|
+
"input_nonces",
|
|
2425
|
+
"leaf_indices",
|
|
2426
|
+
"merkle_paths",
|
|
2427
|
+
"input_source_indices",
|
|
2428
|
+
"public_key_x",
|
|
2429
|
+
"public_key_y",
|
|
2430
|
+
"signature",
|
|
2431
|
+
"spender_payout",
|
|
2432
|
+
"spender_wallet_identity",
|
|
2433
|
+
"owner_wallet_identity",
|
|
2434
|
+
"credit_amount",
|
|
2435
|
+
"credit_nonce",
|
|
2436
|
+
"credit_shared_key",
|
|
2437
|
+
"change_amount",
|
|
2438
|
+
"change_nonce",
|
|
2439
|
+
"previous_credit_amount",
|
|
2440
|
+
"previous_credit_nonce",
|
|
2441
|
+
"previous_credit_leaf_index",
|
|
2442
|
+
"previous_credit_merkle_path"
|
|
2443
|
+
]
|
|
2444
|
+
},
|
|
2445
|
+
wallet_registration: {
|
|
2446
|
+
artifactSha256: "65c3d429f6bc9735af3136f7c383214c2eb222cd32655791f37f7ae5dd428048",
|
|
2447
|
+
keys: {
|
|
2448
|
+
evm: "b8171bdb558489c75293ee71f64c1ac534f533ae3b3f71107378e46dbd93dd48"
|
|
2449
|
+
},
|
|
2450
|
+
publicInputCount: 3,
|
|
2451
|
+
public: [
|
|
2452
|
+
{
|
|
2453
|
+
name: "wallet_identity",
|
|
2454
|
+
count: 1,
|
|
2455
|
+
array: false
|
|
2456
|
+
},
|
|
2457
|
+
{
|
|
2458
|
+
name: "auth_digest_high",
|
|
2459
|
+
count: 1,
|
|
2460
|
+
array: false
|
|
2461
|
+
},
|
|
2462
|
+
{
|
|
2463
|
+
name: "auth_digest_low",
|
|
2464
|
+
count: 1,
|
|
2465
|
+
array: false
|
|
2466
|
+
}
|
|
2467
|
+
],
|
|
2468
|
+
private: [
|
|
2469
|
+
"public_key_x",
|
|
2470
|
+
"public_key_y",
|
|
2471
|
+
"signature"
|
|
2472
|
+
]
|
|
2473
|
+
}
|
|
2474
|
+
};
|
|
2475
|
+
|
|
2476
|
+
// src/witness.ts
|
|
2477
|
+
var pad2 = (values, count, zero) => {
|
|
2478
|
+
if (values.length > count) throw new Error("witness capacity exceeded");
|
|
2479
|
+
return [...values, ...Array.from({ length: count - values.length }, zero)];
|
|
2480
|
+
};
|
|
2481
|
+
var zeros = () => Array(16).fill(0n);
|
|
2482
|
+
var zeroAuthority = () => ({
|
|
2483
|
+
public_key_x: Array(32).fill(0),
|
|
2484
|
+
public_key_y: Array(32).fill(0),
|
|
2485
|
+
signature: Array(64).fill(0)
|
|
2486
|
+
});
|
|
2487
|
+
function check(ok, message) {
|
|
2488
|
+
if (!ok) throw new Error(message);
|
|
2489
|
+
}
|
|
2490
|
+
function provingRequest(circuitName, privateInputs, expectedPublicInputs, target = "evm") {
|
|
2491
|
+
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
2492
|
+
check(typeof key === "string", "unpublished proof target");
|
|
2493
|
+
check(
|
|
2494
|
+
expectedPublicInputs.length === schema.publicInputCount,
|
|
2495
|
+
"public input order/width mismatch"
|
|
2496
|
+
);
|
|
2497
|
+
check(
|
|
2498
|
+
Object.keys(privateInputs).length === schema.private.length && schema.private.every((name) => Object.hasOwn(privateInputs, name)),
|
|
2499
|
+
"private witness schema mismatch"
|
|
2500
|
+
);
|
|
2501
|
+
let offset = 0;
|
|
2502
|
+
const publicInputs = {};
|
|
2503
|
+
for (const entry of schema.public) {
|
|
2504
|
+
const values = expectedPublicInputs.slice(offset, offset + entry.count).map((value) => {
|
|
2505
|
+
const n = BigInt(value);
|
|
2506
|
+
check(n >= 0n && n < FIELD_MODULUS, "noncanonical public input");
|
|
2507
|
+
return n;
|
|
2508
|
+
});
|
|
2509
|
+
publicInputs[entry.name] = entry.array ? values : values[0];
|
|
2510
|
+
offset += entry.count;
|
|
2511
|
+
}
|
|
2512
|
+
check(offset === expectedPublicInputs.length, "public input layout mismatch");
|
|
2513
|
+
return {
|
|
2514
|
+
circuitName,
|
|
2515
|
+
target,
|
|
2516
|
+
artifactSha256: schema.artifactSha256,
|
|
2517
|
+
vkSha256: key,
|
|
2518
|
+
expectedPublicInputs: [...expectedPublicInputs],
|
|
2519
|
+
witness: new LocalWitness({ ...privateInputs, ...publicInputs })
|
|
2520
|
+
};
|
|
2521
|
+
}
|
|
2522
|
+
var WitnessBuilder = class {
|
|
2523
|
+
#protocol;
|
|
2524
|
+
constructor(protocol) {
|
|
2525
|
+
this.#protocol = protocol;
|
|
2526
|
+
}
|
|
2527
|
+
static statement(circuitName, expectedPublicInputs, target = "evm") {
|
|
2528
|
+
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
2529
|
+
check(
|
|
2530
|
+
typeof key === "string" && expectedPublicInputs.length === schema.publicInputCount,
|
|
2531
|
+
"unpublished target or statement width mismatch"
|
|
2532
|
+
);
|
|
2533
|
+
return {
|
|
2534
|
+
circuitName,
|
|
2535
|
+
target,
|
|
2536
|
+
artifactSha256: schema.artifactSha256,
|
|
2537
|
+
vkSha256: key,
|
|
2538
|
+
expectedPublicInputs: [...expectedPublicInputs]
|
|
2539
|
+
};
|
|
2540
|
+
}
|
|
2541
|
+
context(note) {
|
|
2542
|
+
const c = this.#protocol.context;
|
|
2543
|
+
check(
|
|
2544
|
+
note.chainId === c.chainId && note.protocolAddress === BigInt(c.protocolAddress) && note.tokenAddress === BigInt(c.tokenAddress),
|
|
2545
|
+
"note context mismatch"
|
|
2546
|
+
);
|
|
2547
|
+
}
|
|
2548
|
+
async authority(operation, capacity, words, signed, identity) {
|
|
2549
|
+
check(!!signed, "private wallet authorization required");
|
|
2550
|
+
const c = this.#protocol.context, request = {
|
|
2551
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
2552
|
+
operation,
|
|
2553
|
+
capacity,
|
|
2554
|
+
words: words.slice(0, -2).map(BigInt)
|
|
2555
|
+
};
|
|
2556
|
+
check(
|
|
2557
|
+
signed.walletIdentity === identity && signed.digest === computeWalletAuthorizationDigest4(request),
|
|
2558
|
+
"authorization statement mismatch"
|
|
2559
|
+
);
|
|
2560
|
+
const witness = signed.withWitness((value) => value);
|
|
2561
|
+
check(
|
|
2562
|
+
await verifyWalletAuthorization(
|
|
2563
|
+
identity,
|
|
2564
|
+
Uint8Array.from([4, ...witness.public_key_x, ...witness.public_key_y]),
|
|
2565
|
+
Uint8Array.from(witness.signature),
|
|
2566
|
+
request
|
|
2567
|
+
),
|
|
2568
|
+
"invalid wallet authorization"
|
|
2569
|
+
);
|
|
2570
|
+
return witness;
|
|
2571
|
+
}
|
|
2572
|
+
async membership(leaf, input, sources) {
|
|
2573
|
+
const source = sources.findIndex((value) => value.treeId === input.treeId);
|
|
2574
|
+
check(
|
|
2575
|
+
source >= 0 && Number.isInteger(input.leafIndex) && input.leafIndex >= 0 && input.leafIndex < 65536 && input.path.length === 16,
|
|
2576
|
+
"invalid membership position"
|
|
2577
|
+
);
|
|
2578
|
+
let root = BigInt(leaf);
|
|
2579
|
+
for (let level = 0; level < 16; level++)
|
|
2580
|
+
root = BigInt(
|
|
2581
|
+
await poseidonHash(
|
|
2582
|
+
input.leafIndex >> level & 1 ? [input.path[level], root] : [root, input.path[level]]
|
|
2583
|
+
)
|
|
2584
|
+
);
|
|
2585
|
+
check(root === BigInt(sources[source].merkleRoot), "membership root mismatch");
|
|
2586
|
+
return source;
|
|
2587
|
+
}
|
|
2588
|
+
async noteLeaf(note) {
|
|
2589
|
+
this.context(note);
|
|
2590
|
+
return computeNoteCommitment2(
|
|
2591
|
+
note.chainId,
|
|
2592
|
+
await computeNoteIdentity(BigInt(note.walletIdentity), note.nonce),
|
|
2593
|
+
note.tokenAddress,
|
|
2594
|
+
note.amount
|
|
2595
|
+
);
|
|
2596
|
+
}
|
|
2597
|
+
async creditLeaf(note) {
|
|
2598
|
+
this.context(note);
|
|
2599
|
+
return computeCreditCommitment(
|
|
2600
|
+
note.chainId,
|
|
2601
|
+
note.spenderWalletIdentity,
|
|
2602
|
+
note.ownerWalletIdentity,
|
|
2603
|
+
note.spenderPayout,
|
|
2604
|
+
note.ownerPayout,
|
|
2605
|
+
note.tokenAddress,
|
|
2606
|
+
note.amount,
|
|
2607
|
+
note.nonce,
|
|
2608
|
+
note.expiry,
|
|
2609
|
+
await computeCreditSharedKeyHash(note.creditSharedKey)
|
|
2610
|
+
);
|
|
2611
|
+
}
|
|
2612
|
+
async noteInputs(inputs, sources, nullifiers, identity, authority) {
|
|
2613
|
+
check(inputs.length === nullifiers.length, "input count mismatch");
|
|
2614
|
+
return Promise.all(
|
|
2615
|
+
inputs.map(async (input, i) => {
|
|
2616
|
+
check(input.note.walletIdentity === identity, "input wallet mismatch");
|
|
2617
|
+
const leaf = await this.noteLeaf(input.note);
|
|
2618
|
+
check(
|
|
2619
|
+
await computeNoteNullifier(input.note.chainId, input.note.nonce, leaf) === nullifiers[i],
|
|
2620
|
+
"input nullifier mismatch"
|
|
2621
|
+
);
|
|
2622
|
+
return BigInt(await this.membership(leaf, input, sources));
|
|
2623
|
+
})
|
|
2624
|
+
);
|
|
2625
|
+
}
|
|
2626
|
+
async transact(p) {
|
|
2627
|
+
const c = this.#protocol.context, n = normalizeTransactRequest(c, p.params, p.deliveries, p.funding), words = transactUserPublicInputs(c, p.params, p.deliveries, p.funding);
|
|
2628
|
+
check(
|
|
2629
|
+
p.inputs.length === n.inputCount && p.outputs.length === n.outputCount,
|
|
2630
|
+
"note count mismatch"
|
|
2631
|
+
);
|
|
2632
|
+
const identity = p.inputs[0]?.note.walletIdentity;
|
|
2633
|
+
const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
|
|
2634
|
+
const authority = identity && !unsignedSweep ? await this.authority("transact", n.capacity, words, p.authorization, identity) : zeroAuthority();
|
|
2635
|
+
const sources = await this.noteInputs(
|
|
2636
|
+
p.inputs,
|
|
2637
|
+
p.params.sources,
|
|
2638
|
+
p.params.nullifiers,
|
|
2639
|
+
identity ?? "0x" + "00".repeat(32),
|
|
2640
|
+
authority
|
|
2641
|
+
);
|
|
2642
|
+
for (const [i, note] of p.outputs.entries())
|
|
2643
|
+
check(
|
|
2644
|
+
await this.noteLeaf(note) === p.params.outputCommitments[i],
|
|
2645
|
+
"output commitment mismatch"
|
|
2646
|
+
);
|
|
2647
|
+
const all = [...p.inputs.map((input) => input.note), ...p.outputs];
|
|
2648
|
+
return provingRequest(
|
|
2649
|
+
`transact_user_slots${n.capacity}`,
|
|
2650
|
+
{
|
|
2651
|
+
wallet_identity: identity ? BigInt(identity) : 0n,
|
|
2652
|
+
...authority,
|
|
2653
|
+
output_wallet_identities: pad2(
|
|
2654
|
+
[
|
|
2655
|
+
...p.inputs.map(() => 0n),
|
|
2656
|
+
...p.outputs.map((note) => BigInt(note.walletIdentity))
|
|
2657
|
+
],
|
|
2658
|
+
n.capacity,
|
|
2659
|
+
() => 0n
|
|
2660
|
+
),
|
|
2661
|
+
amounts: pad2(
|
|
2662
|
+
all.map((note) => note.amount),
|
|
2663
|
+
n.capacity,
|
|
2664
|
+
() => 0n
|
|
2665
|
+
),
|
|
2666
|
+
nonces: pad2(
|
|
2667
|
+
all.map((note) => note.nonce),
|
|
2668
|
+
n.capacity,
|
|
2669
|
+
() => 0n
|
|
2670
|
+
),
|
|
2671
|
+
leaf_indices: pad2(
|
|
2672
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
2673
|
+
n.capacity,
|
|
2674
|
+
() => 0n
|
|
2675
|
+
),
|
|
2676
|
+
merkle_paths: pad2(
|
|
2677
|
+
p.inputs.map((input) => [...input.path]),
|
|
2678
|
+
n.capacity,
|
|
2679
|
+
zeros
|
|
2680
|
+
),
|
|
2681
|
+
input_source_indices: pad2(sources, n.capacity, () => 0n)
|
|
2682
|
+
},
|
|
2683
|
+
words,
|
|
2684
|
+
p.target
|
|
2685
|
+
);
|
|
2686
|
+
}
|
|
2687
|
+
async creation(p, operation, words) {
|
|
2688
|
+
const state = normalizeCreditDeliveryState(p.state), note = state.note;
|
|
2689
|
+
check(
|
|
2690
|
+
await this.creditLeaf(note) === p.params.creditCommitment && note.ownerPayout === BigInt(p.params.owner) && note.expiry === p.params.expiry,
|
|
2691
|
+
"Credit creation mismatch"
|
|
2692
|
+
);
|
|
2693
|
+
const authority = await this.authority(
|
|
2694
|
+
operation,
|
|
2695
|
+
10,
|
|
2696
|
+
words,
|
|
2697
|
+
p.authorization,
|
|
2698
|
+
note.ownerWalletIdentity
|
|
2699
|
+
);
|
|
2700
|
+
const sources = await this.noteInputs(
|
|
2701
|
+
p.inputs,
|
|
2702
|
+
p.params.sources,
|
|
2703
|
+
p.params.nullifiers,
|
|
2704
|
+
note.ownerWalletIdentity,
|
|
2705
|
+
authority
|
|
2706
|
+
);
|
|
2707
|
+
if (p.change)
|
|
2708
|
+
check(
|
|
2709
|
+
p.change.walletIdentity === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
|
|
2710
|
+
"change commitment mismatch"
|
|
2711
|
+
);
|
|
2712
|
+
else check(BigInt(p.params.changeCommitment) === 0n, "missing change note");
|
|
2713
|
+
return {
|
|
2714
|
+
...authority,
|
|
2715
|
+
input_amounts: pad2(
|
|
2716
|
+
p.inputs.map((input) => input.note.amount),
|
|
2717
|
+
10,
|
|
2718
|
+
() => 0n
|
|
2719
|
+
),
|
|
2720
|
+
input_nonces: pad2(
|
|
2721
|
+
p.inputs.map((input) => input.note.nonce),
|
|
2722
|
+
10,
|
|
2723
|
+
() => 0n
|
|
2724
|
+
),
|
|
2725
|
+
leaf_indices: pad2(
|
|
2726
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
2727
|
+
10,
|
|
2728
|
+
() => 0n
|
|
2729
|
+
),
|
|
2730
|
+
merkle_paths: pad2(
|
|
2731
|
+
p.inputs.map((input) => [...input.path]),
|
|
2732
|
+
10,
|
|
2733
|
+
zeros
|
|
2734
|
+
),
|
|
2735
|
+
input_source_indices: pad2(sources, 10, () => 0n),
|
|
2736
|
+
spender_payout: note.spenderPayout,
|
|
2737
|
+
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
2738
|
+
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
2739
|
+
credit_amount: note.amount,
|
|
2740
|
+
credit_nonce: note.nonce,
|
|
2741
|
+
credit_shared_key: note.creditSharedKey,
|
|
2742
|
+
change_amount: p.change?.amount ?? 0n,
|
|
2743
|
+
change_nonce: p.change?.nonce ?? 0n
|
|
2744
|
+
};
|
|
2745
|
+
}
|
|
2746
|
+
async createCredit(p) {
|
|
2747
|
+
const words = createCreditPublicInputs(
|
|
2748
|
+
this.#protocol.context,
|
|
2749
|
+
p.params,
|
|
2750
|
+
p.deliveries,
|
|
2751
|
+
p.funding
|
|
2752
|
+
);
|
|
2753
|
+
return provingRequest(
|
|
2754
|
+
"create_credit",
|
|
2755
|
+
await this.creation(p, "create-credit", words),
|
|
2756
|
+
words
|
|
2757
|
+
);
|
|
2758
|
+
}
|
|
2759
|
+
async cancelCredit(p) {
|
|
2760
|
+
const note = normalizeCreditDeliveryState(p.input.state).note, leaf = await this.creditLeaf(note), c = this.#protocol.context;
|
|
2761
|
+
check(
|
|
2762
|
+
await computeCreditNullifier(c.chainId, note.creditSharedKey, leaf) === p.params.nullifier && note.amount === p.params.amount && note.ownerPayout === BigInt(p.params.owner),
|
|
2763
|
+
"Credit cancellation mismatch"
|
|
2764
|
+
);
|
|
2765
|
+
await this.membership(leaf, p.input, [p.params.source]);
|
|
2766
|
+
const words = cancelCreditPublicInputs(c, p.params), authority = await this.authority(
|
|
2767
|
+
"cancel-credit",
|
|
2768
|
+
1,
|
|
2769
|
+
words,
|
|
2770
|
+
p.authorization,
|
|
2771
|
+
note.ownerWalletIdentity
|
|
2772
|
+
);
|
|
2773
|
+
return provingRequest(
|
|
2774
|
+
"credit_cancel",
|
|
2775
|
+
{
|
|
2776
|
+
...authority,
|
|
2777
|
+
spender_payout: note.spenderPayout,
|
|
2778
|
+
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
2779
|
+
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
2780
|
+
input_nonce: note.nonce,
|
|
2781
|
+
expiry: note.expiry,
|
|
2782
|
+
credit_shared_key: note.creditSharedKey,
|
|
2783
|
+
leaf_index: BigInt(p.input.leafIndex),
|
|
2784
|
+
merkle_path: [...p.input.path]
|
|
2785
|
+
},
|
|
2786
|
+
words
|
|
2787
|
+
);
|
|
2788
|
+
}
|
|
2789
|
+
async drawCredit(p) {
|
|
2790
|
+
const c = this.#protocol.context, profile = selectCreditDrawCircuit(p.inputs.length), capacity = profile.maxSize;
|
|
2791
|
+
check(
|
|
2792
|
+
p.inputs.length === p.amounts.length && p.inputs.length === p.params.nullifiers.length,
|
|
2793
|
+
"draw input count mismatch"
|
|
2794
|
+
);
|
|
2795
|
+
const notes2 = p.inputs.map((input) => normalizeCreditDeliveryState(input.state).note), identity = notes2[0].spenderWalletIdentity;
|
|
2796
|
+
const words = creditDrawPublicInputs(c, p.params, p.deliveries), authority = await this.authority(
|
|
2797
|
+
"credit-draw",
|
|
2798
|
+
capacity,
|
|
2799
|
+
words,
|
|
2800
|
+
p.authorization,
|
|
2801
|
+
identity
|
|
2802
|
+
);
|
|
2803
|
+
const sourceIndices = await Promise.all(
|
|
2804
|
+
notes2.map(async (note, i) => {
|
|
2805
|
+
const leaf = await this.creditLeaf(note);
|
|
2806
|
+
check(
|
|
2807
|
+
note.spenderWalletIdentity === identity && note.spenderPayout === BigInt(p.params.spender) && note.expiry === p.params.expiries[i] && p.amounts[i] > 0n && p.amounts[i] <= note.amount && await computeCreditNullifier(c.chainId, note.creditSharedKey, leaf) === p.params.nullifiers[i],
|
|
2808
|
+
"Credit draw mismatch"
|
|
2809
|
+
);
|
|
2810
|
+
return BigInt(await this.membership(leaf, p.inputs[i], p.params.sources));
|
|
2811
|
+
})
|
|
2812
|
+
);
|
|
2813
|
+
return provingRequest(
|
|
2814
|
+
profile.name,
|
|
2815
|
+
{
|
|
2816
|
+
...authority,
|
|
2817
|
+
spender_wallet_identity: BigInt(identity),
|
|
2818
|
+
owner_payouts: pad2(
|
|
2819
|
+
notes2.map((note) => note.ownerPayout),
|
|
2820
|
+
capacity,
|
|
2821
|
+
() => 0n
|
|
2822
|
+
),
|
|
2823
|
+
owner_wallet_identities: pad2(
|
|
2824
|
+
notes2.map((note) => BigInt(note.ownerWalletIdentity)),
|
|
2825
|
+
capacity,
|
|
2826
|
+
() => 0n
|
|
2827
|
+
),
|
|
2828
|
+
input_amounts: pad2(
|
|
2829
|
+
notes2.map((note) => note.amount),
|
|
2830
|
+
capacity,
|
|
2831
|
+
() => 0n
|
|
2832
|
+
),
|
|
2833
|
+
input_nonces: pad2(
|
|
2834
|
+
notes2.map((note) => note.nonce),
|
|
2835
|
+
capacity,
|
|
2836
|
+
() => 0n
|
|
2837
|
+
),
|
|
2838
|
+
credit_shared_keys: pad2(
|
|
2839
|
+
notes2.map((note) => note.creditSharedKey),
|
|
2840
|
+
capacity,
|
|
2841
|
+
() => 0n
|
|
2842
|
+
),
|
|
2843
|
+
leaf_indices: pad2(
|
|
2844
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
2845
|
+
capacity,
|
|
2846
|
+
() => 0n
|
|
2847
|
+
),
|
|
2848
|
+
merkle_paths: pad2(
|
|
2849
|
+
p.inputs.map((input) => [...input.path]),
|
|
2850
|
+
capacity,
|
|
2851
|
+
zeros
|
|
2852
|
+
),
|
|
2853
|
+
input_source_indices: pad2(sourceIndices, capacity, () => 0n),
|
|
2854
|
+
draw_amounts: pad2(p.amounts, capacity, () => 0n)
|
|
2855
|
+
},
|
|
2856
|
+
words
|
|
2857
|
+
);
|
|
2858
|
+
}
|
|
2859
|
+
async topUpCredit(p) {
|
|
2860
|
+
const c = this.#protocol.context, previous = normalizeCreditDeliveryState(p.previous.state), next = normalizeCreditDeliveryState(p.state), old = previous.note, note = next.note, leaf = await this.creditLeaf(old);
|
|
2861
|
+
for (const field2 of [
|
|
2862
|
+
"spenderWalletIdentity",
|
|
2863
|
+
"ownerWalletIdentity",
|
|
2864
|
+
"spenderPayout",
|
|
2865
|
+
"ownerPayout",
|
|
2866
|
+
"creditSharedKey"
|
|
2867
|
+
])
|
|
2868
|
+
check(old[field2] === note[field2], "Credit role or payout changed");
|
|
2869
|
+
check(
|
|
2870
|
+
JSON.stringify(previous.ownerReceivingKeys) === JSON.stringify(next.ownerReceivingKeys) && JSON.stringify(previous.spenderReceivingKeys) === JSON.stringify(next.spenderReceivingKeys),
|
|
2871
|
+
"Credit receiving snapshots changed"
|
|
2872
|
+
);
|
|
2873
|
+
check(
|
|
2874
|
+
old.amount < note.amount && old.expiry <= note.expiry && old.expiry === p.params.previousExpiry && (c.now === void 0 || old.expiry > c.now),
|
|
2875
|
+
"invalid Credit top-up"
|
|
2876
|
+
);
|
|
2877
|
+
check(
|
|
2878
|
+
await computeCreditNullifier(c.chainId, old.creditSharedKey, leaf) === p.params.creditNullifier,
|
|
2879
|
+
"previous Credit nullifier mismatch"
|
|
2880
|
+
);
|
|
2881
|
+
await this.membership(leaf, p.previous, [p.params.creditSource]);
|
|
2882
|
+
const words = topUpCreditPublicInputs(c, p.params, p.deliveries, p.funding), base = await this.creation({ ...p, params: p.params.creation }, "top-up-credit", words);
|
|
2883
|
+
return provingRequest(
|
|
2884
|
+
"credit_top_up",
|
|
2885
|
+
{
|
|
2886
|
+
...base,
|
|
2887
|
+
previous_credit_amount: old.amount,
|
|
2888
|
+
previous_credit_nonce: old.nonce,
|
|
2889
|
+
previous_credit_leaf_index: BigInt(p.previous.leafIndex),
|
|
2890
|
+
previous_credit_merkle_path: [...p.previous.path]
|
|
2891
|
+
},
|
|
2892
|
+
words
|
|
2893
|
+
);
|
|
2894
|
+
}
|
|
2895
|
+
static async registration(context, registration, authorization, options) {
|
|
2896
|
+
const request = registrationAuthorizationRequest(context, registration, options), words = registrationPublicInputs(context, registration, options);
|
|
2897
|
+
check(
|
|
2898
|
+
authorization.walletIdentity === registration.walletIdentity && authorization.digest === computeWalletAuthorizationDigest4(request),
|
|
2899
|
+
"registry authorization mismatch"
|
|
2900
|
+
);
|
|
2901
|
+
const witness = authorization.withWitness((value) => value);
|
|
2902
|
+
check(
|
|
2903
|
+
await verifyWalletAuthorization(
|
|
2904
|
+
registration.walletIdentity,
|
|
2905
|
+
Uint8Array.from([4, ...witness.public_key_x, ...witness.public_key_y]),
|
|
2906
|
+
Uint8Array.from(witness.signature),
|
|
2907
|
+
request
|
|
2908
|
+
),
|
|
2909
|
+
"invalid registry authority"
|
|
2910
|
+
);
|
|
2911
|
+
return provingRequest("wallet_registration", { ...witness }, words);
|
|
2912
|
+
}
|
|
2913
|
+
};
|
|
2914
|
+
|
|
2915
|
+
// src/RegistrationOperation.ts
|
|
2916
|
+
function check2(ok, message) {
|
|
2917
|
+
if (!ok) {
|
|
2918
|
+
throw new Error(message);
|
|
2919
|
+
}
|
|
2920
|
+
}
|
|
2921
|
+
function publicProof(bundle) {
|
|
2922
|
+
return {
|
|
2923
|
+
formatVersion: bundle.formatVersion,
|
|
2924
|
+
bbVersion: bundle.bbVersion,
|
|
2925
|
+
circuitName: bundle.circuitName,
|
|
2926
|
+
target: bundle.target,
|
|
2927
|
+
artifactSha256: bundle.artifactSha256,
|
|
2928
|
+
vkSha256: bundle.vkSha256,
|
|
2929
|
+
proofHex: bundle.proofHex,
|
|
2930
|
+
proofSha256: bundle.proofSha256,
|
|
2931
|
+
publicInputs: [...bundle.publicInputs]
|
|
2932
|
+
};
|
|
2933
|
+
}
|
|
2934
|
+
var RegistrationOperation = class _RegistrationOperation {
|
|
2935
|
+
#registry;
|
|
2936
|
+
#runtime;
|
|
2937
|
+
#plan;
|
|
2938
|
+
#authorization;
|
|
2939
|
+
#proof;
|
|
2940
|
+
#hash;
|
|
2941
|
+
#anchor;
|
|
2942
|
+
status;
|
|
2943
|
+
constructor(registry, runtime, plan, status, authorization, proof, hash, anchor) {
|
|
2944
|
+
this.#registry = registry;
|
|
2945
|
+
this.#runtime = { ...runtime };
|
|
2946
|
+
this.#plan = structuredClone(plan);
|
|
2947
|
+
this.status = status;
|
|
2948
|
+
this.#authorization = authorization;
|
|
2949
|
+
this.#proof = proof ? publicProof(proof) : void 0;
|
|
2950
|
+
this.#hash = hash;
|
|
2951
|
+
this.#anchor = anchor ? { ...anchor } : void 0;
|
|
2952
|
+
Object.freeze(this);
|
|
2953
|
+
}
|
|
2954
|
+
static async prepare(registry, options) {
|
|
2955
|
+
const runtime = { ...options };
|
|
2956
|
+
const update = options.update ?? false;
|
|
2957
|
+
check2(typeof update === "boolean", "update must be boolean");
|
|
2958
|
+
await registry.validateDeployment(runtime.reader);
|
|
2959
|
+
const block = await runtime.reader.getBlock(await runtime.reader.getLatestBlockNumber());
|
|
2960
|
+
const context = { ...registry.context, now: block.timestamp };
|
|
2961
|
+
const nonce = await runtime.reader.getRegistryNonce(
|
|
2962
|
+
context,
|
|
2963
|
+
runtime.wallet.walletIdentity,
|
|
2964
|
+
block
|
|
2965
|
+
);
|
|
2966
|
+
check2(
|
|
2967
|
+
typeof nonce === "bigint" && nonce >= 0n && nonce < (1n << 64n) - 1n,
|
|
2968
|
+
"invalid or exhausted registry nonce"
|
|
2969
|
+
);
|
|
2970
|
+
check2(
|
|
2971
|
+
update ? nonce > 0n : nonce === 0n,
|
|
2972
|
+
update ? "wallet is not registered" : "wallet is already registered; prepare an update"
|
|
2973
|
+
);
|
|
2974
|
+
const address = ReceivingAddress2.parse(await registry.resolve(runtime.wallet.getAddress()));
|
|
2975
|
+
const keys = address.getReceivingKeys();
|
|
2976
|
+
const registration = {
|
|
2977
|
+
walletIdentity: runtime.wallet.walletIdentity,
|
|
2978
|
+
keys: {
|
|
2979
|
+
viewingPublicKey: hexlify2(keys.viewingPublicKey),
|
|
2980
|
+
clueKey: hexlify2(keys.clueKey)
|
|
2981
|
+
},
|
|
2982
|
+
nonce,
|
|
2983
|
+
deadline: options.deadline ?? block.timestamp + 300n
|
|
2984
|
+
};
|
|
2985
|
+
const words = registrationPublicInputs(context, registration, {
|
|
2986
|
+
update,
|
|
2987
|
+
expectedNonce: nonce
|
|
2988
|
+
});
|
|
2989
|
+
const statement = WitnessBuilder.statement("wallet_registration", words);
|
|
2990
|
+
check2(
|
|
2991
|
+
(await runtime.reader.getBlock(block.number)).hash === block.hash,
|
|
2992
|
+
"canonical registry block changed while preparing"
|
|
2993
|
+
);
|
|
2994
|
+
return new _RegistrationOperation(
|
|
2995
|
+
registry,
|
|
2996
|
+
runtime,
|
|
2997
|
+
{ id: crypto.randomUUID(), context, registration, update, statement },
|
|
2998
|
+
"prepared"
|
|
2999
|
+
);
|
|
3000
|
+
}
|
|
3001
|
+
get id() {
|
|
3002
|
+
return this.#plan.id;
|
|
3003
|
+
}
|
|
3004
|
+
preview() {
|
|
3005
|
+
return {
|
|
3006
|
+
id: this.id,
|
|
3007
|
+
status: this.status,
|
|
3008
|
+
chainId: this.#plan.context.chainId,
|
|
3009
|
+
registryAddress: this.#plan.context.registryAddress,
|
|
3010
|
+
...structuredClone(this.#plan.registration),
|
|
3011
|
+
update: this.#plan.update
|
|
3012
|
+
};
|
|
3013
|
+
}
|
|
3014
|
+
async authorize(options = {}) {
|
|
3015
|
+
check2(
|
|
3016
|
+
this.status === "prepared" || this.status === "authorized",
|
|
3017
|
+
"registry operation is not awaiting authorization"
|
|
3018
|
+
);
|
|
3019
|
+
options.signal?.throwIfAborted();
|
|
3020
|
+
const provider = this.#runtime.authorization ?? this.#runtime.wallet.exportAuthorization();
|
|
3021
|
+
const p = this.#plan;
|
|
3022
|
+
check2(
|
|
3023
|
+
provider.walletIdentity === p.registration.walletIdentity,
|
|
3024
|
+
"registry wallet authorization capability mismatch"
|
|
3025
|
+
);
|
|
3026
|
+
const request = registrationAuthorizationRequest(p.context, p.registration, {
|
|
3027
|
+
update: p.update,
|
|
3028
|
+
expectedNonce: p.registration.nonce
|
|
3029
|
+
});
|
|
3030
|
+
const authorization = await provider.authorize(request);
|
|
3031
|
+
check2(
|
|
3032
|
+
authorization.walletIdentity === provider.walletIdentity && authorization.digest === computeWalletAuthorizationDigest5(request),
|
|
3033
|
+
"registry authorization statement mismatch"
|
|
3034
|
+
);
|
|
3035
|
+
options.signal?.throwIfAborted();
|
|
3036
|
+
return new _RegistrationOperation(
|
|
3037
|
+
this.#registry,
|
|
3038
|
+
this.#runtime,
|
|
3039
|
+
p,
|
|
3040
|
+
"authorized",
|
|
3041
|
+
authorization
|
|
3042
|
+
);
|
|
3043
|
+
}
|
|
3044
|
+
async prove(options = {}) {
|
|
3045
|
+
check2(
|
|
3046
|
+
this.status === "authorized" && this.#authorization,
|
|
3047
|
+
"private registry authorization required"
|
|
3048
|
+
);
|
|
3049
|
+
const prover = this.#runtime.prover;
|
|
3050
|
+
if (!prover) {
|
|
3051
|
+
throw new MissingCapabilityError("registry prover");
|
|
3052
|
+
}
|
|
3053
|
+
const p = this.#plan;
|
|
3054
|
+
const request = await WitnessBuilder.registration(
|
|
3055
|
+
p.context,
|
|
3056
|
+
p.registration,
|
|
3057
|
+
this.#authorization,
|
|
3058
|
+
{ update: p.update, expectedNonce: p.registration.nonce }
|
|
3059
|
+
);
|
|
3060
|
+
check2(
|
|
3061
|
+
JSON.stringify({ ...request, witness: void 0 }) === JSON.stringify(p.statement),
|
|
3062
|
+
"registry proof statement changed"
|
|
3063
|
+
);
|
|
3064
|
+
try {
|
|
3065
|
+
const proof = publicProof(await prover.prove(request, options));
|
|
3066
|
+
const expected = p.statement;
|
|
3067
|
+
check2(
|
|
3068
|
+
proof.formatVersion === 1 && proof.bbVersion === "6.0.0" && proof.circuitName === expected.circuitName && proof.target === expected.target && proof.artifactSha256 === expected.artifactSha256 && proof.vkSha256 === expected.vkSha256 && proof.publicInputs.length === 3 && proof.publicInputs.every(
|
|
3069
|
+
(word2, i) => word2 === expected.expectedPublicInputs[i]
|
|
3070
|
+
),
|
|
3071
|
+
"registry proof release or public statement mismatch"
|
|
3072
|
+
);
|
|
3073
|
+
check2(/^0x(?:[a-fA-F0-9]{2})+$/.test(proof.proofHex), "malformed registry proof");
|
|
3074
|
+
const bytes = Uint8Array.from(
|
|
3075
|
+
proof.proofHex.slice(2).match(/../g),
|
|
3076
|
+
(byte) => parseInt(byte, 16)
|
|
3077
|
+
);
|
|
3078
|
+
const hash = hexlify2(new Uint8Array(await crypto.subtle.digest("SHA-256", bytes))).slice(2);
|
|
3079
|
+
check2(
|
|
3080
|
+
hash === proof.proofSha256 && await prover.verify(publicProof(proof), structuredClone(expected), options),
|
|
3081
|
+
"registry proof verification failed"
|
|
3082
|
+
);
|
|
3083
|
+
options.signal?.throwIfAborted();
|
|
3084
|
+
return new _RegistrationOperation(
|
|
3085
|
+
this.#registry,
|
|
3086
|
+
this.#runtime,
|
|
3087
|
+
p,
|
|
3088
|
+
"ready",
|
|
3089
|
+
void 0,
|
|
3090
|
+
proof
|
|
3091
|
+
);
|
|
3092
|
+
} catch {
|
|
3093
|
+
options.signal?.throwIfAborted();
|
|
3094
|
+
throw new Error("registry proof generation or verification failed");
|
|
3095
|
+
}
|
|
3096
|
+
}
|
|
3097
|
+
call() {
|
|
3098
|
+
check2(this.#proof, "registry proof is missing");
|
|
3099
|
+
const p = this.#plan;
|
|
3100
|
+
const result = buildRegistrationCalldata(p.context, p.registration, this.#proof.proofHex, {
|
|
3101
|
+
update: p.update,
|
|
3102
|
+
expectedNonce: p.registration.nonce
|
|
3103
|
+
});
|
|
3104
|
+
return { to: result.to, data: result.callData, value: result.value };
|
|
3105
|
+
}
|
|
3106
|
+
async exportTransaction() {
|
|
3107
|
+
check2(
|
|
3108
|
+
this.#proof && this.status !== "prepared" && this.status !== "authorized",
|
|
3109
|
+
"registry operation is not ready"
|
|
3110
|
+
);
|
|
3111
|
+
await this.#registry.validateDeployment(this.#runtime.reader);
|
|
3112
|
+
const block = await this.#runtime.reader.getBlock(
|
|
3113
|
+
await this.#runtime.reader.getLatestBlockNumber()
|
|
3114
|
+
);
|
|
3115
|
+
const p = this.#plan;
|
|
3116
|
+
check2(block.timestamp <= p.registration.deadline, "registry operation has expired");
|
|
3117
|
+
check2(
|
|
3118
|
+
await this.#runtime.reader.getRegistryNonce(
|
|
3119
|
+
p.context,
|
|
3120
|
+
p.registration.walletIdentity,
|
|
3121
|
+
block
|
|
3122
|
+
) === p.registration.nonce,
|
|
3123
|
+
"registry nonce changed; prepare again"
|
|
3124
|
+
);
|
|
3125
|
+
return this.call();
|
|
3126
|
+
}
|
|
3127
|
+
/** Associate a signed/broadcast transaction; ethers owns sending and receipt waiting. */
|
|
3128
|
+
trackTransaction(transactionHash) {
|
|
3129
|
+
check2(/^0x[a-fA-F0-9]{64}$/.test(transactionHash), "invalid registry transaction hash");
|
|
3130
|
+
check2(
|
|
3131
|
+
this.#proof && ["ready", "uncertain"].includes(this.status),
|
|
3132
|
+
"registry operation is not ready"
|
|
3133
|
+
);
|
|
3134
|
+
return new _RegistrationOperation(
|
|
3135
|
+
this.#registry,
|
|
3136
|
+
this.#runtime,
|
|
3137
|
+
this.#plan,
|
|
3138
|
+
"uncertain",
|
|
3139
|
+
void 0,
|
|
3140
|
+
this.#proof,
|
|
3141
|
+
transactionHash
|
|
3142
|
+
);
|
|
3143
|
+
}
|
|
3144
|
+
async reconcile(options = {}) {
|
|
3145
|
+
options.signal?.throwIfAborted();
|
|
3146
|
+
const { reader } = this.#runtime;
|
|
3147
|
+
const p = this.#plan;
|
|
3148
|
+
await this.#registry.validateDeployment(reader);
|
|
3149
|
+
if (this.#anchor && (await reader.getBlock(this.#anchor.number)).hash !== this.#anchor.hash) {
|
|
3150
|
+
return new _RegistrationOperation(
|
|
3151
|
+
this.#registry,
|
|
3152
|
+
this.#runtime,
|
|
3153
|
+
p,
|
|
3154
|
+
"reorged",
|
|
3155
|
+
void 0,
|
|
3156
|
+
this.#proof,
|
|
3157
|
+
this.#hash
|
|
3158
|
+
);
|
|
3159
|
+
}
|
|
3160
|
+
const hash = options.transactionHash ?? this.#hash;
|
|
3161
|
+
const receipt = hash ? await reader.getReceipt(hash) : null;
|
|
3162
|
+
if (receipt) {
|
|
3163
|
+
check2(
|
|
3164
|
+
receipt.transactionHash === hash && (await reader.getBlock(receipt.block.number)).hash === receipt.block.hash,
|
|
3165
|
+
"registry receipt is not canonical"
|
|
3166
|
+
);
|
|
3167
|
+
const transaction = await reader.getTransaction(hash);
|
|
3168
|
+
const call = this.call();
|
|
3169
|
+
check2(
|
|
3170
|
+
transaction && transaction.transactionHash === hash && transaction.to.toLowerCase() === call.to.toLowerCase() && transaction.data.toLowerCase() === call.data.toLowerCase() && transaction.value === 0n,
|
|
3171
|
+
"registry transaction differs from frozen request"
|
|
3172
|
+
);
|
|
3173
|
+
check2(
|
|
3174
|
+
receipt.status === "success" || receipt.status === "reverted",
|
|
3175
|
+
"registry execution status is missing"
|
|
3176
|
+
);
|
|
3177
|
+
if (receipt.status === "success") {
|
|
3178
|
+
const found = receipt.logs.some((log) => {
|
|
3179
|
+
if (log.address.toLowerCase() !== p.context.registryAddress.toLowerCase() || log.transactionHash !== hash) {
|
|
3180
|
+
return false;
|
|
3181
|
+
}
|
|
3182
|
+
try {
|
|
3183
|
+
const event = ((decoded) => ({
|
|
3184
|
+
eventName: decoded.name,
|
|
3185
|
+
args: decoded.args.toObject()
|
|
3186
|
+
}))(
|
|
3187
|
+
new Interface5(invisiAddressRegistryAbi).parseLog({
|
|
3188
|
+
data: log.data,
|
|
3189
|
+
topics: log.topics
|
|
3190
|
+
})
|
|
3191
|
+
);
|
|
3192
|
+
return event.eventName === "ReceivingKeysSet" && BigInt(event.args.walletIdentity) === BigInt(p.registration.walletIdentity) && event.args.viewingPublicKey.toLowerCase() === p.registration.keys.viewingPublicKey.toLowerCase() && event.args.clueKey.toLowerCase() === p.registration.keys.clueKey.toLowerCase() && event.args.nextNonce === p.registration.nonce + 1n;
|
|
3193
|
+
} catch {
|
|
3194
|
+
return false;
|
|
3195
|
+
}
|
|
3196
|
+
});
|
|
3197
|
+
check2(found, "registry receipt has no matching key update event");
|
|
3198
|
+
check2(
|
|
3199
|
+
(await reader.getBlock(receipt.block.number)).hash === receipt.block.hash,
|
|
3200
|
+
"registry block changed during confirmation"
|
|
3201
|
+
);
|
|
3202
|
+
options.signal?.throwIfAborted();
|
|
3203
|
+
return new _RegistrationOperation(
|
|
3204
|
+
this.#registry,
|
|
3205
|
+
this.#runtime,
|
|
3206
|
+
p,
|
|
3207
|
+
"confirmed",
|
|
3208
|
+
void 0,
|
|
3209
|
+
this.#proof,
|
|
3210
|
+
hash,
|
|
3211
|
+
receipt.block
|
|
3212
|
+
);
|
|
3213
|
+
}
|
|
3214
|
+
}
|
|
3215
|
+
const head = await reader.getBlock(await reader.getLatestBlockNumber());
|
|
3216
|
+
const nonce = await reader.getRegistryNonce(p.context, p.registration.walletIdentity, head);
|
|
3217
|
+
check2(
|
|
3218
|
+
(await reader.getBlock(head.number)).hash === head.hash,
|
|
3219
|
+
"canonical registry block changed during reconciliation"
|
|
3220
|
+
);
|
|
3221
|
+
return new _RegistrationOperation(
|
|
3222
|
+
this.#registry,
|
|
3223
|
+
this.#runtime,
|
|
3224
|
+
p,
|
|
3225
|
+
head.timestamp > p.registration.deadline ? "expired" : nonce !== p.registration.nonce ? "failed" : "uncertain",
|
|
3226
|
+
void 0,
|
|
3227
|
+
this.#proof,
|
|
3228
|
+
hash
|
|
3229
|
+
);
|
|
3230
|
+
}
|
|
3231
|
+
toJSON() {
|
|
3232
|
+
return {
|
|
3233
|
+
id: this.id,
|
|
3234
|
+
kind: this.#plan.update ? "update-address" : "register-address",
|
|
3235
|
+
status: this.status
|
|
3236
|
+
};
|
|
3237
|
+
}
|
|
3238
|
+
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
3239
|
+
return this.toJSON();
|
|
3240
|
+
}
|
|
3241
|
+
};
|
|
3242
|
+
|
|
3243
|
+
// src/AddressRegistry.ts
|
|
3244
|
+
var AddressRegistry = class {
|
|
3245
|
+
context;
|
|
3246
|
+
#lookup;
|
|
3247
|
+
expectedRuntimeCodeHash;
|
|
3248
|
+
constructor(context, options = {}) {
|
|
3249
|
+
if (typeof context.chainId !== "bigint" || context.chainId < 0n || context.chainId >= 1n << 64n || BigInt(getAddress6(context.registryAddress)) === 0n) {
|
|
3250
|
+
throw new Error("invalid registry context");
|
|
3251
|
+
}
|
|
3252
|
+
this.context = Object.freeze({
|
|
3253
|
+
...context,
|
|
3254
|
+
registryAddress: getAddress6(context.registryAddress)
|
|
3255
|
+
});
|
|
3256
|
+
this.#lookup = options.lookup;
|
|
3257
|
+
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
3258
|
+
if (this.expectedRuntimeCodeHash && !/^0x[0-9a-f]{64}$/.test(this.expectedRuntimeCodeHash)) {
|
|
3259
|
+
throw new Error("invalid registry runtime profile");
|
|
3260
|
+
}
|
|
3261
|
+
Object.freeze(this);
|
|
3262
|
+
}
|
|
3263
|
+
async validateDeployment(reader) {
|
|
3264
|
+
if (!this.expectedRuntimeCodeHash) {
|
|
3265
|
+
throw new MissingCapabilityError2("trusted registry deployment profile");
|
|
3266
|
+
}
|
|
3267
|
+
if (await reader.getChainId() !== this.context.chainId) {
|
|
3268
|
+
throw new Error("registry chain mismatch");
|
|
3269
|
+
}
|
|
3270
|
+
const code = await reader.getCode(this.context.registryAddress);
|
|
3271
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || keccak2566(code) !== this.expectedRuntimeCodeHash) {
|
|
3272
|
+
throw new Error("registry runtime profile mismatch");
|
|
3273
|
+
}
|
|
3274
|
+
}
|
|
3275
|
+
prepareRegistration(options) {
|
|
3276
|
+
return RegistrationOperation.prepare(this, options);
|
|
3277
|
+
}
|
|
3278
|
+
async resolve(address) {
|
|
3279
|
+
const receiving = ReceivingAddress3.parse(address);
|
|
3280
|
+
if (receiving.kind === "short" && !this.#lookup) {
|
|
3281
|
+
throw new MissingCapabilityError2("registry reader");
|
|
3282
|
+
}
|
|
3283
|
+
return (await receiving.resolve(this.#lookup)).toString();
|
|
3284
|
+
}
|
|
3285
|
+
authorization(registration, options) {
|
|
3286
|
+
return registrationAuthorizationRequest(this.context, registration, options);
|
|
3287
|
+
}
|
|
3288
|
+
publicInputs(registration, options) {
|
|
3289
|
+
return registrationPublicInputs(this.context, registration, options);
|
|
3290
|
+
}
|
|
3291
|
+
buildCall(registration, proof, options) {
|
|
3292
|
+
return buildRegistrationCalldata(this.context, registration, proof, options);
|
|
3293
|
+
}
|
|
3294
|
+
};
|
|
3295
|
+
|
|
3296
|
+
// src/Protocol.ts
|
|
3297
|
+
import { Contract as Contract2, getAddress as getAddress7, keccak256 as keccak2568 } from "ethers";
|
|
3298
|
+
import {
|
|
3299
|
+
defineDeployment
|
|
3300
|
+
} from "@invisi-labs/rpc";
|
|
3301
|
+
|
|
3302
|
+
// src/TokenProtocol.ts
|
|
3303
|
+
import { keccak256 as keccak2567 } from "ethers";
|
|
3304
|
+
import { MissingCapabilityError as MissingCapabilityError3 } from "@invisi-labs/core";
|
|
3305
|
+
var TokenProtocol = class {
|
|
3306
|
+
context;
|
|
3307
|
+
expectedRuntimeCodeHash;
|
|
3308
|
+
constructor(context, options = {}) {
|
|
3309
|
+
const normalized = normalizeContext(context);
|
|
3310
|
+
if (BigInt(normalized.protocolAddress) === 0n || BigInt(normalized.tokenAddress) === 0n) {
|
|
3311
|
+
throw new Error("deployment addresses must be nonzero");
|
|
3312
|
+
}
|
|
3313
|
+
if (options.expectedRuntimeCodeHash && !/^0x[0-9a-fA-F]{64}$/.test(options.expectedRuntimeCodeHash)) {
|
|
3314
|
+
throw new Error("invalid runtime code hash");
|
|
3315
|
+
}
|
|
3316
|
+
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
3317
|
+
this.context = Object.freeze(normalized);
|
|
3318
|
+
Object.freeze(this);
|
|
3319
|
+
}
|
|
3320
|
+
async validateDeployment(reader, options = {}) {
|
|
3321
|
+
if ((options.requireRuntimeProfile ?? true) && !this.expectedRuntimeCodeHash) {
|
|
3322
|
+
throw new MissingCapabilityError3("trusted deployment profile");
|
|
3323
|
+
}
|
|
3324
|
+
if (await reader.getChainId() !== this.context.chainId) {
|
|
3325
|
+
throw new Error("deployment chain mismatch");
|
|
3326
|
+
}
|
|
3327
|
+
const code = await reader.getCode(this.context.protocolAddress);
|
|
3328
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || this.expectedRuntimeCodeHash && keccak2567(code) !== this.expectedRuntimeCodeHash) {
|
|
3329
|
+
throw new Error("deployment runtime code profile mismatch");
|
|
3330
|
+
}
|
|
3331
|
+
const tokenCode = await reader.getCode(this.context.tokenAddress);
|
|
3332
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(tokenCode)) {
|
|
3333
|
+
throw new Error("token address must have contract code");
|
|
3334
|
+
}
|
|
3335
|
+
}
|
|
3336
|
+
transact(request) {
|
|
3337
|
+
return {
|
|
3338
|
+
to: this.context.protocolAddress,
|
|
3339
|
+
value: 0n,
|
|
3340
|
+
...buildTransactCalldata({ ...request, context: this.context })
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
aggregate(request) {
|
|
3344
|
+
return {
|
|
3345
|
+
to: this.context.protocolAddress,
|
|
3346
|
+
value: 0n,
|
|
3347
|
+
...buildTransactAggregateCalldata({ ...request, context: this.context })
|
|
3348
|
+
};
|
|
3349
|
+
}
|
|
3350
|
+
async shield(request) {
|
|
3351
|
+
return {
|
|
3352
|
+
to: this.context.protocolAddress,
|
|
3353
|
+
value: 0n,
|
|
3354
|
+
...await buildShieldCalldata({ ...request, context: this.context })
|
|
3355
|
+
};
|
|
3356
|
+
}
|
|
3357
|
+
createCredit(request) {
|
|
3358
|
+
return {
|
|
3359
|
+
to: this.context.protocolAddress,
|
|
3360
|
+
value: 0n,
|
|
3361
|
+
...buildCreateCreditCalldata({ ...request, context: this.context })
|
|
3362
|
+
};
|
|
3363
|
+
}
|
|
3364
|
+
drawCredit(request) {
|
|
3365
|
+
return {
|
|
3366
|
+
to: this.context.protocolAddress,
|
|
3367
|
+
value: 0n,
|
|
3368
|
+
...buildCreditDrawCalldata({ ...request, context: this.context })
|
|
3369
|
+
};
|
|
3370
|
+
}
|
|
3371
|
+
cancelCredit(request) {
|
|
3372
|
+
return {
|
|
3373
|
+
to: this.context.protocolAddress,
|
|
3374
|
+
value: 0n,
|
|
3375
|
+
...buildCancelCreditCalldata({ ...request, context: this.context })
|
|
3376
|
+
};
|
|
3377
|
+
}
|
|
3378
|
+
topUpCredit(request) {
|
|
3379
|
+
return {
|
|
3380
|
+
to: this.context.protocolAddress,
|
|
3381
|
+
value: 0n,
|
|
3382
|
+
...buildTopUpCreditCalldata({ ...request, context: this.context })
|
|
3383
|
+
};
|
|
3384
|
+
}
|
|
3385
|
+
};
|
|
3386
|
+
|
|
3387
|
+
// src/Protocol.ts
|
|
3388
|
+
var Protocol = class _Protocol {
|
|
3389
|
+
deployment;
|
|
3390
|
+
context;
|
|
3391
|
+
constructor(options) {
|
|
3392
|
+
known(options, ["deployment"], "protocol options");
|
|
3393
|
+
this.deployment = defineDeployment(options.deployment);
|
|
3394
|
+
this.context = Object.freeze({
|
|
3395
|
+
chainId: this.deployment.chainId,
|
|
3396
|
+
protocolAddress: this.deployment.protocol.address
|
|
3397
|
+
});
|
|
3398
|
+
Object.freeze(this);
|
|
3399
|
+
}
|
|
3400
|
+
/** Load the selected deployment and verify its contract against Chain RPC before returning. */
|
|
3401
|
+
static async fromRpc(rpc, provider, options = {}) {
|
|
3402
|
+
const chainId = (await provider.getNetwork()).chainId;
|
|
3403
|
+
if (typeof chainId !== "bigint" || chainId <= 0n || chainId >= 1n << 64n)
|
|
3404
|
+
throw new Error("invalid protocol chainId");
|
|
3405
|
+
const deployment = await rpc.getDeployment(
|
|
3406
|
+
chainId,
|
|
3407
|
+
options.signal ? { signal: options.signal } : {}
|
|
3408
|
+
);
|
|
3409
|
+
const protocol = new _Protocol({ deployment });
|
|
3410
|
+
if (protocol.context.chainId !== chainId) throw new Error("RPC deployment chain mismatch");
|
|
3411
|
+
await protocol.validateDeployment(provider);
|
|
3412
|
+
return protocol;
|
|
3413
|
+
}
|
|
3414
|
+
async validateDeployment(connection) {
|
|
3415
|
+
const reader = "getNetwork" in connection ? {
|
|
3416
|
+
getChainId: async () => (await connection.getNetwork()).chainId,
|
|
3417
|
+
getCode: async (address) => await connection.getCode(address),
|
|
3418
|
+
getProtocolVersion: async (address) => BigInt(
|
|
3419
|
+
await new Contract2(
|
|
3420
|
+
address,
|
|
3421
|
+
["function VERSION() view returns (uint256)"],
|
|
3422
|
+
connection
|
|
3423
|
+
).getFunction("VERSION")()
|
|
3424
|
+
)
|
|
3425
|
+
} : connection;
|
|
3426
|
+
if (await reader.getChainId() !== this.context.chainId)
|
|
3427
|
+
throw new Error("deployment chain mismatch");
|
|
3428
|
+
const code = await reader.getCode(this.context.protocolAddress);
|
|
3429
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || keccak2568(code) !== this.deployment.protocol.runtimeCodeHash)
|
|
3430
|
+
throw new Error("protocol runtime code profile mismatch");
|
|
3431
|
+
if (reader.getProtocolVersion && await reader.getProtocolVersion(this.context.protocolAddress) !== 1n)
|
|
3432
|
+
throw new Error("unsupported onchain protocol version");
|
|
3433
|
+
}
|
|
3434
|
+
aggregate(request) {
|
|
3435
|
+
return {
|
|
3436
|
+
to: this.context.protocolAddress,
|
|
3437
|
+
value: 0n,
|
|
3438
|
+
...buildTransactAggregateCalldata({ ...request, context: this.context })
|
|
3439
|
+
};
|
|
3440
|
+
}
|
|
3441
|
+
/** Build an operation context for one asset within this same deployment. */
|
|
3442
|
+
forToken(tokenAddress) {
|
|
3443
|
+
return new TokenProtocol(
|
|
3444
|
+
{ ...this.context, tokenAddress: getAddress7(tokenAddress) },
|
|
3445
|
+
{ expectedRuntimeCodeHash: this.deployment.protocol.runtimeCodeHash }
|
|
3446
|
+
);
|
|
3447
|
+
}
|
|
3448
|
+
};
|
|
3449
|
+
|
|
3450
|
+
// src/verify.ts
|
|
3451
|
+
import {
|
|
3452
|
+
computeCreditCommitment as computeCreditCommitment2,
|
|
3453
|
+
computeCreditSharedKeyHash as computeCreditSharedKeyHash2,
|
|
3454
|
+
computeNoteCommitment as computeNoteCommitment3,
|
|
3455
|
+
computeNoteIdentity as computeNoteIdentity2,
|
|
3456
|
+
FIELD_MODULUS as FIELD_MODULUS2
|
|
3457
|
+
} from "@invisi-labs/core";
|
|
3458
|
+
async function verifyNoteCommitment(params) {
|
|
3459
|
+
const expected = await computeNoteCommitment3(
|
|
3460
|
+
params.chainId,
|
|
3461
|
+
await computeNoteIdentity2(BigInt(params.walletIdentity), BigInt(params.nonce)),
|
|
3462
|
+
BigInt(params.tokenAddress),
|
|
3463
|
+
params.amount
|
|
3464
|
+
);
|
|
3465
|
+
return BigInt(expected) === BigInt(params.noteCommitment);
|
|
3466
|
+
}
|
|
3467
|
+
async function verifyCreditCommitment(params) {
|
|
3468
|
+
if (params.creditSharedKey <= 0n || params.creditSharedKey >= FIELD_MODULUS2)
|
|
3469
|
+
throw new RangeError("creditSharedKey must be a nonzero canonical Field");
|
|
3470
|
+
const expected = await computeCreditCommitment2(
|
|
3471
|
+
params.chainId,
|
|
3472
|
+
params.spenderWalletIdentity,
|
|
3473
|
+
params.ownerWalletIdentity,
|
|
3474
|
+
BigInt(params.spenderPayout),
|
|
3475
|
+
BigInt(params.ownerPayout),
|
|
3476
|
+
BigInt(params.tokenAddress),
|
|
3477
|
+
params.amount,
|
|
3478
|
+
params.nonce,
|
|
3479
|
+
params.expiry,
|
|
3480
|
+
await computeCreditSharedKeyHash2(params.creditSharedKey)
|
|
3481
|
+
);
|
|
3482
|
+
return BigInt(expected) === BigInt(params.creditCommitment);
|
|
3483
|
+
}
|
|
3484
|
+
|
|
3485
|
+
// src/withdrawal.ts
|
|
3486
|
+
import {
|
|
3487
|
+
computeNoteCommitment as computeNoteCommitment4,
|
|
3488
|
+
computeNoteIdentity as computeNoteIdentity3,
|
|
3489
|
+
computeNoteNullifier as computeNoteNullifier2
|
|
3490
|
+
} from "@invisi-labs/core";
|
|
3491
|
+
async function buildWithdrawalCalldata(p) {
|
|
3492
|
+
const r = normalizeTransactRequest(p.context, p.params, [], p.funding);
|
|
3493
|
+
if (r.outputCount !== 0 || r.depositAmount !== 0n || p.sourceNotes.length === 0 || p.sourceNotes.length !== r.inputCount) {
|
|
3494
|
+
throw new Error("full withdrawal requires inputs, no private outputs and no funding");
|
|
3495
|
+
}
|
|
3496
|
+
const walletIdentity = BigInt(p.sourceNotes[0].walletIdentity);
|
|
3497
|
+
let total = 0n;
|
|
3498
|
+
for (const [index, note] of p.sourceNotes.entries()) {
|
|
3499
|
+
if (note.chainId !== p.context.chainId || note.protocolAddress !== BigInt(p.context.protocolAddress))
|
|
3500
|
+
throw new Error("source note context mismatch");
|
|
3501
|
+
if (BigInt(note.walletIdentity) !== walletIdentity || note.tokenAddress !== BigInt(p.context.tokenAddress) || note.amount <= 0n)
|
|
3502
|
+
throw new Error("source note wallet/token/amount mismatch");
|
|
3503
|
+
const commitment = await computeNoteCommitment4(
|
|
3504
|
+
note.chainId,
|
|
3505
|
+
await computeNoteIdentity3(walletIdentity, note.nonce),
|
|
3506
|
+
note.tokenAddress,
|
|
3507
|
+
note.amount
|
|
3508
|
+
);
|
|
3509
|
+
const nullifier = await computeNoteNullifier2(note.chainId, note.nonce, commitment);
|
|
3510
|
+
if (nullifier.toLowerCase() !== r.nullifiers[index].toLowerCase())
|
|
3511
|
+
throw new Error("source note nullifier mismatch");
|
|
3512
|
+
total += note.amount;
|
|
3513
|
+
}
|
|
3514
|
+
if (r.withdrawalAmount !== total)
|
|
3515
|
+
throw new Error("withdrawal must equal the full input balance");
|
|
3516
|
+
return buildTransactCalldata({ ...p, deliveries: [] });
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
// src/factory.ts
|
|
3520
|
+
import { Contract as Contract3, getAddress as getAddress8 } from "ethers";
|
|
3521
|
+
async function resolveInstanceAddress(client, factoryAddress, salt) {
|
|
3522
|
+
const instance = await new Contract3(
|
|
3523
|
+
getAddress8(factoryAddress),
|
|
3524
|
+
invisiFactoryAbi,
|
|
3525
|
+
client
|
|
3526
|
+
).getFunction("getInstanceAddress")(salt);
|
|
3527
|
+
return getAddress8(instance);
|
|
3528
|
+
}
|
|
3529
|
+
export {
|
|
3530
|
+
AddressRegistry,
|
|
3531
|
+
CREATE_CREDIT_FIELDS,
|
|
3532
|
+
CREDIT_DRAW_CAPACITIES,
|
|
3533
|
+
EMPTY_FUNDING,
|
|
3534
|
+
EMPTY_PERMIT,
|
|
3535
|
+
FIELD_MODULUS,
|
|
3536
|
+
Protocol,
|
|
3537
|
+
RegistrationOperation,
|
|
3538
|
+
TRANSACT_CAPACITIES,
|
|
3539
|
+
TokenProtocol,
|
|
3540
|
+
WitnessBuilder,
|
|
3541
|
+
ZERO_ADDRESS,
|
|
3542
|
+
ZERO_WORD,
|
|
3543
|
+
aggregateMemberRequestHash,
|
|
3544
|
+
aggregatePublicInputs,
|
|
3545
|
+
buildCancelCreditCalldata,
|
|
3546
|
+
buildCreateCreditCalldata,
|
|
3547
|
+
buildCreditDrawCalldata,
|
|
3548
|
+
buildRegistrationCalldata,
|
|
3549
|
+
buildShieldCalldata,
|
|
3550
|
+
buildTopUpCreditCalldata,
|
|
3551
|
+
buildTransactAggregateCalldata,
|
|
3552
|
+
buildTransactCalldata,
|
|
3553
|
+
buildWithdrawalCalldata,
|
|
3554
|
+
cancelCreditBaseInputs,
|
|
3555
|
+
cancelCreditPublicInputs,
|
|
3556
|
+
cancelCreditRequestHash,
|
|
3557
|
+
checkDeadline,
|
|
3558
|
+
createCreditBaseInputs,
|
|
3559
|
+
createCreditPublicInputs,
|
|
3560
|
+
createCreditRequestHash,
|
|
3561
|
+
createRegistryReceivingKeyLookup,
|
|
3562
|
+
creditDrawBaseInputs,
|
|
3563
|
+
creditDrawPublicInputs,
|
|
3564
|
+
deliveriesHash,
|
|
3565
|
+
dense,
|
|
3566
|
+
encodeAggregateFundingTypedData,
|
|
3567
|
+
encodeCancelCreditTypedData,
|
|
3568
|
+
encodeCreateCreditFundingTypedData,
|
|
3569
|
+
encodeCreateCreditTypedData,
|
|
3570
|
+
encodeCreditDrawTypedData,
|
|
3571
|
+
encodeCreditProof,
|
|
3572
|
+
encodeShieldFundingTypedData,
|
|
3573
|
+
encodeTopUpCreditFundingTypedData,
|
|
3574
|
+
encodeTopUpCreditTypedData,
|
|
3575
|
+
encodeTransactFundingTypedData,
|
|
3576
|
+
encodeTransactTypedData,
|
|
3577
|
+
envelope,
|
|
3578
|
+
field,
|
|
3579
|
+
fundingFields,
|
|
3580
|
+
getEIP712Domain,
|
|
3581
|
+
known,
|
|
3582
|
+
normalizeContext,
|
|
3583
|
+
normalizeDelivery,
|
|
3584
|
+
normalizeFunding,
|
|
3585
|
+
normalizeSources,
|
|
3586
|
+
normalizeTransactRequest,
|
|
3587
|
+
notes,
|
|
3588
|
+
pad,
|
|
3589
|
+
registrationAuthorizationRequest,
|
|
3590
|
+
registrationPublicInputs,
|
|
3591
|
+
registrationTypedData,
|
|
3592
|
+
resolveInstanceAddress,
|
|
3593
|
+
selectCreditDrawCircuit,
|
|
3594
|
+
selectTransactCapacity,
|
|
3595
|
+
shieldFundingRequestHash,
|
|
3596
|
+
topUpCreditBaseInputs,
|
|
3597
|
+
topUpCreditPublicInputs,
|
|
3598
|
+
topUpCreditRequestHash,
|
|
3599
|
+
transactFundingRequestHash,
|
|
3600
|
+
transactPublicInputs,
|
|
3601
|
+
transactUserPublicInputs,
|
|
3602
|
+
uint,
|
|
3603
|
+
validateCancelCreditRequest,
|
|
3604
|
+
validateCreateCreditRequest,
|
|
3605
|
+
validateCreditDrawRequest,
|
|
3606
|
+
validateFundingSubmission,
|
|
3607
|
+
validateShieldRequest,
|
|
3608
|
+
validateTopUpCreditRequest,
|
|
3609
|
+
verifyCreditCommitment,
|
|
3610
|
+
verifyNoteCommitment,
|
|
3611
|
+
word
|
|
3612
|
+
};
|
|
3613
|
+
//# sourceMappingURL=index.js.map
|