@invisi-labs/protocol 1.1.0 → 1.1.1
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 → chunk-47SC3EAI.js} +114 -45
- package/dist/chunk-47SC3EAI.js.map +1 -0
- package/dist/contracts.cjs +113 -44
- package/dist/contracts.cjs.map +1 -1
- package/dist/contracts.d.cts +5 -5
- package/dist/contracts.d.ts +5 -5
- package/dist/contracts.js +1 -1
- package/dist/index.cjs +1585 -1572
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +82 -36
- package/dist/index.d.ts +82 -36
- package/dist/index.js +2663 -2728
- package/dist/index.js.map +1 -1
- package/dist/{types-RN45XzKc.d.cts → types-BCTQjKzw.d.cts} +89 -34
- package/dist/{types-RN45XzKc.d.ts → types-BCTQjKzw.d.ts} +89 -34
- package/package.json +4 -4
- package/dist/chunk-XTOQXQES.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -79,8 +79,7 @@ __export(src_exports, {
|
|
|
79
79
|
normalizeTransactRequest: () => normalizeTransactRequest,
|
|
80
80
|
notes: () => notes,
|
|
81
81
|
pad: () => pad,
|
|
82
|
-
|
|
83
|
-
registrationPublicInputs: () => registrationPublicInputs,
|
|
82
|
+
registrationDigest: () => registrationDigest,
|
|
84
83
|
registrationTypedData: () => registrationTypedData,
|
|
85
84
|
resolveInstanceAddress: () => resolveInstanceAddress,
|
|
86
85
|
selectCreditDrawCircuit: () => selectCreditDrawCircuit,
|
|
@@ -106,11 +105,11 @@ __export(src_exports, {
|
|
|
106
105
|
module.exports = __toCommonJS(src_exports);
|
|
107
106
|
|
|
108
107
|
// src/AddressRegistry.ts
|
|
109
|
-
var
|
|
110
|
-
var
|
|
108
|
+
var import_ethers3 = require("ethers");
|
|
109
|
+
var import_core3 = require("@invisi-labs/core");
|
|
111
110
|
|
|
112
111
|
// src/RegistrationOperation.ts
|
|
113
|
-
var
|
|
112
|
+
var import_ethers2 = require("ethers");
|
|
114
113
|
|
|
115
114
|
// src/contracts/abis/InvisiProtocol.ts
|
|
116
115
|
var invisiProtocolAbi = [
|
|
@@ -153,6 +152,11 @@ var invisiProtocolAbi = [
|
|
|
153
152
|
"name": "_screener",
|
|
154
153
|
"type": "address",
|
|
155
154
|
"internalType": "address"
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
"name": "_addressRegistry",
|
|
158
|
+
"type": "address",
|
|
159
|
+
"internalType": "address"
|
|
156
160
|
}
|
|
157
161
|
],
|
|
158
162
|
"stateMutability": "nonpayable"
|
|
@@ -229,6 +233,19 @@ var invisiProtocolAbi = [
|
|
|
229
233
|
],
|
|
230
234
|
"stateMutability": "view"
|
|
231
235
|
},
|
|
236
|
+
{
|
|
237
|
+
"type": "function",
|
|
238
|
+
"name": "addressRegistry",
|
|
239
|
+
"inputs": [],
|
|
240
|
+
"outputs": [
|
|
241
|
+
{
|
|
242
|
+
"name": "",
|
|
243
|
+
"type": "address",
|
|
244
|
+
"internalType": "contract IAddressRegistry"
|
|
245
|
+
}
|
|
246
|
+
],
|
|
247
|
+
"stateMutability": "view"
|
|
248
|
+
},
|
|
232
249
|
{
|
|
233
250
|
"type": "function",
|
|
234
251
|
"name": "cancelCredit",
|
|
@@ -422,7 +439,7 @@ var invisiProtocolAbi = [
|
|
|
422
439
|
{
|
|
423
440
|
"name": "permit",
|
|
424
441
|
"type": "tuple",
|
|
425
|
-
"internalType": "struct
|
|
442
|
+
"internalType": "struct IMetaTx.TokenPermit",
|
|
426
443
|
"components": [
|
|
427
444
|
{
|
|
428
445
|
"name": "deadline",
|
|
@@ -965,7 +982,7 @@ var invisiProtocolAbi = [
|
|
|
965
982
|
{
|
|
966
983
|
"name": "permit",
|
|
967
984
|
"type": "tuple",
|
|
968
|
-
"internalType": "struct
|
|
985
|
+
"internalType": "struct IMetaTx.TokenPermit",
|
|
969
986
|
"components": [
|
|
970
987
|
{
|
|
971
988
|
"name": "deadline",
|
|
@@ -1147,7 +1164,7 @@ var invisiProtocolAbi = [
|
|
|
1147
1164
|
{
|
|
1148
1165
|
"name": "permit",
|
|
1149
1166
|
"type": "tuple",
|
|
1150
|
-
"internalType": "struct
|
|
1167
|
+
"internalType": "struct IMetaTx.TokenPermit",
|
|
1151
1168
|
"components": [
|
|
1152
1169
|
{
|
|
1153
1170
|
"name": "deadline",
|
|
@@ -1295,7 +1312,7 @@ var invisiProtocolAbi = [
|
|
|
1295
1312
|
{
|
|
1296
1313
|
"name": "permit",
|
|
1297
1314
|
"type": "tuple",
|
|
1298
|
-
"internalType": "struct
|
|
1315
|
+
"internalType": "struct IMetaTx.TokenPermit",
|
|
1299
1316
|
"components": [
|
|
1300
1317
|
{
|
|
1301
1318
|
"name": "deadline",
|
|
@@ -1445,7 +1462,7 @@ var invisiProtocolAbi = [
|
|
|
1445
1462
|
{
|
|
1446
1463
|
"name": "permit",
|
|
1447
1464
|
"type": "tuple",
|
|
1448
|
-
"internalType": "struct
|
|
1465
|
+
"internalType": "struct IMetaTx.TokenPermit",
|
|
1449
1466
|
"components": [
|
|
1450
1467
|
{
|
|
1451
1468
|
"name": "deadline",
|
|
@@ -2532,6 +2549,11 @@ var invisiProtocolAbi = [
|
|
|
2532
2549
|
}
|
|
2533
2550
|
]
|
|
2534
2551
|
},
|
|
2552
|
+
{
|
|
2553
|
+
"type": "error",
|
|
2554
|
+
"name": "InvalidAddressRegistry",
|
|
2555
|
+
"inputs": []
|
|
2556
|
+
},
|
|
2535
2557
|
{
|
|
2536
2558
|
"type": "error",
|
|
2537
2559
|
"name": "InvalidAggregateBatch",
|
|
@@ -2908,6 +2930,11 @@ var invisiFactoryAbi = [
|
|
|
2908
2930
|
"name": "screener_",
|
|
2909
2931
|
"type": "address",
|
|
2910
2932
|
"internalType": "address"
|
|
2933
|
+
},
|
|
2934
|
+
{
|
|
2935
|
+
"name": "addressRegistry_",
|
|
2936
|
+
"type": "address",
|
|
2937
|
+
"internalType": "address"
|
|
2911
2938
|
}
|
|
2912
2939
|
],
|
|
2913
2940
|
"outputs": [
|
|
@@ -2960,6 +2987,11 @@ var invisiFactoryAbi = [
|
|
|
2960
2987
|
"name": "screener_",
|
|
2961
2988
|
"type": "address",
|
|
2962
2989
|
"internalType": "address"
|
|
2990
|
+
},
|
|
2991
|
+
{
|
|
2992
|
+
"name": "addressRegistry_",
|
|
2993
|
+
"type": "address",
|
|
2994
|
+
"internalType": "address"
|
|
2963
2995
|
}
|
|
2964
2996
|
],
|
|
2965
2997
|
"outputs": [
|
|
@@ -3343,13 +3375,7 @@ var invisiFactoryAbi = [
|
|
|
3343
3375
|
var invisiAddressRegistryAbi = [
|
|
3344
3376
|
{
|
|
3345
3377
|
"type": "constructor",
|
|
3346
|
-
"inputs": [
|
|
3347
|
-
{
|
|
3348
|
-
"name": "verifier",
|
|
3349
|
-
"type": "address",
|
|
3350
|
-
"internalType": "contract IVerifier"
|
|
3351
|
-
}
|
|
3352
|
-
],
|
|
3378
|
+
"inputs": [],
|
|
3353
3379
|
"stateMutability": "nonpayable"
|
|
3354
3380
|
},
|
|
3355
3381
|
{
|
|
@@ -3365,6 +3391,49 @@ var invisiAddressRegistryAbi = [
|
|
|
3365
3391
|
],
|
|
3366
3392
|
"stateMutability": "view"
|
|
3367
3393
|
},
|
|
3394
|
+
{
|
|
3395
|
+
"type": "function",
|
|
3396
|
+
"name": "eip712Domain",
|
|
3397
|
+
"inputs": [],
|
|
3398
|
+
"outputs": [
|
|
3399
|
+
{
|
|
3400
|
+
"name": "fields",
|
|
3401
|
+
"type": "bytes1",
|
|
3402
|
+
"internalType": "bytes1"
|
|
3403
|
+
},
|
|
3404
|
+
{
|
|
3405
|
+
"name": "name",
|
|
3406
|
+
"type": "string",
|
|
3407
|
+
"internalType": "string"
|
|
3408
|
+
},
|
|
3409
|
+
{
|
|
3410
|
+
"name": "version",
|
|
3411
|
+
"type": "string",
|
|
3412
|
+
"internalType": "string"
|
|
3413
|
+
},
|
|
3414
|
+
{
|
|
3415
|
+
"name": "chainId",
|
|
3416
|
+
"type": "uint256",
|
|
3417
|
+
"internalType": "uint256"
|
|
3418
|
+
},
|
|
3419
|
+
{
|
|
3420
|
+
"name": "verifyingContract",
|
|
3421
|
+
"type": "address",
|
|
3422
|
+
"internalType": "address"
|
|
3423
|
+
},
|
|
3424
|
+
{
|
|
3425
|
+
"name": "salt",
|
|
3426
|
+
"type": "bytes32",
|
|
3427
|
+
"internalType": "bytes32"
|
|
3428
|
+
},
|
|
3429
|
+
{
|
|
3430
|
+
"name": "extensions",
|
|
3431
|
+
"type": "uint256[]",
|
|
3432
|
+
"internalType": "uint256[]"
|
|
3433
|
+
}
|
|
3434
|
+
],
|
|
3435
|
+
"stateMutability": "view"
|
|
3436
|
+
},
|
|
3368
3437
|
{
|
|
3369
3438
|
"type": "function",
|
|
3370
3439
|
"name": "isRegistered",
|
|
@@ -3417,7 +3486,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3417
3486
|
{
|
|
3418
3487
|
"name": "keys",
|
|
3419
3488
|
"type": "tuple",
|
|
3420
|
-
"internalType": "struct
|
|
3489
|
+
"internalType": "struct IAddressRegistry.ReceivingKeys",
|
|
3421
3490
|
"components": [
|
|
3422
3491
|
{
|
|
3423
3492
|
"name": "viewingPublicKey",
|
|
@@ -3446,7 +3515,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3446
3515
|
{
|
|
3447
3516
|
"name": "registration",
|
|
3448
3517
|
"type": "tuple",
|
|
3449
|
-
"internalType": "struct
|
|
3518
|
+
"internalType": "struct IAddressRegistry.Registration",
|
|
3450
3519
|
"components": [
|
|
3451
3520
|
{
|
|
3452
3521
|
"name": "walletIdentity",
|
|
@@ -3456,7 +3525,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3456
3525
|
{
|
|
3457
3526
|
"name": "keys",
|
|
3458
3527
|
"type": "tuple",
|
|
3459
|
-
"internalType": "struct
|
|
3528
|
+
"internalType": "struct IAddressRegistry.ReceivingKeys",
|
|
3460
3529
|
"components": [
|
|
3461
3530
|
{
|
|
3462
3531
|
"name": "viewingPublicKey",
|
|
@@ -3483,7 +3552,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3483
3552
|
]
|
|
3484
3553
|
},
|
|
3485
3554
|
{
|
|
3486
|
-
"name": "
|
|
3555
|
+
"name": "signature",
|
|
3487
3556
|
"type": "bytes",
|
|
3488
3557
|
"internalType": "bytes"
|
|
3489
3558
|
}
|
|
@@ -3491,19 +3560,6 @@ var invisiAddressRegistryAbi = [
|
|
|
3491
3560
|
"outputs": [],
|
|
3492
3561
|
"stateMutability": "nonpayable"
|
|
3493
3562
|
},
|
|
3494
|
-
{
|
|
3495
|
-
"type": "function",
|
|
3496
|
-
"name": "registrationVerifier",
|
|
3497
|
-
"inputs": [],
|
|
3498
|
-
"outputs": [
|
|
3499
|
-
{
|
|
3500
|
-
"name": "",
|
|
3501
|
-
"type": "address",
|
|
3502
|
-
"internalType": "contract IVerifier"
|
|
3503
|
-
}
|
|
3504
|
-
],
|
|
3505
|
-
"stateMutability": "view"
|
|
3506
|
-
},
|
|
3507
3563
|
{
|
|
3508
3564
|
"type": "function",
|
|
3509
3565
|
"name": "supportsInterface",
|
|
@@ -3530,7 +3586,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3530
3586
|
{
|
|
3531
3587
|
"name": "registration",
|
|
3532
3588
|
"type": "tuple",
|
|
3533
|
-
"internalType": "struct
|
|
3589
|
+
"internalType": "struct IAddressRegistry.Registration",
|
|
3534
3590
|
"components": [
|
|
3535
3591
|
{
|
|
3536
3592
|
"name": "walletIdentity",
|
|
@@ -3540,7 +3596,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3540
3596
|
{
|
|
3541
3597
|
"name": "keys",
|
|
3542
3598
|
"type": "tuple",
|
|
3543
|
-
"internalType": "struct
|
|
3599
|
+
"internalType": "struct IAddressRegistry.ReceivingKeys",
|
|
3544
3600
|
"components": [
|
|
3545
3601
|
{
|
|
3546
3602
|
"name": "viewingPublicKey",
|
|
@@ -3567,7 +3623,7 @@ var invisiAddressRegistryAbi = [
|
|
|
3567
3623
|
]
|
|
3568
3624
|
},
|
|
3569
3625
|
{
|
|
3570
|
-
"name": "
|
|
3626
|
+
"name": "signature",
|
|
3571
3627
|
"type": "bytes",
|
|
3572
3628
|
"internalType": "bytes"
|
|
3573
3629
|
}
|
|
@@ -3575,6 +3631,12 @@ var invisiAddressRegistryAbi = [
|
|
|
3575
3631
|
"outputs": [],
|
|
3576
3632
|
"stateMutability": "nonpayable"
|
|
3577
3633
|
},
|
|
3634
|
+
{
|
|
3635
|
+
"type": "event",
|
|
3636
|
+
"name": "EIP712DomainChanged",
|
|
3637
|
+
"inputs": [],
|
|
3638
|
+
"anonymous": false
|
|
3639
|
+
},
|
|
3578
3640
|
{
|
|
3579
3641
|
"type": "event",
|
|
3580
3642
|
"name": "ReceivingKeysSet",
|
|
@@ -3628,12 +3690,12 @@ var invisiAddressRegistryAbi = [
|
|
|
3628
3690
|
},
|
|
3629
3691
|
{
|
|
3630
3692
|
"type": "error",
|
|
3631
|
-
"name": "
|
|
3693
|
+
"name": "InvalidRegistrationSignature",
|
|
3632
3694
|
"inputs": []
|
|
3633
3695
|
},
|
|
3634
3696
|
{
|
|
3635
3697
|
"type": "error",
|
|
3636
|
-
"name": "
|
|
3698
|
+
"name": "InvalidShortString",
|
|
3637
3699
|
"inputs": []
|
|
3638
3700
|
},
|
|
3639
3701
|
{
|
|
@@ -3641,11 +3703,6 @@ var invisiAddressRegistryAbi = [
|
|
|
3641
3703
|
"name": "InvalidWalletIdentity",
|
|
3642
3704
|
"inputs": []
|
|
3643
3705
|
},
|
|
3644
|
-
{
|
|
3645
|
-
"type": "error",
|
|
3646
|
-
"name": "InvalidWalletStatement",
|
|
3647
|
-
"inputs": []
|
|
3648
|
-
},
|
|
3649
3706
|
{
|
|
3650
3707
|
"type": "error",
|
|
3651
3708
|
"name": "NonceExhausted",
|
|
@@ -3665,17 +3722,27 @@ var invisiAddressRegistryAbi = [
|
|
|
3665
3722
|
"type": "error",
|
|
3666
3723
|
"name": "RegistrationExpired",
|
|
3667
3724
|
"inputs": []
|
|
3725
|
+
},
|
|
3726
|
+
{
|
|
3727
|
+
"type": "error",
|
|
3728
|
+
"name": "StringTooLong",
|
|
3729
|
+
"inputs": [
|
|
3730
|
+
{
|
|
3731
|
+
"name": "str",
|
|
3732
|
+
"type": "string",
|
|
3733
|
+
"internalType": "string"
|
|
3734
|
+
}
|
|
3735
|
+
]
|
|
3668
3736
|
}
|
|
3669
3737
|
];
|
|
3670
3738
|
|
|
3671
3739
|
// src/RegistrationOperation.ts
|
|
3672
|
-
var
|
|
3740
|
+
var import_core2 = require("@invisi-labs/core");
|
|
3673
3741
|
|
|
3674
3742
|
// src/registry.ts
|
|
3675
3743
|
var import_ethers = require("ethers");
|
|
3676
3744
|
var import_core = require("@invisi-labs/core");
|
|
3677
3745
|
var MAX_NONCE = (1n << 64n) - 1n;
|
|
3678
|
-
var MASK128 = (1n << 128n) - 1n;
|
|
3679
3746
|
function uint64(value, name) {
|
|
3680
3747
|
if (typeof value !== "bigint" || value < 0n || value > MAX_NONCE)
|
|
3681
3748
|
throw new RangeError(`${name} must be uint64`);
|
|
@@ -3704,8 +3771,12 @@ function normalize(context, registration, options) {
|
|
|
3704
3771
|
uint64(context.chainId, "chainId");
|
|
3705
3772
|
const registryAddress = (0, import_ethers.getAddress)(context.registryAddress);
|
|
3706
3773
|
if (BigInt(registryAddress) === 0n) throw new Error("Registry address must be nonzero");
|
|
3774
|
+
if (!/^0x(?:[0-9a-fA-F]{40}|[0-9a-fA-F]{64})$/.test(registration.walletIdentity))
|
|
3775
|
+
throw new Error("Wallet identity must be an EVM owner or padded bytes32");
|
|
3707
3776
|
const walletIdentity = (0, import_core.decodeAddress)(
|
|
3708
|
-
import_core.ReceivingAddress.fromIdentity(
|
|
3777
|
+
import_core.ReceivingAddress.fromIdentity(
|
|
3778
|
+
(0, import_ethers.toBeHex)(BigInt(registration.walletIdentity), 20)
|
|
3779
|
+
).toString()
|
|
3709
3780
|
).walletIdentity;
|
|
3710
3781
|
const keys = normalizeKeys(walletIdentity, registration.keys);
|
|
3711
3782
|
const nonce = uint64(registration.nonce, "nonce"), deadline = uint64(registration.deadline, "deadline");
|
|
@@ -3720,44 +3791,42 @@ function normalize(context, registration, options) {
|
|
|
3720
3791
|
throw new Error("Registration expired");
|
|
3721
3792
|
return { registryAddress, registration: { walletIdentity, keys, nonce, deadline } };
|
|
3722
3793
|
}
|
|
3723
|
-
function
|
|
3724
|
-
const
|
|
3725
|
-
const
|
|
3726
|
-
(0, import_ethers.keccak256)((0, import_ethers.concat)([r.keys.viewingPublicKey, r.keys.clueKey]))
|
|
3727
|
-
);
|
|
3794
|
+
function registrationTypedData(context, registration, options = {}) {
|
|
3795
|
+
const { registryAddress, registration: r } = normalize(context, registration, options);
|
|
3796
|
+
const primaryType = options.update ? "UpdateReceivingKeys" : "RegisterReceivingKeys";
|
|
3728
3797
|
return {
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3798
|
+
domain: {
|
|
3799
|
+
name: "InvisiAddressRegistry",
|
|
3800
|
+
version: "1",
|
|
3801
|
+
chainId: context.chainId,
|
|
3802
|
+
verifyingContract: registryAddress
|
|
3803
|
+
},
|
|
3804
|
+
primaryType,
|
|
3805
|
+
types: {
|
|
3806
|
+
[primaryType]: [
|
|
3807
|
+
{ name: "walletIdentity", type: "bytes32" },
|
|
3808
|
+
{ name: "viewingPublicKey", type: "bytes" },
|
|
3809
|
+
{ name: "clueKey", type: "bytes32" },
|
|
3810
|
+
{ name: "nonce", type: "uint64" },
|
|
3811
|
+
{ name: "deadline", type: "uint64" }
|
|
3812
|
+
]
|
|
3813
|
+
},
|
|
3814
|
+
message: {
|
|
3815
|
+
walletIdentity: (0, import_ethers.toBeHex)(BigInt(r.walletIdentity), 32),
|
|
3816
|
+
...r.keys,
|
|
3817
|
+
nonce: r.nonce,
|
|
3818
|
+
deadline: r.deadline
|
|
3819
|
+
}
|
|
3741
3820
|
};
|
|
3742
3821
|
}
|
|
3743
|
-
function
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
);
|
|
3747
|
-
}
|
|
3748
|
-
function registrationPublicInputs(context, registration, options = {}) {
|
|
3749
|
-
const request = registrationAuthorizationRequest(context, registration, options);
|
|
3750
|
-
const digest = BigInt((0, import_core.computeWalletAuthorizationDigest)(request));
|
|
3751
|
-
return [
|
|
3752
|
-
(0, import_ethers.toBeHex)(request.words[2], 32),
|
|
3753
|
-
(0, import_ethers.toBeHex)(digest >> 128n, 32),
|
|
3754
|
-
(0, import_ethers.toBeHex)(digest & MASK128, 32)
|
|
3755
|
-
];
|
|
3822
|
+
function registrationDigest(context, registration, options = {}) {
|
|
3823
|
+
const typed = registrationTypedData(context, registration, options);
|
|
3824
|
+
return import_ethers.TypedDataEncoder.hash(typed.domain, typed.types, typed.message);
|
|
3756
3825
|
}
|
|
3757
|
-
function buildRegistrationCalldata(context, registration,
|
|
3826
|
+
function buildRegistrationCalldata(context, registration, signature, options = {}) {
|
|
3758
3827
|
const normalized = normalize(context, registration, options);
|
|
3759
|
-
if (typeof
|
|
3760
|
-
throw new Error("Registration
|
|
3828
|
+
if (typeof signature !== "string" || !(0, import_ethers.isHexString)(signature) || signature.length % 2 !== 0)
|
|
3829
|
+
throw new Error("Registration signature must be hexadecimal bytes");
|
|
3761
3830
|
return {
|
|
3762
3831
|
to: normalized.registryAddress,
|
|
3763
3832
|
value: 0n,
|
|
@@ -3768,10 +3837,9 @@ function buildRegistrationCalldata(context, registration, proof, options = {}) {
|
|
|
3768
3837
|
...normalized.registration,
|
|
3769
3838
|
walletIdentity: (0, import_ethers.toBeHex)(BigInt(normalized.registration.walletIdentity), 32)
|
|
3770
3839
|
},
|
|
3771
|
-
|
|
3840
|
+
signature
|
|
3772
3841
|
]
|
|
3773
|
-
)
|
|
3774
|
-
publicInputs: registrationPublicInputs(context, normalized.registration, options)
|
|
3842
|
+
)
|
|
3775
3843
|
};
|
|
3776
3844
|
}
|
|
3777
3845
|
function createRegistryReceivingKeyLookup(client, registryAddress) {
|
|
@@ -3795,161 +3863,512 @@ function createRegistryReceivingKeyLookup(client, registryAddress) {
|
|
|
3795
3863
|
};
|
|
3796
3864
|
}
|
|
3797
3865
|
|
|
3798
|
-
// src/
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
// src/credit-create.ts
|
|
3803
|
-
var import_ethers3 = require("ethers");
|
|
3804
|
-
var import_core2 = require("@invisi-labs/core");
|
|
3805
|
-
|
|
3806
|
-
// src/validation.ts
|
|
3807
|
-
var import_ethers2 = require("ethers");
|
|
3808
|
-
var FIELD_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
3809
|
-
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
3810
|
-
var ZERO_WORD = (0, import_ethers2.toBeHex)(0n, 32);
|
|
3811
|
-
var EMPTY_PERMIT = {
|
|
3812
|
-
deadline: 0n,
|
|
3813
|
-
v: 0,
|
|
3814
|
-
r: ZERO_WORD,
|
|
3815
|
-
s: ZERO_WORD
|
|
3816
|
-
};
|
|
3817
|
-
var EMPTY_FUNDING = {
|
|
3818
|
-
payer: ZERO_ADDRESS,
|
|
3819
|
-
amount: 0n,
|
|
3820
|
-
sigNonce: 0n,
|
|
3821
|
-
deadline: 0n,
|
|
3822
|
-
signature: "0x",
|
|
3823
|
-
permit: EMPTY_PERMIT
|
|
3824
|
-
};
|
|
3825
|
-
function uint(v, bits, name = "value") {
|
|
3826
|
-
if (typeof v !== "bigint" && typeof v !== "number" && typeof v !== "string" || typeof v === "number" && !Number.isSafeInteger(v))
|
|
3827
|
-
throw new Error(`${name} must be an integer`);
|
|
3828
|
-
const n = BigInt(v);
|
|
3829
|
-
if (n < 0n || n >= 1n << BigInt(bits)) throw new Error(`${name} exceeds u${bits}`);
|
|
3830
|
-
return n;
|
|
3831
|
-
}
|
|
3832
|
-
function field(v, name = "field") {
|
|
3833
|
-
const n = uint(v, 256, name);
|
|
3834
|
-
if (n >= FIELD_MODULUS) throw new Error(`${name} is noncanonical field`);
|
|
3835
|
-
return n;
|
|
3836
|
-
}
|
|
3837
|
-
var word = (v) => (0, import_ethers2.toBeHex)(typeof v === "bigint" ? v : BigInt(v), 32);
|
|
3838
|
-
function dense(v, name) {
|
|
3839
|
-
if (!Array.isArray(v)) throw new Error(`${name} must be array`);
|
|
3840
|
-
for (let i = 0; i < v.length; i++)
|
|
3841
|
-
if (!Object.hasOwn(v, i) || v[i] === void 0 || v[i] === null)
|
|
3842
|
-
throw new Error(`${name} has missing or sparse entries`);
|
|
3843
|
-
return v;
|
|
3844
|
-
}
|
|
3845
|
-
function known(v, keys, name = "params") {
|
|
3846
|
-
if (!v || typeof v !== "object" || Array.isArray(v) || Object.keys(v).some((k) => !keys.includes(k)))
|
|
3847
|
-
throw new Error(`${name} has unsupported fields`);
|
|
3848
|
-
}
|
|
3849
|
-
function notes(v, name) {
|
|
3850
|
-
const r = dense(v, name).map((v2) => word(field(v2, name)));
|
|
3851
|
-
if (r.some((v2) => BigInt(v2) === 0n) || new Set(r).size !== r.length)
|
|
3852
|
-
throw new Error(`duplicate or zero ${name}`);
|
|
3853
|
-
return r;
|
|
3854
|
-
}
|
|
3855
|
-
function envelope(v, length, version) {
|
|
3856
|
-
if (!(0, import_ethers2.isHexString)(v) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(v) || (0, import_ethers2.dataLength)(v) !== length)
|
|
3857
|
-
throw new Error(`ciphertext must be ${length} bytes`);
|
|
3858
|
-
if (version !== void 0 && Number.parseInt(v.slice(2, 4), 16) !== version)
|
|
3859
|
-
throw new Error("unsupported ciphertext envelope version");
|
|
3860
|
-
return v;
|
|
3861
|
-
}
|
|
3862
|
-
function normalizeContext(c) {
|
|
3863
|
-
return {
|
|
3864
|
-
...c,
|
|
3865
|
-
chainId: uint(c.chainId, 64, "chainId"),
|
|
3866
|
-
protocolAddress: (0, import_ethers2.getAddress)(c.protocolAddress),
|
|
3867
|
-
tokenAddress: (0, import_ethers2.getAddress)(c.tokenAddress)
|
|
3868
|
-
};
|
|
3869
|
-
}
|
|
3870
|
-
function checkDeadline(c, value) {
|
|
3871
|
-
const n = uint(value, 64, "deadline");
|
|
3872
|
-
if (c.now !== void 0 && n < uint(c.now, 64, "now")) throw new Error("deadline has expired");
|
|
3873
|
-
return n;
|
|
3874
|
-
}
|
|
3875
|
-
function normalizeSources(sources, inputCount, capacity) {
|
|
3876
|
-
dense(sources, "sources");
|
|
3877
|
-
if (inputCount < 0 || inputCount > capacity || sources.length > inputCount || (inputCount === 0 ? sources.length !== 0 : sources.length === 0))
|
|
3878
|
-
throw new Error("source count must be 1..inputCount, or empty for zero inputs");
|
|
3879
|
-
let previous = 0n;
|
|
3880
|
-
return sources.map((s) => {
|
|
3881
|
-
known(s, ["treeId", "merkleRoot"], "source");
|
|
3882
|
-
const treeId = uint(s.treeId, 64, "treeId"), merkleRoot = word(field(s.merkleRoot, "merkleRoot"));
|
|
3883
|
-
if (treeId === 0n || treeId <= previous || BigInt(merkleRoot) === 0n)
|
|
3884
|
-
throw new Error("sources must have positive roots and strictly ascending tree IDs");
|
|
3885
|
-
previous = treeId;
|
|
3886
|
-
return { treeId, merkleRoot };
|
|
3887
|
-
});
|
|
3888
|
-
}
|
|
3889
|
-
var pad = (v, n) => [
|
|
3890
|
-
...v,
|
|
3891
|
-
...Array(n - v.length).fill(0n)
|
|
3892
|
-
];
|
|
3893
|
-
function normalizeDelivery(value, options = {}) {
|
|
3894
|
-
known(value, ["ciphertext", "clue"], "delivery");
|
|
3895
|
-
if (options.empty) {
|
|
3896
|
-
if (value.ciphertext !== "0x" || value.clue !== "0x")
|
|
3897
|
-
throw new Error("absent output requires an empty delivery");
|
|
3898
|
-
return { ciphertext: "0x", clue: "0x" };
|
|
3866
|
+
// src/RegistrationOperation.ts
|
|
3867
|
+
function check(ok, message) {
|
|
3868
|
+
if (!ok) {
|
|
3869
|
+
throw new Error(message);
|
|
3899
3870
|
}
|
|
3900
|
-
const ciphertext = envelope(
|
|
3901
|
-
value.ciphertext,
|
|
3902
|
-
options.credit ? 400 : 158,
|
|
3903
|
-
options.credit ? 3 : 1
|
|
3904
|
-
);
|
|
3905
|
-
const clue = envelope(value.clue, 68);
|
|
3906
|
-
if (clue.slice(130, 132).toLowerCase() !== "18") throw new Error("clue precision must be 24");
|
|
3907
|
-
return { ciphertext, clue };
|
|
3908
3871
|
}
|
|
3909
|
-
var
|
|
3910
|
-
|
|
3911
|
-
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3916
|
-
|
|
3917
|
-
|
|
3918
|
-
|
|
3919
|
-
|
|
3920
|
-
|
|
3921
|
-
|
|
3922
|
-
|
|
3923
|
-
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
|
|
3927
|
-
|
|
3872
|
+
var RegistrationOperation = class _RegistrationOperation {
|
|
3873
|
+
#registry;
|
|
3874
|
+
#runtime;
|
|
3875
|
+
#plan;
|
|
3876
|
+
#signature;
|
|
3877
|
+
#hash;
|
|
3878
|
+
#anchor;
|
|
3879
|
+
status;
|
|
3880
|
+
constructor(registry, runtime, plan, status, signature, hash, anchor) {
|
|
3881
|
+
this.#registry = registry;
|
|
3882
|
+
this.#runtime = { ...runtime };
|
|
3883
|
+
this.#plan = structuredClone(plan);
|
|
3884
|
+
this.status = status;
|
|
3885
|
+
this.#signature = signature;
|
|
3886
|
+
this.#hash = hash;
|
|
3887
|
+
this.#anchor = anchor ? { ...anchor } : void 0;
|
|
3888
|
+
Object.freeze(this);
|
|
3889
|
+
}
|
|
3890
|
+
static async prepare(registry, options) {
|
|
3891
|
+
const runtime = { ...options };
|
|
3892
|
+
const update = options.update ?? false;
|
|
3893
|
+
check(typeof update === "boolean", "update must be boolean");
|
|
3894
|
+
await registry.validateDeployment(runtime.reader);
|
|
3895
|
+
const block = await runtime.reader.getBlock(await runtime.reader.getLatestBlockNumber());
|
|
3896
|
+
const context = { ...registry.context, now: block.timestamp };
|
|
3897
|
+
const nonce = await runtime.reader.getRegistryNonce(
|
|
3898
|
+
context,
|
|
3899
|
+
runtime.wallet.walletIdentity,
|
|
3900
|
+
block
|
|
3901
|
+
);
|
|
3902
|
+
check(
|
|
3903
|
+
typeof nonce === "bigint" && nonce >= 0n && nonce < (1n << 64n) - 1n,
|
|
3904
|
+
"invalid or exhausted registry nonce"
|
|
3905
|
+
);
|
|
3906
|
+
check(
|
|
3907
|
+
update ? nonce > 0n : nonce === 0n,
|
|
3908
|
+
update ? "wallet is not registered" : "wallet is already registered; prepare an update"
|
|
3909
|
+
);
|
|
3910
|
+
const address = import_core2.ReceivingAddress.parse(await registry.resolve(runtime.wallet.getAddress()));
|
|
3911
|
+
const keys = address.getReceivingKeys();
|
|
3912
|
+
const registration = {
|
|
3913
|
+
walletIdentity: runtime.wallet.walletIdentity,
|
|
3914
|
+
keys: {
|
|
3915
|
+
viewingPublicKey: (0, import_ethers2.hexlify)(keys.viewingPublicKey),
|
|
3916
|
+
clueKey: (0, import_ethers2.hexlify)(keys.clueKey)
|
|
3917
|
+
},
|
|
3918
|
+
nonce,
|
|
3919
|
+
deadline: options.deadline ?? block.timestamp + 300n
|
|
3920
|
+
};
|
|
3921
|
+
registrationTypedData(context, registration, { update, expectedNonce: nonce });
|
|
3922
|
+
check(
|
|
3923
|
+
(await runtime.reader.getBlock(block.number)).hash === block.hash,
|
|
3924
|
+
"canonical registry block changed while preparing"
|
|
3925
|
+
);
|
|
3926
|
+
return new _RegistrationOperation(
|
|
3927
|
+
registry,
|
|
3928
|
+
runtime,
|
|
3929
|
+
{ id: crypto.randomUUID(), context, registration, update },
|
|
3930
|
+
"prepared"
|
|
3931
|
+
);
|
|
3932
|
+
}
|
|
3933
|
+
get id() {
|
|
3934
|
+
return this.#plan.id;
|
|
3935
|
+
}
|
|
3936
|
+
preview() {
|
|
3937
|
+
return {
|
|
3938
|
+
id: this.id,
|
|
3939
|
+
status: this.status,
|
|
3940
|
+
chainId: this.#plan.context.chainId,
|
|
3941
|
+
registryAddress: this.#plan.context.registryAddress,
|
|
3942
|
+
...structuredClone(this.#plan.registration),
|
|
3943
|
+
update: this.#plan.update
|
|
3944
|
+
};
|
|
3945
|
+
}
|
|
3946
|
+
/** Sign with ethers, or attach externally obtained ERC-1271 signature bytes. */
|
|
3947
|
+
async authorize(options = {}) {
|
|
3948
|
+
check(this.status === "prepared", "registry operation is not awaiting authorization");
|
|
3949
|
+
options.signal?.throwIfAborted();
|
|
3950
|
+
await this.validateFreshness();
|
|
3951
|
+
options.signal?.throwIfAborted();
|
|
3952
|
+
let signature = options.signature;
|
|
3953
|
+
if (signature === void 0) {
|
|
3954
|
+
const signer = this.#runtime.signer;
|
|
3955
|
+
check(signer, "registry signer capability is missing");
|
|
3956
|
+
check(
|
|
3957
|
+
BigInt(await signer.getAddress()) === BigInt(this.#plan.registration.walletIdentity),
|
|
3958
|
+
"registry signer does not match wallet owner"
|
|
3959
|
+
);
|
|
3960
|
+
const typed = this.typedData();
|
|
3961
|
+
signature = await signer.signTypedData(
|
|
3962
|
+
typed.domain,
|
|
3963
|
+
typed.types,
|
|
3964
|
+
typed.message
|
|
3965
|
+
);
|
|
3966
|
+
}
|
|
3967
|
+
check(
|
|
3968
|
+
/^0x(?:[a-fA-F0-9]{2})+$/.test(signature),
|
|
3969
|
+
"registry signature must be nonempty hexadecimal bytes"
|
|
3970
|
+
);
|
|
3971
|
+
const p = this.#plan;
|
|
3972
|
+
const owner = p.registration.walletIdentity;
|
|
3973
|
+
let valid = false;
|
|
3974
|
+
try {
|
|
3975
|
+
const bytes = (0, import_ethers2.getBytes)(signature);
|
|
3976
|
+
const typed = this.typedData();
|
|
3977
|
+
valid = bytes.length === 65 && (bytes[64] === 27 || bytes[64] === 28) && BigInt((0, import_ethers2.verifyTypedData)(typed.domain, typed.types, typed.message, signature)) === BigInt(owner);
|
|
3978
|
+
} catch {
|
|
3979
|
+
valid = false;
|
|
3980
|
+
}
|
|
3981
|
+
if (!valid) {
|
|
3982
|
+
const code = await this.#runtime.reader.getCode(owner);
|
|
3983
|
+
check(/^0x(?:[a-fA-F0-9]{2})*$/.test(code), "invalid owner contract code");
|
|
3984
|
+
check(code !== "0x", "invalid EOA registry signature");
|
|
3985
|
+
const verify = this.#runtime.reader.isValidRegistrationSignature;
|
|
3986
|
+
check(verify, "ERC-1271 registry signature verification capability is missing");
|
|
3987
|
+
check(
|
|
3988
|
+
await verify.call(
|
|
3989
|
+
this.#runtime.reader,
|
|
3990
|
+
owner,
|
|
3991
|
+
registrationDigest(p.context, p.registration, { update: p.update }),
|
|
3992
|
+
signature
|
|
3993
|
+
),
|
|
3994
|
+
"invalid ERC-1271 registry signature"
|
|
3995
|
+
);
|
|
3996
|
+
}
|
|
3997
|
+
options.signal?.throwIfAborted();
|
|
3998
|
+
return new _RegistrationOperation(
|
|
3999
|
+
this.#registry,
|
|
4000
|
+
this.#runtime,
|
|
4001
|
+
this.#plan,
|
|
4002
|
+
"ready",
|
|
4003
|
+
signature
|
|
4004
|
+
);
|
|
4005
|
+
}
|
|
4006
|
+
/** Empty signatures require the transaction sender to be the wallet owner. */
|
|
4007
|
+
async authorizeDirect() {
|
|
4008
|
+
check(this.status === "prepared", "registry operation is not awaiting authorization");
|
|
4009
|
+
await this.validateFreshness();
|
|
4010
|
+
return new _RegistrationOperation(this.#registry, this.#runtime, this.#plan, "ready", "0x");
|
|
4011
|
+
}
|
|
4012
|
+
typedData() {
|
|
4013
|
+
const p = this.#plan;
|
|
4014
|
+
return registrationTypedData(p.context, p.registration, {
|
|
4015
|
+
update: p.update,
|
|
4016
|
+
expectedNonce: p.registration.nonce
|
|
4017
|
+
});
|
|
4018
|
+
}
|
|
4019
|
+
call() {
|
|
4020
|
+
check(this.#signature !== void 0, "registry signature is missing");
|
|
4021
|
+
const p = this.#plan;
|
|
4022
|
+
const result = buildRegistrationCalldata(p.context, p.registration, this.#signature, {
|
|
4023
|
+
update: p.update,
|
|
4024
|
+
expectedNonce: p.registration.nonce
|
|
4025
|
+
});
|
|
4026
|
+
return { to: result.to, data: result.callData, value: result.value };
|
|
4027
|
+
}
|
|
4028
|
+
async exportTransaction() {
|
|
4029
|
+
check(
|
|
4030
|
+
this.#signature !== void 0 && this.status !== "prepared",
|
|
4031
|
+
"registry operation is not ready"
|
|
4032
|
+
);
|
|
4033
|
+
await this.validateFreshness();
|
|
4034
|
+
return this.call();
|
|
4035
|
+
}
|
|
4036
|
+
async validateFreshness() {
|
|
4037
|
+
await this.#registry.validateDeployment(this.#runtime.reader);
|
|
4038
|
+
const block = await this.#runtime.reader.getBlock(
|
|
4039
|
+
await this.#runtime.reader.getLatestBlockNumber()
|
|
4040
|
+
);
|
|
4041
|
+
const p = this.#plan;
|
|
4042
|
+
check(block.timestamp <= p.registration.deadline, "registry operation has expired");
|
|
4043
|
+
check(
|
|
4044
|
+
await this.#runtime.reader.getRegistryNonce(
|
|
4045
|
+
p.context,
|
|
4046
|
+
p.registration.walletIdentity,
|
|
4047
|
+
block
|
|
4048
|
+
) === p.registration.nonce,
|
|
4049
|
+
"registry nonce changed; prepare again"
|
|
4050
|
+
);
|
|
4051
|
+
check(
|
|
4052
|
+
(await this.#runtime.reader.getBlock(block.number)).hash === block.hash,
|
|
4053
|
+
"canonical registry block changed during authorization"
|
|
4054
|
+
);
|
|
4055
|
+
}
|
|
4056
|
+
/** Associate a signed/broadcast transaction; ethers owns sending and receipt waiting. */
|
|
4057
|
+
trackTransaction(transactionHash) {
|
|
4058
|
+
check(/^0x[a-fA-F0-9]{64}$/.test(transactionHash), "invalid registry transaction hash");
|
|
4059
|
+
check(
|
|
4060
|
+
this.#signature !== void 0 && ["ready", "uncertain"].includes(this.status),
|
|
4061
|
+
"registry operation is not ready"
|
|
4062
|
+
);
|
|
4063
|
+
return new _RegistrationOperation(
|
|
4064
|
+
this.#registry,
|
|
4065
|
+
this.#runtime,
|
|
4066
|
+
this.#plan,
|
|
4067
|
+
"uncertain",
|
|
4068
|
+
this.#signature,
|
|
4069
|
+
transactionHash
|
|
4070
|
+
);
|
|
4071
|
+
}
|
|
4072
|
+
async reconcile(options = {}) {
|
|
4073
|
+
options.signal?.throwIfAborted();
|
|
4074
|
+
const { reader } = this.#runtime;
|
|
4075
|
+
const p = this.#plan;
|
|
4076
|
+
await this.#registry.validateDeployment(reader);
|
|
4077
|
+
if (this.#anchor && (await reader.getBlock(this.#anchor.number)).hash !== this.#anchor.hash) {
|
|
4078
|
+
return new _RegistrationOperation(
|
|
4079
|
+
this.#registry,
|
|
4080
|
+
this.#runtime,
|
|
4081
|
+
p,
|
|
4082
|
+
"reorged",
|
|
4083
|
+
this.#signature,
|
|
4084
|
+
this.#hash
|
|
4085
|
+
);
|
|
4086
|
+
}
|
|
4087
|
+
const hash = options.transactionHash ?? this.#hash;
|
|
4088
|
+
const receipt = hash ? await reader.getReceipt(hash) : null;
|
|
4089
|
+
if (receipt) {
|
|
4090
|
+
check(
|
|
4091
|
+
receipt.transactionHash === hash && (await reader.getBlock(receipt.block.number)).hash === receipt.block.hash,
|
|
4092
|
+
"registry receipt is not canonical"
|
|
4093
|
+
);
|
|
4094
|
+
const transaction = await reader.getTransaction(hash);
|
|
4095
|
+
const call = this.call();
|
|
4096
|
+
check(
|
|
4097
|
+
transaction && transaction.transactionHash === hash && transaction.to.toLowerCase() === call.to.toLowerCase() && transaction.data.toLowerCase() === call.data.toLowerCase() && transaction.value === 0n && (this.#signature !== "0x" || BigInt(transaction.from) === BigInt(p.registration.walletIdentity)),
|
|
4098
|
+
"registry transaction differs from frozen request"
|
|
4099
|
+
);
|
|
4100
|
+
check(
|
|
4101
|
+
receipt.status === "success" || receipt.status === "reverted",
|
|
4102
|
+
"registry execution status is missing"
|
|
4103
|
+
);
|
|
4104
|
+
if (receipt.status === "success") {
|
|
4105
|
+
const found = receipt.logs.some((log) => {
|
|
4106
|
+
if (log.address.toLowerCase() !== p.context.registryAddress.toLowerCase() || log.transactionHash !== hash) {
|
|
4107
|
+
return false;
|
|
4108
|
+
}
|
|
4109
|
+
try {
|
|
4110
|
+
const event = ((decoded) => ({
|
|
4111
|
+
eventName: decoded.name,
|
|
4112
|
+
args: decoded.args.toObject()
|
|
4113
|
+
}))(
|
|
4114
|
+
new import_ethers2.Interface(invisiAddressRegistryAbi).parseLog({
|
|
4115
|
+
data: log.data,
|
|
4116
|
+
topics: log.topics
|
|
4117
|
+
})
|
|
4118
|
+
);
|
|
4119
|
+
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;
|
|
4120
|
+
} catch {
|
|
4121
|
+
return false;
|
|
4122
|
+
}
|
|
4123
|
+
});
|
|
4124
|
+
check(found, "registry receipt has no matching key update event");
|
|
4125
|
+
check(
|
|
4126
|
+
(await reader.getBlock(receipt.block.number)).hash === receipt.block.hash,
|
|
4127
|
+
"registry block changed during confirmation"
|
|
4128
|
+
);
|
|
4129
|
+
options.signal?.throwIfAborted();
|
|
4130
|
+
return new _RegistrationOperation(
|
|
4131
|
+
this.#registry,
|
|
4132
|
+
this.#runtime,
|
|
4133
|
+
p,
|
|
4134
|
+
"confirmed",
|
|
4135
|
+
this.#signature,
|
|
4136
|
+
hash,
|
|
4137
|
+
receipt.block
|
|
4138
|
+
);
|
|
4139
|
+
}
|
|
4140
|
+
}
|
|
4141
|
+
const head = await reader.getBlock(await reader.getLatestBlockNumber());
|
|
4142
|
+
const nonce = await reader.getRegistryNonce(p.context, p.registration.walletIdentity, head);
|
|
4143
|
+
check(
|
|
4144
|
+
(await reader.getBlock(head.number)).hash === head.hash,
|
|
4145
|
+
"canonical registry block changed during reconciliation"
|
|
4146
|
+
);
|
|
4147
|
+
return new _RegistrationOperation(
|
|
4148
|
+
this.#registry,
|
|
4149
|
+
this.#runtime,
|
|
4150
|
+
p,
|
|
4151
|
+
head.timestamp > p.registration.deadline ? "expired" : nonce !== p.registration.nonce ? "failed" : "uncertain",
|
|
4152
|
+
this.#signature,
|
|
4153
|
+
hash
|
|
4154
|
+
);
|
|
4155
|
+
}
|
|
4156
|
+
toJSON() {
|
|
4157
|
+
return {
|
|
4158
|
+
id: this.id,
|
|
4159
|
+
kind: this.#plan.update ? "update-receiving-keys" : "register-receiving-keys",
|
|
4160
|
+
status: this.status
|
|
4161
|
+
};
|
|
4162
|
+
}
|
|
4163
|
+
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
4164
|
+
return this.toJSON();
|
|
4165
|
+
}
|
|
4166
|
+
};
|
|
4167
|
+
|
|
4168
|
+
// src/AddressRegistry.ts
|
|
4169
|
+
var AddressRegistry = class {
|
|
4170
|
+
context;
|
|
4171
|
+
#lookup;
|
|
4172
|
+
expectedRuntimeCodeHash;
|
|
4173
|
+
constructor(context, options = {}) {
|
|
4174
|
+
if (typeof context.chainId !== "bigint" || context.chainId < 0n || context.chainId >= 1n << 64n || BigInt((0, import_ethers3.getAddress)(context.registryAddress)) === 0n) {
|
|
4175
|
+
throw new Error("invalid registry context");
|
|
4176
|
+
}
|
|
4177
|
+
this.context = Object.freeze({
|
|
4178
|
+
...context,
|
|
4179
|
+
registryAddress: (0, import_ethers3.getAddress)(context.registryAddress)
|
|
4180
|
+
});
|
|
4181
|
+
this.#lookup = options.lookup;
|
|
4182
|
+
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
4183
|
+
if (this.expectedRuntimeCodeHash && !/^0x[0-9a-f]{64}$/.test(this.expectedRuntimeCodeHash)) {
|
|
4184
|
+
throw new Error("invalid registry runtime profile");
|
|
4185
|
+
}
|
|
4186
|
+
Object.freeze(this);
|
|
4187
|
+
}
|
|
4188
|
+
async validateDeployment(reader) {
|
|
4189
|
+
if (!this.expectedRuntimeCodeHash) {
|
|
4190
|
+
throw new import_core3.MissingCapabilityError("trusted registry deployment profile");
|
|
4191
|
+
}
|
|
4192
|
+
if (await reader.getChainId() !== this.context.chainId) {
|
|
4193
|
+
throw new Error("registry chain mismatch");
|
|
4194
|
+
}
|
|
4195
|
+
const code = await reader.getCode(this.context.registryAddress);
|
|
4196
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || (0, import_ethers3.keccak256)(code) !== this.expectedRuntimeCodeHash) {
|
|
4197
|
+
throw new Error("registry runtime profile mismatch");
|
|
4198
|
+
}
|
|
4199
|
+
}
|
|
4200
|
+
prepareRegistration(options) {
|
|
4201
|
+
return RegistrationOperation.prepare(this, options);
|
|
4202
|
+
}
|
|
4203
|
+
async resolve(address) {
|
|
4204
|
+
const receiving = import_core3.ReceivingAddress.parse(address);
|
|
4205
|
+
if (receiving.kind === "short" && !this.#lookup) {
|
|
4206
|
+
throw new import_core3.MissingCapabilityError("registry reader");
|
|
4207
|
+
}
|
|
4208
|
+
return (await receiving.resolve(this.#lookup)).toString();
|
|
4209
|
+
}
|
|
4210
|
+
typedData(registration, options) {
|
|
4211
|
+
return registrationTypedData(this.context, registration, options);
|
|
4212
|
+
}
|
|
4213
|
+
digest(registration, options) {
|
|
4214
|
+
return registrationDigest(this.context, registration, options);
|
|
4215
|
+
}
|
|
4216
|
+
buildCall(registration, signature, options) {
|
|
4217
|
+
return buildRegistrationCalldata(this.context, registration, signature, options);
|
|
4218
|
+
}
|
|
4219
|
+
};
|
|
4220
|
+
|
|
4221
|
+
// src/credit-create.ts
|
|
4222
|
+
var import_ethers5 = require("ethers");
|
|
4223
|
+
var import_core4 = require("@invisi-labs/core");
|
|
4224
|
+
|
|
4225
|
+
// src/validation.ts
|
|
4226
|
+
var import_ethers4 = require("ethers");
|
|
4227
|
+
var FIELD_MODULUS = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
4228
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
4229
|
+
var ZERO_WORD = (0, import_ethers4.toBeHex)(0n, 32);
|
|
4230
|
+
var EMPTY_PERMIT = {
|
|
4231
|
+
deadline: 0n,
|
|
4232
|
+
v: 0,
|
|
4233
|
+
r: ZERO_WORD,
|
|
4234
|
+
s: ZERO_WORD
|
|
4235
|
+
};
|
|
4236
|
+
var EMPTY_FUNDING = {
|
|
4237
|
+
payer: ZERO_ADDRESS,
|
|
4238
|
+
amount: 0n,
|
|
4239
|
+
sigNonce: 0n,
|
|
4240
|
+
deadline: 0n,
|
|
4241
|
+
signature: "0x",
|
|
4242
|
+
permit: EMPTY_PERMIT
|
|
4243
|
+
};
|
|
4244
|
+
function uint(v, bits, name = "value") {
|
|
4245
|
+
if (typeof v !== "bigint" && typeof v !== "number" && typeof v !== "string" || typeof v === "number" && !Number.isSafeInteger(v))
|
|
4246
|
+
throw new Error(`${name} must be an integer`);
|
|
4247
|
+
const n = BigInt(v);
|
|
4248
|
+
if (n < 0n || n >= 1n << BigInt(bits)) throw new Error(`${name} exceeds u${bits}`);
|
|
4249
|
+
return n;
|
|
4250
|
+
}
|
|
4251
|
+
function field(v, name = "field") {
|
|
4252
|
+
const n = uint(v, 256, name);
|
|
4253
|
+
if (n >= FIELD_MODULUS) throw new Error(`${name} is noncanonical field`);
|
|
4254
|
+
return n;
|
|
4255
|
+
}
|
|
4256
|
+
var word = (v) => (0, import_ethers4.toBeHex)(typeof v === "bigint" ? v : BigInt(v), 32);
|
|
4257
|
+
function dense(v, name) {
|
|
4258
|
+
if (!Array.isArray(v)) throw new Error(`${name} must be array`);
|
|
4259
|
+
for (let i = 0; i < v.length; i++)
|
|
4260
|
+
if (!Object.hasOwn(v, i) || v[i] === void 0 || v[i] === null)
|
|
4261
|
+
throw new Error(`${name} has missing or sparse entries`);
|
|
4262
|
+
return v;
|
|
4263
|
+
}
|
|
4264
|
+
function known(v, keys, name = "params") {
|
|
4265
|
+
if (!v || typeof v !== "object" || Array.isArray(v) || Object.keys(v).some((k) => !keys.includes(k)))
|
|
4266
|
+
throw new Error(`${name} has unsupported fields`);
|
|
4267
|
+
}
|
|
4268
|
+
function notes(v, name) {
|
|
4269
|
+
const r = dense(v, name).map((v2) => word(field(v2, name)));
|
|
4270
|
+
if (r.some((v2) => BigInt(v2) === 0n) || new Set(r).size !== r.length)
|
|
4271
|
+
throw new Error(`duplicate or zero ${name}`);
|
|
4272
|
+
return r;
|
|
4273
|
+
}
|
|
4274
|
+
function envelope(v, length, version) {
|
|
4275
|
+
if (!(0, import_ethers4.isHexString)(v) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(v) || (0, import_ethers4.dataLength)(v) !== length)
|
|
4276
|
+
throw new Error(`ciphertext must be ${length} bytes`);
|
|
4277
|
+
if (version !== void 0 && Number.parseInt(v.slice(2, 4), 16) !== version)
|
|
4278
|
+
throw new Error("unsupported ciphertext envelope version");
|
|
4279
|
+
return v;
|
|
4280
|
+
}
|
|
4281
|
+
function normalizeContext(c) {
|
|
4282
|
+
return {
|
|
4283
|
+
...c,
|
|
4284
|
+
chainId: uint(c.chainId, 64, "chainId"),
|
|
4285
|
+
protocolAddress: (0, import_ethers4.getAddress)(c.protocolAddress),
|
|
4286
|
+
tokenAddress: (0, import_ethers4.getAddress)(c.tokenAddress)
|
|
4287
|
+
};
|
|
4288
|
+
}
|
|
4289
|
+
function checkDeadline(c, value) {
|
|
4290
|
+
const n = uint(value, 64, "deadline");
|
|
4291
|
+
if (c.now !== void 0 && n < uint(c.now, 64, "now")) throw new Error("deadline has expired");
|
|
4292
|
+
return n;
|
|
4293
|
+
}
|
|
4294
|
+
function normalizeSources(sources, inputCount, capacity) {
|
|
4295
|
+
dense(sources, "sources");
|
|
4296
|
+
if (inputCount < 0 || inputCount > capacity || sources.length > inputCount || (inputCount === 0 ? sources.length !== 0 : sources.length === 0))
|
|
4297
|
+
throw new Error("source count must be 1..inputCount, or empty for zero inputs");
|
|
4298
|
+
let previous = 0n;
|
|
4299
|
+
return sources.map((s) => {
|
|
4300
|
+
known(s, ["treeId", "merkleRoot"], "source");
|
|
4301
|
+
const treeId = uint(s.treeId, 64, "treeId"), merkleRoot = word(field(s.merkleRoot, "merkleRoot"));
|
|
4302
|
+
if (treeId === 0n || treeId <= previous || BigInt(merkleRoot) === 0n)
|
|
4303
|
+
throw new Error("sources must have positive roots and strictly ascending tree IDs");
|
|
4304
|
+
previous = treeId;
|
|
4305
|
+
return { treeId, merkleRoot };
|
|
4306
|
+
});
|
|
4307
|
+
}
|
|
4308
|
+
var pad = (v, n) => [
|
|
4309
|
+
...v,
|
|
4310
|
+
...Array(n - v.length).fill(0n)
|
|
4311
|
+
];
|
|
4312
|
+
function normalizeDelivery(value, options = {}) {
|
|
4313
|
+
known(value, ["ciphertext", "clue"], "delivery");
|
|
4314
|
+
if (options.empty) {
|
|
4315
|
+
if (value.ciphertext !== "0x" || value.clue !== "0x")
|
|
4316
|
+
throw new Error("absent output requires an empty delivery");
|
|
4317
|
+
return { ciphertext: "0x", clue: "0x" };
|
|
4318
|
+
}
|
|
4319
|
+
const ciphertext = envelope(
|
|
4320
|
+
value.ciphertext,
|
|
4321
|
+
options.credit ? 400 : 158,
|
|
4322
|
+
options.credit ? 3 : 1
|
|
4323
|
+
);
|
|
4324
|
+
const clue = envelope(value.clue, 68);
|
|
4325
|
+
if (clue.slice(130, 132).toLowerCase() !== "18") throw new Error("clue precision must be 24");
|
|
4326
|
+
return { ciphertext, clue };
|
|
4327
|
+
}
|
|
4328
|
+
var deliveriesHash = (v) => (0, import_ethers4.keccak256)(
|
|
4329
|
+
import_ethers4.AbiCoder.defaultAbiCoder().encode(
|
|
4330
|
+
[
|
|
4331
|
+
{
|
|
4332
|
+
type: "tuple[]",
|
|
4333
|
+
components: [
|
|
4334
|
+
{ name: "ciphertext", type: "bytes" },
|
|
4335
|
+
{ name: "clue", type: "bytes" }
|
|
4336
|
+
]
|
|
4337
|
+
}
|
|
4338
|
+
].map((parameter) => import_ethers4.ParamType.from(parameter)),
|
|
4339
|
+
[dense(v, "deliveries")]
|
|
4340
|
+
)
|
|
4341
|
+
);
|
|
4342
|
+
function normalizeFunding(input = {}) {
|
|
4343
|
+
const f = { ...EMPTY_FUNDING, ...input };
|
|
4344
|
+
(0, import_ethers4.getAddress)(f.payer);
|
|
4345
|
+
uint(f.amount, 128, "depositAmount");
|
|
4346
|
+
uint(f.sigNonce, 256, "sigNonce");
|
|
3928
4347
|
uint(f.deadline, 256, "funding deadline");
|
|
3929
|
-
if (!(0,
|
|
4348
|
+
if (!(0, import_ethers4.isHexString)(f.signature) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(f.signature))
|
|
3930
4349
|
throw new Error("invalid signature bytes");
|
|
3931
4350
|
const p = f.permit;
|
|
3932
4351
|
uint(p.deadline, 256);
|
|
3933
4352
|
uint(p.v, 8);
|
|
3934
4353
|
for (const v of [p.r, p.s])
|
|
3935
|
-
if (!(0,
|
|
4354
|
+
if (!(0, import_ethers4.isHexString)(v) || (0, import_ethers4.dataLength)(v) !== 32) throw new Error("permit r/s must be bytes32");
|
|
3936
4355
|
if (f.amount === 0n !== (BigInt(f.payer) === 0n))
|
|
3937
4356
|
throw new Error("deposit amount and payer must both be zero or positive");
|
|
3938
4357
|
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))
|
|
3939
4358
|
throw new Error("zero funding must be entirely empty");
|
|
3940
|
-
return { ...f, payer: (0,
|
|
4359
|
+
return { ...f, payer: (0, import_ethers4.getAddress)(f.payer) };
|
|
3941
4360
|
}
|
|
3942
4361
|
function validateFundingSubmission(f, caller, now) {
|
|
3943
4362
|
if (f.signature !== "0x" && now !== void 0 && uint(now, 64, "now") > f.deadline)
|
|
3944
4363
|
throw new Error("funding authorization has expired");
|
|
3945
|
-
if (f.signature === "0x" && (f.sigNonce !== 0n || f.deadline !== 0n || caller !== void 0 && f.amount > 0n && (0,
|
|
4364
|
+
if (f.signature === "0x" && (f.sigNonce !== 0n || f.deadline !== 0n || caller !== void 0 && f.amount > 0n && (0, import_ethers4.getAddress)(caller) !== f.payer))
|
|
3946
4365
|
throw new Error("direct funding requires payer caller and zero nonce/deadline");
|
|
3947
4366
|
}
|
|
3948
4367
|
var getEIP712Domain = (c) => ({
|
|
3949
4368
|
name: "InvisibleProtocol",
|
|
3950
4369
|
version: "1",
|
|
3951
4370
|
chainId: uint(c.chainId, 64),
|
|
3952
|
-
verifyingContract: (0,
|
|
4371
|
+
verifyingContract: (0, import_ethers4.getAddress)(c.protocolAddress)
|
|
3953
4372
|
});
|
|
3954
4373
|
var fundingFields = [
|
|
3955
4374
|
{ name: "requestHash", type: "bytes32" },
|
|
@@ -3975,9 +4394,9 @@ var CREATE_CREDIT_FIELDS = [
|
|
|
3975
4394
|
];
|
|
3976
4395
|
function validateCreateCreditRequest(c, p, cs, funding = {}) {
|
|
3977
4396
|
known(p, CREATE_CREDIT_FIELDS);
|
|
3978
|
-
if ((0,
|
|
4397
|
+
if ((0, import_ethers5.getAddress)(p.token) !== (0, import_ethers5.getAddress)(c.tokenAddress))
|
|
3979
4398
|
throw new Error("request token mismatch");
|
|
3980
|
-
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 = (0,
|
|
4399
|
+
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 = (0, import_ethers5.getAddress)(p.owner), expiry = uint(p.expiry, 64, "expiry"), deadline = checkDeadline(c, p.deadline), f = normalizeFunding(funding);
|
|
3981
4400
|
if (BigInt(creditCommitment) === 0n || creditCommitment === changeCommitment)
|
|
3982
4401
|
throw new Error("zero or duplicate commitment");
|
|
3983
4402
|
if (BigInt(owner) === 0n || expiry === 0n || c.now !== void 0 && expiry <= c.now)
|
|
@@ -4034,7 +4453,7 @@ function createCreditBaseInputs(c, p, cs, f = {}) {
|
|
|
4034
4453
|
function createCreditPublicInputs(c, p, deliveries, funding = {}) {
|
|
4035
4454
|
const base = createCreditBaseInputs(c, p, deliveries, funding);
|
|
4036
4455
|
const digest = BigInt(
|
|
4037
|
-
(0,
|
|
4456
|
+
(0, import_core4.computeWalletAuthorizationDigest)({
|
|
4038
4457
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4039
4458
|
operation: "create-credit",
|
|
4040
4459
|
capacity: 10,
|
|
@@ -4050,17 +4469,17 @@ var hashContext = {
|
|
|
4050
4469
|
};
|
|
4051
4470
|
function createCreditRequestHash(p, cs, f = {}) {
|
|
4052
4471
|
const r = validateCreateCreditRequest({ ...hashContext, tokenAddress: p.token }, p, cs, f);
|
|
4053
|
-
return (0,
|
|
4054
|
-
|
|
4472
|
+
return (0, import_ethers5.keccak256)(
|
|
4473
|
+
import_ethers5.AbiCoder.defaultAbiCoder().encode(
|
|
4055
4474
|
[
|
|
4056
4475
|
{ type: "bytes32" },
|
|
4057
4476
|
creationTuple,
|
|
4058
4477
|
{ type: "bytes32" },
|
|
4059
4478
|
{ type: "address" },
|
|
4060
4479
|
{ type: "uint256" }
|
|
4061
|
-
].map((parameter) =>
|
|
4480
|
+
].map((parameter) => import_ethers5.ParamType.from(parameter)),
|
|
4062
4481
|
[
|
|
4063
|
-
(0,
|
|
4482
|
+
(0, import_ethers5.keccak256)(new TextEncoder().encode("InvisiCreateCredit")),
|
|
4064
4483
|
p,
|
|
4065
4484
|
deliveriesHash(cs),
|
|
4066
4485
|
r.funding.payer,
|
|
@@ -4070,7 +4489,7 @@ function createCreditRequestHash(p, cs, f = {}) {
|
|
|
4070
4489
|
);
|
|
4071
4490
|
}
|
|
4072
4491
|
function encodeCreateCreditTypedData(c, p, deliveries, funding = {}) {
|
|
4073
|
-
return (0,
|
|
4492
|
+
return (0, import_core4.walletAuthorizationTypedData)({
|
|
4074
4493
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4075
4494
|
operation: "create-credit",
|
|
4076
4495
|
capacity: 10,
|
|
@@ -4097,7 +4516,7 @@ function buildCreateCreditCalldata(p) {
|
|
|
4097
4516
|
const r = validateCreateCreditRequest(p.context, p.params, p.deliveries, p.funding);
|
|
4098
4517
|
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
4099
4518
|
return {
|
|
4100
|
-
data: new
|
|
4519
|
+
data: new import_ethers5.Interface(invisiProtocolAbi).encodeFunctionData("createCredit", [
|
|
4101
4520
|
encodeCreditProof(p.proof),
|
|
4102
4521
|
p.params,
|
|
4103
4522
|
p.deliveries,
|
|
@@ -4107,17 +4526,17 @@ function buildCreateCreditCalldata(p) {
|
|
|
4107
4526
|
};
|
|
4108
4527
|
}
|
|
4109
4528
|
function encodeCreditProof(proof) {
|
|
4110
|
-
if (!(0,
|
|
4529
|
+
if (!(0, import_ethers5.isHexString)(proof) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(proof) || (0, import_ethers5.dataLength)(proof) === 0)
|
|
4111
4530
|
throw new Error("empty or malformed Credit proof");
|
|
4112
|
-
return
|
|
4113
|
-
["uint8", "bytes"].map((parameter) =>
|
|
4531
|
+
return import_ethers5.AbiCoder.defaultAbiCoder().encode(
|
|
4532
|
+
["uint8", "bytes"].map((parameter) => import_ethers5.ParamType.from(parameter)),
|
|
4114
4533
|
[0, proof]
|
|
4115
4534
|
);
|
|
4116
4535
|
}
|
|
4117
4536
|
|
|
4118
4537
|
// src/credit-lifecycle.ts
|
|
4119
|
-
var
|
|
4120
|
-
var
|
|
4538
|
+
var import_ethers6 = require("ethers");
|
|
4539
|
+
var import_core5 = require("@invisi-labs/core");
|
|
4121
4540
|
var CREDIT_DRAW_CAPACITIES = [1, 12, 50, 120];
|
|
4122
4541
|
function selectCreditDrawCircuit(count) {
|
|
4123
4542
|
if (!Number.isInteger(count) || count < 1 || count > 120)
|
|
@@ -4142,7 +4561,7 @@ function validateCreditDrawRequest(c, p, cs) {
|
|
|
4142
4561
|
"totalAmount",
|
|
4143
4562
|
"deadline"
|
|
4144
4563
|
]);
|
|
4145
|
-
if ((0,
|
|
4564
|
+
if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
|
|
4146
4565
|
throw new Error("request token mismatch");
|
|
4147
4566
|
const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), profile = selectCreditDrawCircuit(ns.length), sources = normalizeSources(p.sources, ns.length, profile.maxSize);
|
|
4148
4567
|
for (const [key, v] of Object.entries({
|
|
@@ -4160,7 +4579,7 @@ function validateCreditDrawRequest(c, p, cs) {
|
|
|
4160
4579
|
if (BigInt(remainderCommitments[i]) === 0n && BigInt(recoveryAmounts[i]) !== 0n)
|
|
4161
4580
|
throw new Error("full draw requires zero recovery amount");
|
|
4162
4581
|
}
|
|
4163
|
-
const spender = (0,
|
|
4582
|
+
const spender = (0, import_ethers6.getAddress)(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
|
|
4164
4583
|
if (BigInt(spender) === 0n || totalAmount === 0n)
|
|
4165
4584
|
throw new Error("spender and total amount must be positive");
|
|
4166
4585
|
if (dense(cs, "deliveries").length !== 2 * ns.length)
|
|
@@ -4211,9 +4630,9 @@ function creditDrawBaseInputs(c, p, cs) {
|
|
|
4211
4630
|
}
|
|
4212
4631
|
function validateCancelCreditRequest(c, p) {
|
|
4213
4632
|
known(p, ["token", "source", "nullifier", "owner", "amount", "deadline"]);
|
|
4214
|
-
if ((0,
|
|
4633
|
+
if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
|
|
4215
4634
|
throw new Error("request token mismatch");
|
|
4216
|
-
const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = (0,
|
|
4635
|
+
const ctx = normalizeContext(c), source = normalizeSources([p.source], 1, 1)[0], nullifier = notes([p.nullifier], "nullifier")[0], owner = (0, import_ethers6.getAddress)(p.owner), amount = uint(p.amount, 126, "amount");
|
|
4217
4636
|
if (BigInt(owner) === 0n || amount === 0n) throw new Error("owner and amount must be positive");
|
|
4218
4637
|
return {
|
|
4219
4638
|
...ctx,
|
|
@@ -4271,10 +4690,10 @@ var hashContext2 = {
|
|
|
4271
4690
|
};
|
|
4272
4691
|
function cancelCreditRequestHash(p) {
|
|
4273
4692
|
validateCancelCreditRequest({ ...hashContext2, tokenAddress: p.token }, p);
|
|
4274
|
-
return (0,
|
|
4275
|
-
|
|
4276
|
-
[{ type: "bytes32" }, cancelTuple].map((parameter) =>
|
|
4277
|
-
[(0,
|
|
4693
|
+
return (0, import_ethers6.keccak256)(
|
|
4694
|
+
import_ethers6.AbiCoder.defaultAbiCoder().encode(
|
|
4695
|
+
[{ type: "bytes32" }, cancelTuple].map((parameter) => import_ethers6.ParamType.from(parameter)),
|
|
4696
|
+
[(0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiCancelCredit")), p]
|
|
4278
4697
|
)
|
|
4279
4698
|
);
|
|
4280
4699
|
}
|
|
@@ -4285,17 +4704,17 @@ function topUpCreditRequestHash(p, cs, f = {}) {
|
|
|
4285
4704
|
cs,
|
|
4286
4705
|
f
|
|
4287
4706
|
);
|
|
4288
|
-
return (0,
|
|
4289
|
-
|
|
4707
|
+
return (0, import_ethers6.keccak256)(
|
|
4708
|
+
import_ethers6.AbiCoder.defaultAbiCoder().encode(
|
|
4290
4709
|
[
|
|
4291
4710
|
{ type: "bytes32" },
|
|
4292
4711
|
topTuple,
|
|
4293
4712
|
{ type: "bytes32" },
|
|
4294
4713
|
{ type: "address" },
|
|
4295
4714
|
{ type: "uint256" }
|
|
4296
|
-
].map((parameter) =>
|
|
4715
|
+
].map((parameter) => import_ethers6.ParamType.from(parameter)),
|
|
4297
4716
|
[
|
|
4298
|
-
(0,
|
|
4717
|
+
(0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiTopUpCredit")),
|
|
4299
4718
|
p,
|
|
4300
4719
|
deliveriesHash(cs),
|
|
4301
4720
|
r.creation.funding.payer,
|
|
@@ -4305,7 +4724,7 @@ function topUpCreditRequestHash(p, cs, f = {}) {
|
|
|
4305
4724
|
);
|
|
4306
4725
|
}
|
|
4307
4726
|
function authorize(c, operation, capacity, words) {
|
|
4308
|
-
return (0,
|
|
4727
|
+
return (0, import_core5.walletAuthorizationTypedData)({
|
|
4309
4728
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4310
4729
|
operation,
|
|
4311
4730
|
capacity,
|
|
@@ -4314,7 +4733,7 @@ function authorize(c, operation, capacity, words) {
|
|
|
4314
4733
|
}
|
|
4315
4734
|
function appendDigest(c, operation, capacity, words) {
|
|
4316
4735
|
const digest = BigInt(
|
|
4317
|
-
(0,
|
|
4736
|
+
(0, import_core5.computeWalletAuthorizationDigest)({
|
|
4318
4737
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4319
4738
|
operation,
|
|
4320
4739
|
capacity,
|
|
@@ -4370,7 +4789,7 @@ function encodeTopUpCreditFundingTypedData(c, p, cs, f) {
|
|
|
4370
4789
|
function buildCreditDrawCalldata(p) {
|
|
4371
4790
|
validateCreditDrawRequest(p.context, p.params, p.deliveries);
|
|
4372
4791
|
return {
|
|
4373
|
-
data: new
|
|
4792
|
+
data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("creditDraw", [
|
|
4374
4793
|
encodeCreditProof(p.proof),
|
|
4375
4794
|
p.params,
|
|
4376
4795
|
p.deliveries
|
|
@@ -4382,7 +4801,7 @@ function buildCreditDrawCalldata(p) {
|
|
|
4382
4801
|
function buildCancelCreditCalldata(p) {
|
|
4383
4802
|
validateCancelCreditRequest(p.context, p.params);
|
|
4384
4803
|
return {
|
|
4385
|
-
data: new
|
|
4804
|
+
data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("cancelCredit", [
|
|
4386
4805
|
encodeCreditProof(p.proof),
|
|
4387
4806
|
p.params
|
|
4388
4807
|
])
|
|
@@ -4392,7 +4811,7 @@ function buildTopUpCreditCalldata(p) {
|
|
|
4392
4811
|
const r = validateTopUpCreditRequest(p.context, p.params, p.deliveries, p.funding);
|
|
4393
4812
|
validateFundingSubmission(r.creation.funding, p.caller, p.context.now);
|
|
4394
4813
|
return {
|
|
4395
|
-
data: new
|
|
4814
|
+
data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("topUpCredit", [
|
|
4396
4815
|
encodeCreditProof(p.proof),
|
|
4397
4816
|
p.params,
|
|
4398
4817
|
p.deliveries,
|
|
@@ -4403,8 +4822,8 @@ function buildTopUpCreditCalldata(p) {
|
|
|
4403
4822
|
}
|
|
4404
4823
|
|
|
4405
4824
|
// src/funds.ts
|
|
4406
|
-
var
|
|
4407
|
-
var
|
|
4825
|
+
var import_ethers7 = require("ethers");
|
|
4826
|
+
var import_core6 = require("@invisi-labs/core");
|
|
4408
4827
|
var TRANSACT_CAPACITIES = [14, 56, 112, 168];
|
|
4409
4828
|
function selectTransactCapacity(inputs, outputs) {
|
|
4410
4829
|
if (!Number.isInteger(inputs) || !Number.isInteger(outputs) || inputs < 0 || outputs < 0 || inputs + outputs < 1 || inputs === 0 && outputs < 2 || inputs + outputs > 168)
|
|
@@ -4413,7 +4832,7 @@ function selectTransactCapacity(inputs, outputs) {
|
|
|
4413
4832
|
}
|
|
4414
4833
|
function normalizeTransactRequest(c, p, cs, funding = {}) {
|
|
4415
4834
|
const ctx = normalizeContext(c);
|
|
4416
|
-
if ((0,
|
|
4835
|
+
if ((0, import_ethers7.getAddress)(p.token) !== ctx.tokenAddress)
|
|
4417
4836
|
throw new Error("request token mismatch");
|
|
4418
4837
|
known(p, [
|
|
4419
4838
|
"token",
|
|
@@ -4427,7 +4846,7 @@ function normalizeTransactRequest(c, p, cs, funding = {}) {
|
|
|
4427
4846
|
const ns = notes(p.nullifiers, "nullifiers"), os = notes(p.outputCommitments, "outputCommitments"), capacity = selectTransactCapacity(ns.length, os.length);
|
|
4428
4847
|
const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map((v) => normalizeDelivery(v));
|
|
4429
4848
|
if (deliveries.length !== os.length) throw new Error("deliveries count mismatch");
|
|
4430
|
-
const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = (0,
|
|
4849
|
+
const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = (0, import_ethers7.getAddress)(p.withdrawalAddress), f = normalizeFunding(funding);
|
|
4431
4850
|
if (withdrawalAmount === 0n !== (BigInt(withdrawalAddress) === 0n) || os.length === 0 && withdrawalAmount === 0n)
|
|
4432
4851
|
throw new Error("invalid withdrawal");
|
|
4433
4852
|
if (ns.length === 0 && (f.amount === 0n || withdrawalAmount !== 0n))
|
|
@@ -4483,7 +4902,7 @@ function transactPublicInputs(c, p, cs, f = {}) {
|
|
|
4483
4902
|
}
|
|
4484
4903
|
function encodeTransactTypedData(c, p, deliveries, f = {}) {
|
|
4485
4904
|
const r = normalizeTransactRequest(c, p, deliveries, f);
|
|
4486
|
-
return (0,
|
|
4905
|
+
return (0, import_core6.walletAuthorizationTypedData)({
|
|
4487
4906
|
context: { chainId: r.chainId, protocolAddress: BigInt(r.protocolAddress) },
|
|
4488
4907
|
operation: "transact",
|
|
4489
4908
|
capacity: r.capacity,
|
|
@@ -4507,24 +4926,24 @@ function transactFundingRequestHash(proof, p, cs) {
|
|
|
4507
4926
|
withdrawalAmount: p.withdrawalAmount,
|
|
4508
4927
|
deadline: p.deadline
|
|
4509
4928
|
};
|
|
4510
|
-
return p.sources.length > 1 ? (0,
|
|
4511
|
-
|
|
4929
|
+
return p.sources.length > 1 ? (0, import_ethers7.keccak256)(
|
|
4930
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
4512
4931
|
[{ type: "bytes32" }, { type: "bytes32" }, crossTuple, { type: "bytes32" }].map(
|
|
4513
|
-
(parameter) =>
|
|
4932
|
+
(parameter) => import_ethers7.ParamType.from(parameter)
|
|
4514
4933
|
),
|
|
4515
4934
|
[
|
|
4516
|
-
(0,
|
|
4517
|
-
(0,
|
|
4935
|
+
(0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiCrossTreeTransact")),
|
|
4936
|
+
(0, import_ethers7.keccak256)(proof),
|
|
4518
4937
|
p,
|
|
4519
4938
|
deliveriesHash(cs)
|
|
4520
4939
|
]
|
|
4521
4940
|
)
|
|
4522
|
-
) : (0,
|
|
4523
|
-
|
|
4941
|
+
) : (0, import_ethers7.keccak256)(
|
|
4942
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
4524
4943
|
[{ type: "bytes32" }, singleTuple, { type: "bytes32" }].map(
|
|
4525
|
-
(parameter) =>
|
|
4944
|
+
(parameter) => import_ethers7.ParamType.from(parameter)
|
|
4526
4945
|
),
|
|
4527
|
-
[(0,
|
|
4946
|
+
[(0, import_ethers7.keccak256)(proof), single, deliveriesHash(cs)]
|
|
4528
4947
|
)
|
|
4529
4948
|
);
|
|
4530
4949
|
}
|
|
@@ -4564,7 +4983,7 @@ function buildTransactCalldata(p) {
|
|
|
4564
4983
|
const abi = invisiProtocolAbi.filter(
|
|
4565
4984
|
(item) => item.type === "function" && item.name === "transact" && item.inputs.length === 2 && item.inputs[1]?.type === "tuple"
|
|
4566
4985
|
);
|
|
4567
|
-
const data = new
|
|
4986
|
+
const data = new import_ethers7.Interface(abi).encodeFunctionData("transact", [p.proof, request]);
|
|
4568
4987
|
return { data, capacity: r.capacity, approveAmount: r.depositAmount };
|
|
4569
4988
|
}
|
|
4570
4989
|
function buildTransactAggregateCalldata(p) {
|
|
@@ -4581,7 +5000,7 @@ function buildTransactAggregateCalldata(p) {
|
|
|
4581
5000
|
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
4582
5001
|
}
|
|
4583
5002
|
return {
|
|
4584
|
-
data: new
|
|
5003
|
+
data: new import_ethers7.Interface(
|
|
4585
5004
|
invisiProtocolAbi.filter(
|
|
4586
5005
|
(item) => item.type === "function" && item.name === "transact" && item.inputs[1]?.type === "tuple[]"
|
|
4587
5006
|
)
|
|
@@ -4591,7 +5010,7 @@ function buildTransactAggregateCalldata(p) {
|
|
|
4591
5010
|
}
|
|
4592
5011
|
async function validateShieldRequest(p) {
|
|
4593
5012
|
normalizeContext(p.context);
|
|
4594
|
-
if ((0,
|
|
5013
|
+
if ((0, import_ethers7.getAddress)(p.params.token) !== (0, import_ethers7.getAddress)(p.context.tokenAddress))
|
|
4595
5014
|
throw new Error("request token mismatch");
|
|
4596
5015
|
known(p.params, ["token", "outputCommitments", "deadline"]);
|
|
4597
5016
|
checkDeadline(p.context, p.params.deadline);
|
|
@@ -4605,7 +5024,7 @@ async function validateShieldRequest(p) {
|
|
|
4605
5024
|
if (o.amount === 0n) throw new Error("amount must be positive");
|
|
4606
5025
|
field(o.identity);
|
|
4607
5026
|
normalizeDelivery(cs[i]);
|
|
4608
|
-
if (await (0,
|
|
5027
|
+
if (await (0, import_core6.computeNoteCommitment)(
|
|
4609
5028
|
p.context.chainId,
|
|
4610
5029
|
o.identity,
|
|
4611
5030
|
BigInt(p.context.tokenAddress),
|
|
@@ -4618,22 +5037,22 @@ async function validateShieldRequest(p) {
|
|
|
4618
5037
|
return f;
|
|
4619
5038
|
}
|
|
4620
5039
|
function shieldFundingRequestHash(params, outputs, cs) {
|
|
4621
|
-
const outputHash = (0,
|
|
4622
|
-
|
|
4623
|
-
["(bytes32 identity,uint256 amount)[]"].map((parameter) =>
|
|
5040
|
+
const outputHash = (0, import_ethers7.keccak256)(
|
|
5041
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
5042
|
+
["(bytes32 identity,uint256 amount)[]"].map((parameter) => import_ethers7.ParamType.from(parameter)),
|
|
4624
5043
|
[outputs]
|
|
4625
5044
|
)
|
|
4626
5045
|
);
|
|
4627
|
-
return (0,
|
|
4628
|
-
|
|
5046
|
+
return (0, import_ethers7.keccak256)(
|
|
5047
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
4629
5048
|
[
|
|
4630
5049
|
"bytes32",
|
|
4631
5050
|
"(address token,bytes32[] outputCommitments,uint256 deadline)",
|
|
4632
5051
|
"bytes32",
|
|
4633
5052
|
"bytes32"
|
|
4634
|
-
].map((parameter) =>
|
|
5053
|
+
].map((parameter) => import_ethers7.ParamType.from(parameter)),
|
|
4635
5054
|
[
|
|
4636
|
-
(0,
|
|
5055
|
+
(0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiShield")),
|
|
4637
5056
|
params,
|
|
4638
5057
|
outputHash,
|
|
4639
5058
|
deliveriesHash(cs)
|
|
@@ -4660,7 +5079,7 @@ async function buildShieldCalldata(p) {
|
|
|
4660
5079
|
const f = await validateShieldRequest(p);
|
|
4661
5080
|
validateFundingSubmission(f, p.caller, p.context.now);
|
|
4662
5081
|
return {
|
|
4663
|
-
data: new
|
|
5082
|
+
data: new import_ethers7.Interface(invisiProtocolAbi).encodeFunctionData("shield", [
|
|
4664
5083
|
p.params,
|
|
4665
5084
|
p.outputs,
|
|
4666
5085
|
p.deliveries,
|
|
@@ -4671,7 +5090,7 @@ async function buildShieldCalldata(p) {
|
|
|
4671
5090
|
}
|
|
4672
5091
|
function transactUserPublicInputs(c, p, cs, f = {}) {
|
|
4673
5092
|
const words = transactPublicInputs(c, p, cs, f), digest = BigInt(
|
|
4674
|
-
((typed) =>
|
|
5093
|
+
((typed) => import_ethers7.TypedDataEncoder.hash(
|
|
4675
5094
|
typed.domain,
|
|
4676
5095
|
Object.fromEntries(
|
|
4677
5096
|
Object.entries(typed.types).map(([name, fields]) => [
|
|
@@ -4690,11 +5109,11 @@ function aggregateMemberRequestHash(c, r) {
|
|
|
4690
5109
|
r.params.outputCommitments.length
|
|
4691
5110
|
);
|
|
4692
5111
|
if (capacity !== 14) throw new Error("aggregate supports only capacity 14");
|
|
4693
|
-
return (0,
|
|
4694
|
-
|
|
4695
|
-
["bytes32", "uint256", "bytes32[]"].map((parameter) =>
|
|
5112
|
+
return (0, import_ethers7.keccak256)(
|
|
5113
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
5114
|
+
["bytes32", "uint256", "bytes32[]"].map((parameter) => import_ethers7.ParamType.from(parameter)),
|
|
4696
5115
|
[
|
|
4697
|
-
(0,
|
|
5116
|
+
(0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiAtomicBatchMemberV1")),
|
|
4698
5117
|
BigInt(capacity),
|
|
4699
5118
|
transactPublicInputs(c, r.params, r.deliveries, r.funding)
|
|
4700
5119
|
]
|
|
@@ -4727,6 +5146,240 @@ function encodeAggregateFundingTypedData(c, r) {
|
|
|
4727
5146
|
};
|
|
4728
5147
|
}
|
|
4729
5148
|
|
|
5149
|
+
// src/Protocol.ts
|
|
5150
|
+
var import_ethers9 = require("ethers");
|
|
5151
|
+
var import_rpc = require("@invisi-labs/rpc");
|
|
5152
|
+
|
|
5153
|
+
// src/TokenProtocol.ts
|
|
5154
|
+
var import_ethers8 = require("ethers");
|
|
5155
|
+
var import_core7 = require("@invisi-labs/core");
|
|
5156
|
+
var TokenProtocol = class {
|
|
5157
|
+
context;
|
|
5158
|
+
expectedRuntimeCodeHash;
|
|
5159
|
+
constructor(context, options = {}) {
|
|
5160
|
+
const normalized = normalizeContext(context);
|
|
5161
|
+
if (BigInt(normalized.protocolAddress) === 0n || BigInt(normalized.tokenAddress) === 0n) {
|
|
5162
|
+
throw new Error("deployment addresses must be nonzero");
|
|
5163
|
+
}
|
|
5164
|
+
if (options.expectedRuntimeCodeHash && !/^0x[0-9a-fA-F]{64}$/.test(options.expectedRuntimeCodeHash)) {
|
|
5165
|
+
throw new Error("invalid runtime code hash");
|
|
5166
|
+
}
|
|
5167
|
+
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
5168
|
+
this.context = Object.freeze(normalized);
|
|
5169
|
+
Object.freeze(this);
|
|
5170
|
+
}
|
|
5171
|
+
async validateDeployment(reader, options = {}) {
|
|
5172
|
+
if ((options.requireRuntimeProfile ?? true) && !this.expectedRuntimeCodeHash) {
|
|
5173
|
+
throw new import_core7.MissingCapabilityError("trusted deployment profile");
|
|
5174
|
+
}
|
|
5175
|
+
if (await reader.getChainId() !== this.context.chainId) {
|
|
5176
|
+
throw new Error("deployment chain mismatch");
|
|
5177
|
+
}
|
|
5178
|
+
const code = await reader.getCode(this.context.protocolAddress);
|
|
5179
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || this.expectedRuntimeCodeHash && (0, import_ethers8.keccak256)(code) !== this.expectedRuntimeCodeHash) {
|
|
5180
|
+
throw new Error("deployment runtime code profile mismatch");
|
|
5181
|
+
}
|
|
5182
|
+
const tokenCode = await reader.getCode(this.context.tokenAddress);
|
|
5183
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(tokenCode)) {
|
|
5184
|
+
throw new Error("token address must have contract code");
|
|
5185
|
+
}
|
|
5186
|
+
}
|
|
5187
|
+
transact(request) {
|
|
5188
|
+
return {
|
|
5189
|
+
to: this.context.protocolAddress,
|
|
5190
|
+
value: 0n,
|
|
5191
|
+
...buildTransactCalldata({ ...request, context: this.context })
|
|
5192
|
+
};
|
|
5193
|
+
}
|
|
5194
|
+
aggregate(request) {
|
|
5195
|
+
return {
|
|
5196
|
+
to: this.context.protocolAddress,
|
|
5197
|
+
value: 0n,
|
|
5198
|
+
...buildTransactAggregateCalldata({ ...request, context: this.context })
|
|
5199
|
+
};
|
|
5200
|
+
}
|
|
5201
|
+
async shield(request) {
|
|
5202
|
+
return {
|
|
5203
|
+
to: this.context.protocolAddress,
|
|
5204
|
+
value: 0n,
|
|
5205
|
+
...await buildShieldCalldata({ ...request, context: this.context })
|
|
5206
|
+
};
|
|
5207
|
+
}
|
|
5208
|
+
createCredit(request) {
|
|
5209
|
+
return {
|
|
5210
|
+
to: this.context.protocolAddress,
|
|
5211
|
+
value: 0n,
|
|
5212
|
+
...buildCreateCreditCalldata({ ...request, context: this.context })
|
|
5213
|
+
};
|
|
5214
|
+
}
|
|
5215
|
+
drawCredit(request) {
|
|
5216
|
+
return {
|
|
5217
|
+
to: this.context.protocolAddress,
|
|
5218
|
+
value: 0n,
|
|
5219
|
+
...buildCreditDrawCalldata({ ...request, context: this.context })
|
|
5220
|
+
};
|
|
5221
|
+
}
|
|
5222
|
+
cancelCredit(request) {
|
|
5223
|
+
return {
|
|
5224
|
+
to: this.context.protocolAddress,
|
|
5225
|
+
value: 0n,
|
|
5226
|
+
...buildCancelCreditCalldata({ ...request, context: this.context })
|
|
5227
|
+
};
|
|
5228
|
+
}
|
|
5229
|
+
topUpCredit(request) {
|
|
5230
|
+
return {
|
|
5231
|
+
to: this.context.protocolAddress,
|
|
5232
|
+
value: 0n,
|
|
5233
|
+
...buildTopUpCreditCalldata({ ...request, context: this.context })
|
|
5234
|
+
};
|
|
5235
|
+
}
|
|
5236
|
+
};
|
|
5237
|
+
|
|
5238
|
+
// src/Protocol.ts
|
|
5239
|
+
var Protocol = class _Protocol {
|
|
5240
|
+
deployment;
|
|
5241
|
+
context;
|
|
5242
|
+
constructor(options) {
|
|
5243
|
+
known(options, ["deployment"], "protocol options");
|
|
5244
|
+
this.deployment = (0, import_rpc.defineDeployment)(options.deployment);
|
|
5245
|
+
this.context = Object.freeze({
|
|
5246
|
+
chainId: this.deployment.chainId,
|
|
5247
|
+
protocolAddress: this.deployment.protocol.address
|
|
5248
|
+
});
|
|
5249
|
+
Object.freeze(this);
|
|
5250
|
+
}
|
|
5251
|
+
/** Load the selected deployment and verify its contract against Chain RPC before returning. */
|
|
5252
|
+
static async fromRpc(rpc, provider, options = {}) {
|
|
5253
|
+
const chainId = (await provider.getNetwork()).chainId;
|
|
5254
|
+
if (typeof chainId !== "bigint" || chainId <= 0n || chainId >= 1n << 64n)
|
|
5255
|
+
throw new Error("invalid protocol chainId");
|
|
5256
|
+
const deployment = await rpc.getDeployment(
|
|
5257
|
+
chainId,
|
|
5258
|
+
options.signal ? { signal: options.signal } : {}
|
|
5259
|
+
);
|
|
5260
|
+
const protocol = new _Protocol({ deployment });
|
|
5261
|
+
if (protocol.context.chainId !== chainId) throw new Error("RPC deployment chain mismatch");
|
|
5262
|
+
await protocol.validateDeployment(provider);
|
|
5263
|
+
return protocol;
|
|
5264
|
+
}
|
|
5265
|
+
async validateDeployment(connection) {
|
|
5266
|
+
const reader = "getNetwork" in connection ? {
|
|
5267
|
+
getChainId: async () => (await connection.getNetwork()).chainId,
|
|
5268
|
+
getCode: async (address) => await connection.getCode(address),
|
|
5269
|
+
getProtocolAddressRegistry: async (address) => (0, import_ethers9.getAddress)(
|
|
5270
|
+
await new import_ethers9.Contract(
|
|
5271
|
+
address,
|
|
5272
|
+
["function addressRegistry() view returns (address)"],
|
|
5273
|
+
connection
|
|
5274
|
+
).getFunction("addressRegistry")()
|
|
5275
|
+
),
|
|
5276
|
+
getProtocolVersion: async (address) => BigInt(
|
|
5277
|
+
await new import_ethers9.Contract(
|
|
5278
|
+
address,
|
|
5279
|
+
["function VERSION() view returns (uint256)"],
|
|
5280
|
+
connection
|
|
5281
|
+
).getFunction("VERSION")()
|
|
5282
|
+
)
|
|
5283
|
+
} : connection;
|
|
5284
|
+
if (await reader.getChainId() !== this.context.chainId)
|
|
5285
|
+
throw new Error("deployment chain mismatch");
|
|
5286
|
+
const code = await reader.getCode(this.context.protocolAddress);
|
|
5287
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || (0, import_ethers9.keccak256)(code) !== this.deployment.protocol.runtimeCodeHash)
|
|
5288
|
+
throw new Error("protocol runtime code profile mismatch");
|
|
5289
|
+
if (reader.getProtocolVersion && await reader.getProtocolVersion(this.context.protocolAddress) !== 1n)
|
|
5290
|
+
throw new Error("unsupported onchain protocol version");
|
|
5291
|
+
const registry = this.deployment.registry;
|
|
5292
|
+
if (registry) {
|
|
5293
|
+
if (!reader.getProtocolAddressRegistry)
|
|
5294
|
+
throw new Error("registry binding reader capability is missing");
|
|
5295
|
+
if ((0, import_ethers9.getAddress)(
|
|
5296
|
+
await reader.getProtocolAddressRegistry(this.context.protocolAddress)
|
|
5297
|
+
) !== (0, import_ethers9.getAddress)(registry.address))
|
|
5298
|
+
throw new Error("protocol registry binding mismatch");
|
|
5299
|
+
const registryCode = await reader.getCode(registry.address);
|
|
5300
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(registryCode) || (0, import_ethers9.keccak256)(registryCode) !== registry.runtimeCodeHash)
|
|
5301
|
+
throw new Error("registry runtime code profile mismatch");
|
|
5302
|
+
}
|
|
5303
|
+
}
|
|
5304
|
+
aggregate(request) {
|
|
5305
|
+
return {
|
|
5306
|
+
to: this.context.protocolAddress,
|
|
5307
|
+
value: 0n,
|
|
5308
|
+
...buildTransactAggregateCalldata({ ...request, context: this.context })
|
|
5309
|
+
};
|
|
5310
|
+
}
|
|
5311
|
+
/** Build an operation context for one asset within this same deployment. */
|
|
5312
|
+
forToken(tokenAddress) {
|
|
5313
|
+
return new TokenProtocol(
|
|
5314
|
+
{ ...this.context, tokenAddress: (0, import_ethers9.getAddress)(tokenAddress) },
|
|
5315
|
+
{ expectedRuntimeCodeHash: this.deployment.protocol.runtimeCodeHash }
|
|
5316
|
+
);
|
|
5317
|
+
}
|
|
5318
|
+
};
|
|
5319
|
+
|
|
5320
|
+
// src/verify.ts
|
|
5321
|
+
var import_core8 = require("@invisi-labs/core");
|
|
5322
|
+
async function verifyNoteCommitment(params) {
|
|
5323
|
+
const expected = await (0, import_core8.computeNoteCommitment)(
|
|
5324
|
+
params.chainId,
|
|
5325
|
+
await (0, import_core8.computeNoteIdentity)(BigInt(params.walletIdentity), BigInt(params.nonce)),
|
|
5326
|
+
BigInt(params.tokenAddress),
|
|
5327
|
+
params.amount
|
|
5328
|
+
);
|
|
5329
|
+
return BigInt(expected) === BigInt(params.noteCommitment);
|
|
5330
|
+
}
|
|
5331
|
+
async function verifyCreditCommitment(params) {
|
|
5332
|
+
if (params.creditSharedKey <= 0n || params.creditSharedKey >= import_core8.FIELD_MODULUS)
|
|
5333
|
+
throw new RangeError("creditSharedKey must be a nonzero canonical Field");
|
|
5334
|
+
const expected = await (0, import_core8.computeCreditCommitment)(
|
|
5335
|
+
params.chainId,
|
|
5336
|
+
params.spenderWalletIdentity,
|
|
5337
|
+
params.ownerWalletIdentity,
|
|
5338
|
+
BigInt(params.spenderPayout),
|
|
5339
|
+
BigInt(params.ownerPayout),
|
|
5340
|
+
BigInt(params.tokenAddress),
|
|
5341
|
+
params.amount,
|
|
5342
|
+
params.nonce,
|
|
5343
|
+
params.expiry,
|
|
5344
|
+
await (0, import_core8.computeCreditSharedKeyHash)(params.creditSharedKey)
|
|
5345
|
+
);
|
|
5346
|
+
return BigInt(expected) === BigInt(params.creditCommitment);
|
|
5347
|
+
}
|
|
5348
|
+
|
|
5349
|
+
// src/withdrawal.ts
|
|
5350
|
+
var import_core9 = require("@invisi-labs/core");
|
|
5351
|
+
async function buildWithdrawalCalldata(p) {
|
|
5352
|
+
const r = normalizeTransactRequest(p.context, p.params, [], p.funding);
|
|
5353
|
+
if (r.outputCount !== 0 || r.depositAmount !== 0n || p.sourceNotes.length === 0 || p.sourceNotes.length !== r.inputCount) {
|
|
5354
|
+
throw new Error("full withdrawal requires inputs, no private outputs and no funding");
|
|
5355
|
+
}
|
|
5356
|
+
const walletIdentity = BigInt(p.sourceNotes[0].walletIdentity);
|
|
5357
|
+
let total = 0n;
|
|
5358
|
+
for (const [index, note] of p.sourceNotes.entries()) {
|
|
5359
|
+
if (note.chainId !== p.context.chainId || note.protocolAddress !== BigInt(p.context.protocolAddress))
|
|
5360
|
+
throw new Error("source note context mismatch");
|
|
5361
|
+
if (BigInt(note.walletIdentity) !== walletIdentity || note.tokenAddress !== BigInt(p.context.tokenAddress) || note.amount <= 0n)
|
|
5362
|
+
throw new Error("source note wallet/token/amount mismatch");
|
|
5363
|
+
const commitment = await (0, import_core9.computeNoteCommitment)(
|
|
5364
|
+
note.chainId,
|
|
5365
|
+
await (0, import_core9.computeNoteIdentity)(walletIdentity, note.nonce),
|
|
5366
|
+
note.tokenAddress,
|
|
5367
|
+
note.amount
|
|
5368
|
+
);
|
|
5369
|
+
const nullifier = await (0, import_core9.computeNoteNullifier)(note.chainId, note.nonce, commitment);
|
|
5370
|
+
if (nullifier.toLowerCase() !== r.nullifiers[index].toLowerCase())
|
|
5371
|
+
throw new Error("source note nullifier mismatch");
|
|
5372
|
+
total += note.amount;
|
|
5373
|
+
}
|
|
5374
|
+
if (r.withdrawalAmount !== total)
|
|
5375
|
+
throw new Error("withdrawal must equal the full input balance");
|
|
5376
|
+
return buildTransactCalldata({ ...p, deliveries: [] });
|
|
5377
|
+
}
|
|
5378
|
+
|
|
5379
|
+
// src/witness.ts
|
|
5380
|
+
var import_core10 = require("@invisi-labs/core");
|
|
5381
|
+
var import_prover = require("@invisi-labs/prover");
|
|
5382
|
+
|
|
4730
5383
|
// src/witness-layouts.json
|
|
4731
5384
|
var witness_layouts_default = {
|
|
4732
5385
|
transact_user_slots14: {
|
|
@@ -5718,301 +6371,85 @@ var witness_layouts_default = {
|
|
|
5718
6371
|
publicInputCount: 732,
|
|
5719
6372
|
public: [
|
|
5720
6373
|
{
|
|
5721
|
-
name: "chain_id",
|
|
5722
|
-
count: 1,
|
|
5723
|
-
array: false
|
|
5724
|
-
},
|
|
5725
|
-
{
|
|
5726
|
-
name: "protocol_address",
|
|
5727
|
-
count: 1,
|
|
5728
|
-
array: false
|
|
5729
|
-
},
|
|
5730
|
-
{
|
|
5731
|
-
name: "token_address",
|
|
5732
|
-
count: 1,
|
|
5733
|
-
array: false
|
|
5734
|
-
},
|
|
5735
|
-
{
|
|
5736
|
-
name: "spender_address",
|
|
5737
|
-
count: 1,
|
|
5738
|
-
array: false
|
|
5739
|
-
},
|
|
5740
|
-
{
|
|
5741
|
-
name: "actual_count",
|
|
5742
|
-
count: 1,
|
|
5743
|
-
array: false
|
|
5744
|
-
},
|
|
5745
|
-
{
|
|
5746
|
-
name: "source_count",
|
|
5747
|
-
count: 1,
|
|
5748
|
-
array: false
|
|
5749
|
-
},
|
|
5750
|
-
{
|
|
5751
|
-
name: "tree_ids",
|
|
5752
|
-
count: 120,
|
|
5753
|
-
array: true
|
|
5754
|
-
},
|
|
5755
|
-
{
|
|
5756
|
-
name: "roots",
|
|
5757
|
-
count: 120,
|
|
5758
|
-
array: true
|
|
5759
|
-
},
|
|
5760
|
-
{
|
|
5761
|
-
name: "nullifiers",
|
|
5762
|
-
count: 120,
|
|
5763
|
-
array: true
|
|
5764
|
-
},
|
|
5765
|
-
{
|
|
5766
|
-
name: "remainder_commitments",
|
|
5767
|
-
count: 120,
|
|
5768
|
-
array: true
|
|
5769
|
-
},
|
|
5770
|
-
{
|
|
5771
|
-
name: "expiries",
|
|
5772
|
-
count: 120,
|
|
5773
|
-
array: true
|
|
5774
|
-
},
|
|
5775
|
-
{
|
|
5776
|
-
name: "total_amount",
|
|
5777
|
-
count: 1,
|
|
5778
|
-
array: false
|
|
5779
|
-
},
|
|
5780
|
-
{
|
|
5781
|
-
name: "deadline",
|
|
5782
|
-
count: 1,
|
|
5783
|
-
array: false
|
|
5784
|
-
},
|
|
5785
|
-
{
|
|
5786
|
-
name: "delivery_hash_high",
|
|
5787
|
-
count: 1,
|
|
5788
|
-
array: false
|
|
5789
|
-
},
|
|
5790
|
-
{
|
|
5791
|
-
name: "delivery_hash_low",
|
|
5792
|
-
count: 1,
|
|
5793
|
-
array: false
|
|
5794
|
-
},
|
|
5795
|
-
{
|
|
5796
|
-
name: "recovery_amounts",
|
|
5797
|
-
count: 120,
|
|
5798
|
-
array: true
|
|
5799
|
-
},
|
|
5800
|
-
{
|
|
5801
|
-
name: "auth_digest_high",
|
|
5802
|
-
count: 1,
|
|
5803
|
-
array: false
|
|
5804
|
-
},
|
|
5805
|
-
{
|
|
5806
|
-
name: "auth_digest_low",
|
|
5807
|
-
count: 1,
|
|
5808
|
-
array: false
|
|
5809
|
-
}
|
|
5810
|
-
],
|
|
5811
|
-
private: [
|
|
5812
|
-
"public_key_x",
|
|
5813
|
-
"public_key_y",
|
|
5814
|
-
"signature",
|
|
5815
|
-
"spender_wallet_identity",
|
|
5816
|
-
"owner_payouts",
|
|
5817
|
-
"owner_wallet_identities",
|
|
5818
|
-
"input_amounts",
|
|
5819
|
-
"input_nonces",
|
|
5820
|
-
"credit_shared_keys",
|
|
5821
|
-
"leaf_indices",
|
|
5822
|
-
"merkle_paths",
|
|
5823
|
-
"input_source_indices",
|
|
5824
|
-
"draw_amounts"
|
|
5825
|
-
]
|
|
5826
|
-
},
|
|
5827
|
-
credit_cancel: {
|
|
5828
|
-
artifactSha256: "ff278a04f22d2886c9f27f7785a0b8fc317dd242fd4aa9d0d9398d18b7513daf",
|
|
5829
|
-
keys: {
|
|
5830
|
-
evm: "1f8a3c20cb081d6a90962556da3124919cc4e5675e59ad31562af39299da02fb"
|
|
5831
|
-
},
|
|
5832
|
-
publicInputCount: 11,
|
|
5833
|
-
public: [
|
|
5834
|
-
{
|
|
5835
|
-
name: "chain_id",
|
|
5836
|
-
count: 1,
|
|
5837
|
-
array: false
|
|
5838
|
-
},
|
|
5839
|
-
{
|
|
5840
|
-
name: "protocol_address",
|
|
5841
|
-
count: 1,
|
|
5842
|
-
array: false
|
|
5843
|
-
},
|
|
5844
|
-
{
|
|
5845
|
-
name: "token_address",
|
|
5846
|
-
count: 1,
|
|
5847
|
-
array: false
|
|
5848
|
-
},
|
|
5849
|
-
{
|
|
5850
|
-
name: "owner_address",
|
|
5851
|
-
count: 1,
|
|
5852
|
-
array: false
|
|
5853
|
-
},
|
|
5854
|
-
{
|
|
5855
|
-
name: "tree_id",
|
|
5856
|
-
count: 1,
|
|
5857
|
-
array: false
|
|
5858
|
-
},
|
|
5859
|
-
{
|
|
5860
|
-
name: "merkle_root",
|
|
5861
|
-
count: 1,
|
|
5862
|
-
array: false
|
|
5863
|
-
},
|
|
5864
|
-
{
|
|
5865
|
-
name: "nullifier",
|
|
5866
|
-
count: 1,
|
|
5867
|
-
array: false
|
|
5868
|
-
},
|
|
5869
|
-
{
|
|
5870
|
-
name: "amount",
|
|
5871
|
-
count: 1,
|
|
5872
|
-
array: false
|
|
5873
|
-
},
|
|
5874
|
-
{
|
|
5875
|
-
name: "deadline",
|
|
5876
|
-
count: 1,
|
|
5877
|
-
array: false
|
|
5878
|
-
},
|
|
5879
|
-
{
|
|
5880
|
-
name: "auth_digest_high",
|
|
5881
|
-
count: 1,
|
|
5882
|
-
array: false
|
|
5883
|
-
},
|
|
5884
|
-
{
|
|
5885
|
-
name: "auth_digest_low",
|
|
5886
|
-
count: 1,
|
|
5887
|
-
array: false
|
|
5888
|
-
}
|
|
5889
|
-
],
|
|
5890
|
-
private: [
|
|
5891
|
-
"public_key_x",
|
|
5892
|
-
"public_key_y",
|
|
5893
|
-
"signature",
|
|
5894
|
-
"spender_payout",
|
|
5895
|
-
"spender_wallet_identity",
|
|
5896
|
-
"owner_wallet_identity",
|
|
5897
|
-
"input_nonce",
|
|
5898
|
-
"expiry",
|
|
5899
|
-
"credit_shared_key",
|
|
5900
|
-
"leaf_index",
|
|
5901
|
-
"merkle_path"
|
|
5902
|
-
]
|
|
5903
|
-
},
|
|
5904
|
-
credit_top_up: {
|
|
5905
|
-
artifactSha256: "fbe662363d9814983f7940f74369117cd6c84783945fbf527b0ed48d011b58a4",
|
|
5906
|
-
keys: {
|
|
5907
|
-
evm: "44436f31414497a708355426da051ee48ba63fdebcb6cfd72347c37c34c98c50"
|
|
5908
|
-
},
|
|
5909
|
-
publicInputCount: 50,
|
|
5910
|
-
public: [
|
|
5911
|
-
{
|
|
5912
|
-
name: "chain_id",
|
|
5913
|
-
count: 1,
|
|
5914
|
-
array: false
|
|
5915
|
-
},
|
|
5916
|
-
{
|
|
5917
|
-
name: "protocol_address",
|
|
5918
|
-
count: 1,
|
|
5919
|
-
array: false
|
|
5920
|
-
},
|
|
5921
|
-
{
|
|
5922
|
-
name: "token_address",
|
|
5923
|
-
count: 1,
|
|
5924
|
-
array: false
|
|
5925
|
-
},
|
|
5926
|
-
{
|
|
5927
|
-
name: "owner_address",
|
|
5928
|
-
count: 1,
|
|
5929
|
-
array: false
|
|
5930
|
-
},
|
|
5931
|
-
{
|
|
5932
|
-
name: "actual_count",
|
|
5933
|
-
count: 1,
|
|
5934
|
-
array: false
|
|
5935
|
-
},
|
|
5936
|
-
{
|
|
5937
|
-
name: "source_count",
|
|
5938
|
-
count: 1,
|
|
5939
|
-
array: false
|
|
5940
|
-
},
|
|
5941
|
-
{
|
|
5942
|
-
name: "input_tree_ids",
|
|
5943
|
-
count: 10,
|
|
5944
|
-
array: true
|
|
5945
|
-
},
|
|
5946
|
-
{
|
|
5947
|
-
name: "merkle_roots",
|
|
5948
|
-
count: 10,
|
|
5949
|
-
array: true
|
|
5950
|
-
},
|
|
5951
|
-
{
|
|
5952
|
-
name: "nullifiers",
|
|
5953
|
-
count: 10,
|
|
5954
|
-
array: true
|
|
5955
|
-
},
|
|
5956
|
-
{
|
|
5957
|
-
name: "credit_commitment",
|
|
6374
|
+
name: "chain_id",
|
|
5958
6375
|
count: 1,
|
|
5959
6376
|
array: false
|
|
5960
6377
|
},
|
|
5961
6378
|
{
|
|
5962
|
-
name: "
|
|
6379
|
+
name: "protocol_address",
|
|
5963
6380
|
count: 1,
|
|
5964
6381
|
array: false
|
|
5965
6382
|
},
|
|
5966
6383
|
{
|
|
5967
|
-
name: "
|
|
6384
|
+
name: "token_address",
|
|
5968
6385
|
count: 1,
|
|
5969
6386
|
array: false
|
|
5970
6387
|
},
|
|
5971
6388
|
{
|
|
5972
|
-
name: "
|
|
6389
|
+
name: "spender_address",
|
|
5973
6390
|
count: 1,
|
|
5974
6391
|
array: false
|
|
5975
6392
|
},
|
|
5976
6393
|
{
|
|
5977
|
-
name: "
|
|
6394
|
+
name: "actual_count",
|
|
5978
6395
|
count: 1,
|
|
5979
6396
|
array: false
|
|
5980
6397
|
},
|
|
5981
6398
|
{
|
|
5982
|
-
name: "
|
|
6399
|
+
name: "source_count",
|
|
5983
6400
|
count: 1,
|
|
5984
6401
|
array: false
|
|
5985
6402
|
},
|
|
5986
6403
|
{
|
|
5987
|
-
name: "
|
|
5988
|
-
count:
|
|
5989
|
-
array:
|
|
6404
|
+
name: "tree_ids",
|
|
6405
|
+
count: 120,
|
|
6406
|
+
array: true
|
|
5990
6407
|
},
|
|
5991
6408
|
{
|
|
5992
|
-
name: "
|
|
5993
|
-
count:
|
|
5994
|
-
array:
|
|
6409
|
+
name: "roots",
|
|
6410
|
+
count: 120,
|
|
6411
|
+
array: true
|
|
5995
6412
|
},
|
|
5996
6413
|
{
|
|
5997
|
-
name: "
|
|
6414
|
+
name: "nullifiers",
|
|
6415
|
+
count: 120,
|
|
6416
|
+
array: true
|
|
6417
|
+
},
|
|
6418
|
+
{
|
|
6419
|
+
name: "remainder_commitments",
|
|
6420
|
+
count: 120,
|
|
6421
|
+
array: true
|
|
6422
|
+
},
|
|
6423
|
+
{
|
|
6424
|
+
name: "expiries",
|
|
6425
|
+
count: 120,
|
|
6426
|
+
array: true
|
|
6427
|
+
},
|
|
6428
|
+
{
|
|
6429
|
+
name: "total_amount",
|
|
5998
6430
|
count: 1,
|
|
5999
6431
|
array: false
|
|
6000
6432
|
},
|
|
6001
6433
|
{
|
|
6002
|
-
name: "
|
|
6434
|
+
name: "deadline",
|
|
6003
6435
|
count: 1,
|
|
6004
6436
|
array: false
|
|
6005
6437
|
},
|
|
6006
6438
|
{
|
|
6007
|
-
name: "
|
|
6439
|
+
name: "delivery_hash_high",
|
|
6008
6440
|
count: 1,
|
|
6009
6441
|
array: false
|
|
6010
6442
|
},
|
|
6011
6443
|
{
|
|
6012
|
-
name: "
|
|
6444
|
+
name: "delivery_hash_low",
|
|
6013
6445
|
count: 1,
|
|
6014
6446
|
array: false
|
|
6015
6447
|
},
|
|
6448
|
+
{
|
|
6449
|
+
name: "recovery_amounts",
|
|
6450
|
+
count: 120,
|
|
6451
|
+
array: true
|
|
6452
|
+
},
|
|
6016
6453
|
{
|
|
6017
6454
|
name: "auth_digest_high",
|
|
6018
6455
|
count: 1,
|
|
@@ -6025,1089 +6462,666 @@ var witness_layouts_default = {
|
|
|
6025
6462
|
}
|
|
6026
6463
|
],
|
|
6027
6464
|
private: [
|
|
6465
|
+
"public_key_x",
|
|
6466
|
+
"public_key_y",
|
|
6467
|
+
"signature",
|
|
6468
|
+
"spender_wallet_identity",
|
|
6469
|
+
"owner_payouts",
|
|
6470
|
+
"owner_wallet_identities",
|
|
6028
6471
|
"input_amounts",
|
|
6029
6472
|
"input_nonces",
|
|
6473
|
+
"credit_shared_keys",
|
|
6030
6474
|
"leaf_indices",
|
|
6031
6475
|
"merkle_paths",
|
|
6032
6476
|
"input_source_indices",
|
|
6033
|
-
"
|
|
6034
|
-
"public_key_y",
|
|
6035
|
-
"signature",
|
|
6036
|
-
"spender_payout",
|
|
6037
|
-
"spender_wallet_identity",
|
|
6038
|
-
"owner_wallet_identity",
|
|
6039
|
-
"credit_amount",
|
|
6040
|
-
"credit_nonce",
|
|
6041
|
-
"credit_shared_key",
|
|
6042
|
-
"change_amount",
|
|
6043
|
-
"change_nonce",
|
|
6044
|
-
"previous_credit_amount",
|
|
6045
|
-
"previous_credit_nonce",
|
|
6046
|
-
"previous_credit_leaf_index",
|
|
6047
|
-
"previous_credit_merkle_path"
|
|
6477
|
+
"draw_amounts"
|
|
6048
6478
|
]
|
|
6049
6479
|
},
|
|
6050
|
-
|
|
6051
|
-
artifactSha256: "
|
|
6480
|
+
credit_cancel: {
|
|
6481
|
+
artifactSha256: "ff278a04f22d2886c9f27f7785a0b8fc317dd242fd4aa9d0d9398d18b7513daf",
|
|
6052
6482
|
keys: {
|
|
6053
|
-
evm: "
|
|
6483
|
+
evm: "1f8a3c20cb081d6a90962556da3124919cc4e5675e59ad31562af39299da02fb"
|
|
6054
6484
|
},
|
|
6055
|
-
publicInputCount:
|
|
6485
|
+
publicInputCount: 11,
|
|
6056
6486
|
public: [
|
|
6057
6487
|
{
|
|
6058
|
-
name: "
|
|
6059
|
-
count: 1,
|
|
6060
|
-
array: false
|
|
6061
|
-
},
|
|
6062
|
-
{
|
|
6063
|
-
name: "auth_digest_high",
|
|
6064
|
-
count: 1,
|
|
6065
|
-
array: false
|
|
6066
|
-
},
|
|
6067
|
-
{
|
|
6068
|
-
name: "auth_digest_low",
|
|
6069
|
-
count: 1,
|
|
6070
|
-
array: false
|
|
6071
|
-
}
|
|
6072
|
-
],
|
|
6073
|
-
private: [
|
|
6074
|
-
"public_key_x",
|
|
6075
|
-
"public_key_y",
|
|
6076
|
-
"signature"
|
|
6077
|
-
]
|
|
6078
|
-
}
|
|
6079
|
-
};
|
|
6080
|
-
|
|
6081
|
-
// src/witness.ts
|
|
6082
|
-
var pad2 = (values, count, zero) => {
|
|
6083
|
-
if (values.length > count) throw new Error("witness capacity exceeded");
|
|
6084
|
-
return [...values, ...Array.from({ length: count - values.length }, zero)];
|
|
6085
|
-
};
|
|
6086
|
-
var zeros = () => Array(16).fill(0n);
|
|
6087
|
-
var zeroAuthority = () => ({
|
|
6088
|
-
public_key_x: Array(32).fill(0),
|
|
6089
|
-
public_key_y: Array(32).fill(0),
|
|
6090
|
-
signature: Array(64).fill(0)
|
|
6091
|
-
});
|
|
6092
|
-
function check(ok, message) {
|
|
6093
|
-
if (!ok) throw new Error(message);
|
|
6094
|
-
}
|
|
6095
|
-
function provingRequest(circuitName, privateInputs, expectedPublicInputs, target = "evm") {
|
|
6096
|
-
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
6097
|
-
check(typeof key === "string", "unpublished proof target");
|
|
6098
|
-
check(
|
|
6099
|
-
expectedPublicInputs.length === schema.publicInputCount,
|
|
6100
|
-
"public input order/width mismatch"
|
|
6101
|
-
);
|
|
6102
|
-
check(
|
|
6103
|
-
Object.keys(privateInputs).length === schema.private.length && schema.private.every((name) => Object.hasOwn(privateInputs, name)),
|
|
6104
|
-
"private witness schema mismatch"
|
|
6105
|
-
);
|
|
6106
|
-
let offset = 0;
|
|
6107
|
-
const publicInputs = {};
|
|
6108
|
-
for (const entry of schema.public) {
|
|
6109
|
-
const values = expectedPublicInputs.slice(offset, offset + entry.count).map((value) => {
|
|
6110
|
-
const n = BigInt(value);
|
|
6111
|
-
check(n >= 0n && n < FIELD_MODULUS, "noncanonical public input");
|
|
6112
|
-
return n;
|
|
6113
|
-
});
|
|
6114
|
-
publicInputs[entry.name] = entry.array ? values : values[0];
|
|
6115
|
-
offset += entry.count;
|
|
6116
|
-
}
|
|
6117
|
-
check(offset === expectedPublicInputs.length, "public input layout mismatch");
|
|
6118
|
-
return {
|
|
6119
|
-
circuitName,
|
|
6120
|
-
target,
|
|
6121
|
-
artifactSha256: schema.artifactSha256,
|
|
6122
|
-
vkSha256: key,
|
|
6123
|
-
expectedPublicInputs: [...expectedPublicInputs],
|
|
6124
|
-
witness: new import_prover.LocalWitness({ ...privateInputs, ...publicInputs })
|
|
6125
|
-
};
|
|
6126
|
-
}
|
|
6127
|
-
var WitnessBuilder = class {
|
|
6128
|
-
#protocol;
|
|
6129
|
-
constructor(protocol) {
|
|
6130
|
-
this.#protocol = protocol;
|
|
6131
|
-
}
|
|
6132
|
-
static statement(circuitName, expectedPublicInputs, target = "evm") {
|
|
6133
|
-
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
6134
|
-
check(
|
|
6135
|
-
typeof key === "string" && expectedPublicInputs.length === schema.publicInputCount,
|
|
6136
|
-
"unpublished target or statement width mismatch"
|
|
6137
|
-
);
|
|
6138
|
-
return {
|
|
6139
|
-
circuitName,
|
|
6140
|
-
target,
|
|
6141
|
-
artifactSha256: schema.artifactSha256,
|
|
6142
|
-
vkSha256: key,
|
|
6143
|
-
expectedPublicInputs: [...expectedPublicInputs]
|
|
6144
|
-
};
|
|
6145
|
-
}
|
|
6146
|
-
context(note) {
|
|
6147
|
-
const c = this.#protocol.context;
|
|
6148
|
-
check(
|
|
6149
|
-
note.chainId === c.chainId && note.protocolAddress === BigInt(c.protocolAddress) && note.tokenAddress === BigInt(c.tokenAddress),
|
|
6150
|
-
"note context mismatch"
|
|
6151
|
-
);
|
|
6152
|
-
}
|
|
6153
|
-
async authority(operation, capacity, words, signed, identity) {
|
|
6154
|
-
check(!!signed, "private wallet authorization required");
|
|
6155
|
-
const c = this.#protocol.context, request = {
|
|
6156
|
-
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
6157
|
-
operation,
|
|
6158
|
-
capacity,
|
|
6159
|
-
words: words.slice(0, -2).map(BigInt)
|
|
6160
|
-
};
|
|
6161
|
-
check(
|
|
6162
|
-
signed.walletIdentity === identity && signed.digest === (0, import_core5.computeWalletAuthorizationDigest)(request),
|
|
6163
|
-
"authorization statement mismatch"
|
|
6164
|
-
);
|
|
6165
|
-
const witness = signed.withWitness((value) => value);
|
|
6166
|
-
check(
|
|
6167
|
-
await (0, import_core5.verifyWalletAuthorization)(
|
|
6168
|
-
identity,
|
|
6169
|
-
Uint8Array.from([4, ...witness.public_key_x, ...witness.public_key_y]),
|
|
6170
|
-
Uint8Array.from(witness.signature),
|
|
6171
|
-
request
|
|
6172
|
-
),
|
|
6173
|
-
"invalid wallet authorization"
|
|
6174
|
-
);
|
|
6175
|
-
return witness;
|
|
6176
|
-
}
|
|
6177
|
-
async membership(leaf, input, sources) {
|
|
6178
|
-
const source = sources.findIndex((value) => value.treeId === input.treeId);
|
|
6179
|
-
check(
|
|
6180
|
-
source >= 0 && Number.isInteger(input.leafIndex) && input.leafIndex >= 0 && input.leafIndex < 65536 && input.path.length === 16,
|
|
6181
|
-
"invalid membership position"
|
|
6182
|
-
);
|
|
6183
|
-
let root = BigInt(leaf);
|
|
6184
|
-
for (let level = 0; level < 16; level++)
|
|
6185
|
-
root = BigInt(
|
|
6186
|
-
await (0, import_core5.poseidonHash)(
|
|
6187
|
-
input.leafIndex >> level & 1 ? [input.path[level], root] : [root, input.path[level]]
|
|
6188
|
-
)
|
|
6189
|
-
);
|
|
6190
|
-
check(root === BigInt(sources[source].merkleRoot), "membership root mismatch");
|
|
6191
|
-
return source;
|
|
6192
|
-
}
|
|
6193
|
-
async noteLeaf(note) {
|
|
6194
|
-
this.context(note);
|
|
6195
|
-
return (0, import_core5.computeNoteCommitment)(
|
|
6196
|
-
note.chainId,
|
|
6197
|
-
await (0, import_core5.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
|
|
6198
|
-
note.tokenAddress,
|
|
6199
|
-
note.amount
|
|
6200
|
-
);
|
|
6201
|
-
}
|
|
6202
|
-
async creditLeaf(note) {
|
|
6203
|
-
this.context(note);
|
|
6204
|
-
return (0, import_core5.computeCreditCommitment)(
|
|
6205
|
-
note.chainId,
|
|
6206
|
-
note.spenderWalletIdentity,
|
|
6207
|
-
note.ownerWalletIdentity,
|
|
6208
|
-
note.spenderPayout,
|
|
6209
|
-
note.ownerPayout,
|
|
6210
|
-
note.tokenAddress,
|
|
6211
|
-
note.amount,
|
|
6212
|
-
note.nonce,
|
|
6213
|
-
note.expiry,
|
|
6214
|
-
await (0, import_core5.computeCreditSharedKeyHash)(note.creditSharedKey)
|
|
6215
|
-
);
|
|
6216
|
-
}
|
|
6217
|
-
async noteInputs(inputs, sources, nullifiers, identity, authority) {
|
|
6218
|
-
check(inputs.length === nullifiers.length, "input count mismatch");
|
|
6219
|
-
return Promise.all(
|
|
6220
|
-
inputs.map(async (input, i) => {
|
|
6221
|
-
check(input.note.walletIdentity === identity, "input wallet mismatch");
|
|
6222
|
-
const leaf = await this.noteLeaf(input.note);
|
|
6223
|
-
check(
|
|
6224
|
-
await (0, import_core5.computeNoteNullifier)(input.note.chainId, input.note.nonce, leaf) === nullifiers[i],
|
|
6225
|
-
"input nullifier mismatch"
|
|
6226
|
-
);
|
|
6227
|
-
return BigInt(await this.membership(leaf, input, sources));
|
|
6228
|
-
})
|
|
6229
|
-
);
|
|
6230
|
-
}
|
|
6231
|
-
async transact(p) {
|
|
6232
|
-
const c = this.#protocol.context, n = normalizeTransactRequest(c, p.params, p.deliveries, p.funding), words = transactUserPublicInputs(c, p.params, p.deliveries, p.funding);
|
|
6233
|
-
check(
|
|
6234
|
-
p.inputs.length === n.inputCount && p.outputs.length === n.outputCount,
|
|
6235
|
-
"note count mismatch"
|
|
6236
|
-
);
|
|
6237
|
-
const identity = p.inputs[0]?.note.walletIdentity;
|
|
6238
|
-
const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
|
|
6239
|
-
const authority = identity && !unsignedSweep ? await this.authority("transact", n.capacity, words, p.authorization, identity) : zeroAuthority();
|
|
6240
|
-
const sources = await this.noteInputs(
|
|
6241
|
-
p.inputs,
|
|
6242
|
-
p.params.sources,
|
|
6243
|
-
p.params.nullifiers,
|
|
6244
|
-
identity ?? "0x" + "00".repeat(32),
|
|
6245
|
-
authority
|
|
6246
|
-
);
|
|
6247
|
-
for (const [i, note] of p.outputs.entries())
|
|
6248
|
-
check(
|
|
6249
|
-
await this.noteLeaf(note) === p.params.outputCommitments[i],
|
|
6250
|
-
"output commitment mismatch"
|
|
6251
|
-
);
|
|
6252
|
-
const all = [...p.inputs.map((input) => input.note), ...p.outputs];
|
|
6253
|
-
return provingRequest(
|
|
6254
|
-
`transact_user_slots${n.capacity}`,
|
|
6488
|
+
name: "chain_id",
|
|
6489
|
+
count: 1,
|
|
6490
|
+
array: false
|
|
6491
|
+
},
|
|
6255
6492
|
{
|
|
6256
|
-
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
[
|
|
6260
|
-
...p.inputs.map(() => 0n),
|
|
6261
|
-
...p.outputs.map((note) => BigInt(note.walletIdentity))
|
|
6262
|
-
],
|
|
6263
|
-
n.capacity,
|
|
6264
|
-
() => 0n
|
|
6265
|
-
),
|
|
6266
|
-
amounts: pad2(
|
|
6267
|
-
all.map((note) => note.amount),
|
|
6268
|
-
n.capacity,
|
|
6269
|
-
() => 0n
|
|
6270
|
-
),
|
|
6271
|
-
nonces: pad2(
|
|
6272
|
-
all.map((note) => note.nonce),
|
|
6273
|
-
n.capacity,
|
|
6274
|
-
() => 0n
|
|
6275
|
-
),
|
|
6276
|
-
leaf_indices: pad2(
|
|
6277
|
-
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6278
|
-
n.capacity,
|
|
6279
|
-
() => 0n
|
|
6280
|
-
),
|
|
6281
|
-
merkle_paths: pad2(
|
|
6282
|
-
p.inputs.map((input) => [...input.path]),
|
|
6283
|
-
n.capacity,
|
|
6284
|
-
zeros
|
|
6285
|
-
),
|
|
6286
|
-
input_source_indices: pad2(sources, n.capacity, () => 0n)
|
|
6493
|
+
name: "protocol_address",
|
|
6494
|
+
count: 1,
|
|
6495
|
+
array: false
|
|
6287
6496
|
},
|
|
6288
|
-
words,
|
|
6289
|
-
p.target
|
|
6290
|
-
);
|
|
6291
|
-
}
|
|
6292
|
-
async creation(p, operation, words) {
|
|
6293
|
-
const state = (0, import_core5.normalizeCreditDeliveryState)(p.state), note = state.note;
|
|
6294
|
-
check(
|
|
6295
|
-
await this.creditLeaf(note) === p.params.creditCommitment && note.ownerPayout === BigInt(p.params.owner) && note.expiry === p.params.expiry,
|
|
6296
|
-
"Credit creation mismatch"
|
|
6297
|
-
);
|
|
6298
|
-
const authority = await this.authority(
|
|
6299
|
-
operation,
|
|
6300
|
-
10,
|
|
6301
|
-
words,
|
|
6302
|
-
p.authorization,
|
|
6303
|
-
note.ownerWalletIdentity
|
|
6304
|
-
);
|
|
6305
|
-
const sources = await this.noteInputs(
|
|
6306
|
-
p.inputs,
|
|
6307
|
-
p.params.sources,
|
|
6308
|
-
p.params.nullifiers,
|
|
6309
|
-
note.ownerWalletIdentity,
|
|
6310
|
-
authority
|
|
6311
|
-
);
|
|
6312
|
-
if (p.change)
|
|
6313
|
-
check(
|
|
6314
|
-
p.change.walletIdentity === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
|
|
6315
|
-
"change commitment mismatch"
|
|
6316
|
-
);
|
|
6317
|
-
else check(BigInt(p.params.changeCommitment) === 0n, "missing change note");
|
|
6318
|
-
return {
|
|
6319
|
-
...authority,
|
|
6320
|
-
input_amounts: pad2(
|
|
6321
|
-
p.inputs.map((input) => input.note.amount),
|
|
6322
|
-
10,
|
|
6323
|
-
() => 0n
|
|
6324
|
-
),
|
|
6325
|
-
input_nonces: pad2(
|
|
6326
|
-
p.inputs.map((input) => input.note.nonce),
|
|
6327
|
-
10,
|
|
6328
|
-
() => 0n
|
|
6329
|
-
),
|
|
6330
|
-
leaf_indices: pad2(
|
|
6331
|
-
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6332
|
-
10,
|
|
6333
|
-
() => 0n
|
|
6334
|
-
),
|
|
6335
|
-
merkle_paths: pad2(
|
|
6336
|
-
p.inputs.map((input) => [...input.path]),
|
|
6337
|
-
10,
|
|
6338
|
-
zeros
|
|
6339
|
-
),
|
|
6340
|
-
input_source_indices: pad2(sources, 10, () => 0n),
|
|
6341
|
-
spender_payout: note.spenderPayout,
|
|
6342
|
-
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
6343
|
-
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
6344
|
-
credit_amount: note.amount,
|
|
6345
|
-
credit_nonce: note.nonce,
|
|
6346
|
-
credit_shared_key: note.creditSharedKey,
|
|
6347
|
-
change_amount: p.change?.amount ?? 0n,
|
|
6348
|
-
change_nonce: p.change?.nonce ?? 0n
|
|
6349
|
-
};
|
|
6350
|
-
}
|
|
6351
|
-
async createCredit(p) {
|
|
6352
|
-
const words = createCreditPublicInputs(
|
|
6353
|
-
this.#protocol.context,
|
|
6354
|
-
p.params,
|
|
6355
|
-
p.deliveries,
|
|
6356
|
-
p.funding
|
|
6357
|
-
);
|
|
6358
|
-
return provingRequest(
|
|
6359
|
-
"create_credit",
|
|
6360
|
-
await this.creation(p, "create-credit", words),
|
|
6361
|
-
words
|
|
6362
|
-
);
|
|
6363
|
-
}
|
|
6364
|
-
async cancelCredit(p) {
|
|
6365
|
-
const note = (0, import_core5.normalizeCreditDeliveryState)(p.input.state).note, leaf = await this.creditLeaf(note), c = this.#protocol.context;
|
|
6366
|
-
check(
|
|
6367
|
-
await (0, import_core5.computeCreditNullifier)(c.chainId, note.creditSharedKey, leaf) === p.params.nullifier && note.amount === p.params.amount && note.ownerPayout === BigInt(p.params.owner),
|
|
6368
|
-
"Credit cancellation mismatch"
|
|
6369
|
-
);
|
|
6370
|
-
await this.membership(leaf, p.input, [p.params.source]);
|
|
6371
|
-
const words = cancelCreditPublicInputs(c, p.params), authority = await this.authority(
|
|
6372
|
-
"cancel-credit",
|
|
6373
|
-
1,
|
|
6374
|
-
words,
|
|
6375
|
-
p.authorization,
|
|
6376
|
-
note.ownerWalletIdentity
|
|
6377
|
-
);
|
|
6378
|
-
return provingRequest(
|
|
6379
|
-
"credit_cancel",
|
|
6380
6497
|
{
|
|
6381
|
-
|
|
6382
|
-
|
|
6383
|
-
|
|
6384
|
-
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
6385
|
-
input_nonce: note.nonce,
|
|
6386
|
-
expiry: note.expiry,
|
|
6387
|
-
credit_shared_key: note.creditSharedKey,
|
|
6388
|
-
leaf_index: BigInt(p.input.leafIndex),
|
|
6389
|
-
merkle_path: [...p.input.path]
|
|
6498
|
+
name: "token_address",
|
|
6499
|
+
count: 1,
|
|
6500
|
+
array: false
|
|
6390
6501
|
},
|
|
6391
|
-
words
|
|
6392
|
-
);
|
|
6393
|
-
}
|
|
6394
|
-
async drawCredit(p) {
|
|
6395
|
-
const c = this.#protocol.context, profile = selectCreditDrawCircuit(p.inputs.length), capacity = profile.maxSize;
|
|
6396
|
-
check(
|
|
6397
|
-
p.inputs.length === p.amounts.length && p.inputs.length === p.params.nullifiers.length,
|
|
6398
|
-
"draw input count mismatch"
|
|
6399
|
-
);
|
|
6400
|
-
const notes2 = p.inputs.map((input) => (0, import_core5.normalizeCreditDeliveryState)(input.state).note), identity = notes2[0].spenderWalletIdentity;
|
|
6401
|
-
const words = creditDrawPublicInputs(c, p.params, p.deliveries), authority = await this.authority(
|
|
6402
|
-
"credit-draw",
|
|
6403
|
-
capacity,
|
|
6404
|
-
words,
|
|
6405
|
-
p.authorization,
|
|
6406
|
-
identity
|
|
6407
|
-
);
|
|
6408
|
-
const sourceIndices = await Promise.all(
|
|
6409
|
-
notes2.map(async (note, i) => {
|
|
6410
|
-
const leaf = await this.creditLeaf(note);
|
|
6411
|
-
check(
|
|
6412
|
-
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 (0, import_core5.computeCreditNullifier)(c.chainId, note.creditSharedKey, leaf) === p.params.nullifiers[i],
|
|
6413
|
-
"Credit draw mismatch"
|
|
6414
|
-
);
|
|
6415
|
-
return BigInt(await this.membership(leaf, p.inputs[i], p.params.sources));
|
|
6416
|
-
})
|
|
6417
|
-
);
|
|
6418
|
-
return provingRequest(
|
|
6419
|
-
profile.name,
|
|
6420
6502
|
{
|
|
6421
|
-
|
|
6422
|
-
|
|
6423
|
-
|
|
6424
|
-
notes2.map((note) => note.ownerPayout),
|
|
6425
|
-
capacity,
|
|
6426
|
-
() => 0n
|
|
6427
|
-
),
|
|
6428
|
-
owner_wallet_identities: pad2(
|
|
6429
|
-
notes2.map((note) => BigInt(note.ownerWalletIdentity)),
|
|
6430
|
-
capacity,
|
|
6431
|
-
() => 0n
|
|
6432
|
-
),
|
|
6433
|
-
input_amounts: pad2(
|
|
6434
|
-
notes2.map((note) => note.amount),
|
|
6435
|
-
capacity,
|
|
6436
|
-
() => 0n
|
|
6437
|
-
),
|
|
6438
|
-
input_nonces: pad2(
|
|
6439
|
-
notes2.map((note) => note.nonce),
|
|
6440
|
-
capacity,
|
|
6441
|
-
() => 0n
|
|
6442
|
-
),
|
|
6443
|
-
credit_shared_keys: pad2(
|
|
6444
|
-
notes2.map((note) => note.creditSharedKey),
|
|
6445
|
-
capacity,
|
|
6446
|
-
() => 0n
|
|
6447
|
-
),
|
|
6448
|
-
leaf_indices: pad2(
|
|
6449
|
-
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6450
|
-
capacity,
|
|
6451
|
-
() => 0n
|
|
6452
|
-
),
|
|
6453
|
-
merkle_paths: pad2(
|
|
6454
|
-
p.inputs.map((input) => [...input.path]),
|
|
6455
|
-
capacity,
|
|
6456
|
-
zeros
|
|
6457
|
-
),
|
|
6458
|
-
input_source_indices: pad2(sourceIndices, capacity, () => 0n),
|
|
6459
|
-
draw_amounts: pad2(p.amounts, capacity, () => 0n)
|
|
6503
|
+
name: "owner_address",
|
|
6504
|
+
count: 1,
|
|
6505
|
+
array: false
|
|
6460
6506
|
},
|
|
6461
|
-
words
|
|
6462
|
-
);
|
|
6463
|
-
}
|
|
6464
|
-
async topUpCredit(p) {
|
|
6465
|
-
const c = this.#protocol.context, previous = (0, import_core5.normalizeCreditDeliveryState)(p.previous.state), next = (0, import_core5.normalizeCreditDeliveryState)(p.state), old = previous.note, note = next.note, leaf = await this.creditLeaf(old);
|
|
6466
|
-
for (const field2 of [
|
|
6467
|
-
"spenderWalletIdentity",
|
|
6468
|
-
"ownerWalletIdentity",
|
|
6469
|
-
"spenderPayout",
|
|
6470
|
-
"ownerPayout",
|
|
6471
|
-
"creditSharedKey"
|
|
6472
|
-
])
|
|
6473
|
-
check(old[field2] === note[field2], "Credit role or payout changed");
|
|
6474
|
-
check(
|
|
6475
|
-
JSON.stringify(previous.ownerReceivingKeys) === JSON.stringify(next.ownerReceivingKeys) && JSON.stringify(previous.spenderReceivingKeys) === JSON.stringify(next.spenderReceivingKeys),
|
|
6476
|
-
"Credit receiving snapshots changed"
|
|
6477
|
-
);
|
|
6478
|
-
check(
|
|
6479
|
-
old.amount < note.amount && old.expiry <= note.expiry && old.expiry === p.params.previousExpiry && (c.now === void 0 || old.expiry > c.now),
|
|
6480
|
-
"invalid Credit top-up"
|
|
6481
|
-
);
|
|
6482
|
-
check(
|
|
6483
|
-
await (0, import_core5.computeCreditNullifier)(c.chainId, old.creditSharedKey, leaf) === p.params.creditNullifier,
|
|
6484
|
-
"previous Credit nullifier mismatch"
|
|
6485
|
-
);
|
|
6486
|
-
await this.membership(leaf, p.previous, [p.params.creditSource]);
|
|
6487
|
-
const words = topUpCreditPublicInputs(c, p.params, p.deliveries, p.funding), base = await this.creation({ ...p, params: p.params.creation }, "top-up-credit", words);
|
|
6488
|
-
return provingRequest(
|
|
6489
|
-
"credit_top_up",
|
|
6490
6507
|
{
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6508
|
+
name: "tree_id",
|
|
6509
|
+
count: 1,
|
|
6510
|
+
array: false
|
|
6511
|
+
},
|
|
6512
|
+
{
|
|
6513
|
+
name: "merkle_root",
|
|
6514
|
+
count: 1,
|
|
6515
|
+
array: false
|
|
6516
|
+
},
|
|
6517
|
+
{
|
|
6518
|
+
name: "nullifier",
|
|
6519
|
+
count: 1,
|
|
6520
|
+
array: false
|
|
6521
|
+
},
|
|
6522
|
+
{
|
|
6523
|
+
name: "amount",
|
|
6524
|
+
count: 1,
|
|
6525
|
+
array: false
|
|
6496
6526
|
},
|
|
6497
|
-
|
|
6498
|
-
|
|
6499
|
-
|
|
6500
|
-
|
|
6501
|
-
const request = registrationAuthorizationRequest(context, registration, options), words = registrationPublicInputs(context, registration, options);
|
|
6502
|
-
check(
|
|
6503
|
-
authorization.walletIdentity === registration.walletIdentity && authorization.digest === (0, import_core5.computeWalletAuthorizationDigest)(request),
|
|
6504
|
-
"registry authorization mismatch"
|
|
6505
|
-
);
|
|
6506
|
-
const witness = authorization.withWitness((value) => value);
|
|
6507
|
-
check(
|
|
6508
|
-
await (0, import_core5.verifyWalletAuthorization)(
|
|
6509
|
-
registration.walletIdentity,
|
|
6510
|
-
Uint8Array.from([4, ...witness.public_key_x, ...witness.public_key_y]),
|
|
6511
|
-
Uint8Array.from(witness.signature),
|
|
6512
|
-
request
|
|
6513
|
-
),
|
|
6514
|
-
"invalid registry authority"
|
|
6515
|
-
);
|
|
6516
|
-
return provingRequest("wallet_registration", { ...witness }, words);
|
|
6517
|
-
}
|
|
6518
|
-
};
|
|
6519
|
-
|
|
6520
|
-
// src/RegistrationOperation.ts
|
|
6521
|
-
function check2(ok, message) {
|
|
6522
|
-
if (!ok) {
|
|
6523
|
-
throw new Error(message);
|
|
6524
|
-
}
|
|
6525
|
-
}
|
|
6526
|
-
function publicProof(bundle) {
|
|
6527
|
-
return {
|
|
6528
|
-
formatVersion: bundle.formatVersion,
|
|
6529
|
-
bbVersion: bundle.bbVersion,
|
|
6530
|
-
circuitName: bundle.circuitName,
|
|
6531
|
-
target: bundle.target,
|
|
6532
|
-
artifactSha256: bundle.artifactSha256,
|
|
6533
|
-
vkSha256: bundle.vkSha256,
|
|
6534
|
-
proofHex: bundle.proofHex,
|
|
6535
|
-
proofSha256: bundle.proofSha256,
|
|
6536
|
-
publicInputs: [...bundle.publicInputs]
|
|
6537
|
-
};
|
|
6538
|
-
}
|
|
6539
|
-
var RegistrationOperation = class _RegistrationOperation {
|
|
6540
|
-
#registry;
|
|
6541
|
-
#runtime;
|
|
6542
|
-
#plan;
|
|
6543
|
-
#authorization;
|
|
6544
|
-
#proof;
|
|
6545
|
-
#hash;
|
|
6546
|
-
#anchor;
|
|
6547
|
-
status;
|
|
6548
|
-
constructor(registry, runtime, plan, status, authorization, proof, hash, anchor) {
|
|
6549
|
-
this.#registry = registry;
|
|
6550
|
-
this.#runtime = { ...runtime };
|
|
6551
|
-
this.#plan = structuredClone(plan);
|
|
6552
|
-
this.status = status;
|
|
6553
|
-
this.#authorization = authorization;
|
|
6554
|
-
this.#proof = proof ? publicProof(proof) : void 0;
|
|
6555
|
-
this.#hash = hash;
|
|
6556
|
-
this.#anchor = anchor ? { ...anchor } : void 0;
|
|
6557
|
-
Object.freeze(this);
|
|
6558
|
-
}
|
|
6559
|
-
static async prepare(registry, options) {
|
|
6560
|
-
const runtime = { ...options };
|
|
6561
|
-
const update = options.update ?? false;
|
|
6562
|
-
check2(typeof update === "boolean", "update must be boolean");
|
|
6563
|
-
await registry.validateDeployment(runtime.reader);
|
|
6564
|
-
const block = await runtime.reader.getBlock(await runtime.reader.getLatestBlockNumber());
|
|
6565
|
-
const context = { ...registry.context, now: block.timestamp };
|
|
6566
|
-
const nonce = await runtime.reader.getRegistryNonce(
|
|
6567
|
-
context,
|
|
6568
|
-
runtime.wallet.walletIdentity,
|
|
6569
|
-
block
|
|
6570
|
-
);
|
|
6571
|
-
check2(
|
|
6572
|
-
typeof nonce === "bigint" && nonce >= 0n && nonce < (1n << 64n) - 1n,
|
|
6573
|
-
"invalid or exhausted registry nonce"
|
|
6574
|
-
);
|
|
6575
|
-
check2(
|
|
6576
|
-
update ? nonce > 0n : nonce === 0n,
|
|
6577
|
-
update ? "wallet is not registered" : "wallet is already registered; prepare an update"
|
|
6578
|
-
);
|
|
6579
|
-
const address = import_core6.ReceivingAddress.parse(await registry.resolve(runtime.wallet.getAddress()));
|
|
6580
|
-
const keys = address.getReceivingKeys();
|
|
6581
|
-
const registration = {
|
|
6582
|
-
walletIdentity: runtime.wallet.walletIdentity,
|
|
6583
|
-
keys: {
|
|
6584
|
-
viewingPublicKey: (0, import_ethers6.hexlify)(keys.viewingPublicKey),
|
|
6585
|
-
clueKey: (0, import_ethers6.hexlify)(keys.clueKey)
|
|
6527
|
+
{
|
|
6528
|
+
name: "deadline",
|
|
6529
|
+
count: 1,
|
|
6530
|
+
array: false
|
|
6586
6531
|
},
|
|
6587
|
-
|
|
6588
|
-
|
|
6589
|
-
|
|
6590
|
-
|
|
6591
|
-
|
|
6592
|
-
|
|
6593
|
-
|
|
6594
|
-
|
|
6595
|
-
|
|
6596
|
-
|
|
6597
|
-
|
|
6598
|
-
|
|
6599
|
-
|
|
6600
|
-
|
|
6601
|
-
|
|
6602
|
-
|
|
6603
|
-
"
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6608
|
-
|
|
6609
|
-
|
|
6610
|
-
|
|
6611
|
-
|
|
6612
|
-
|
|
6613
|
-
|
|
6614
|
-
|
|
6615
|
-
|
|
6616
|
-
|
|
6617
|
-
|
|
6618
|
-
|
|
6619
|
-
|
|
6620
|
-
|
|
6621
|
-
|
|
6622
|
-
|
|
6623
|
-
|
|
6624
|
-
|
|
6625
|
-
|
|
6626
|
-
|
|
6627
|
-
|
|
6628
|
-
|
|
6629
|
-
|
|
6630
|
-
|
|
6631
|
-
|
|
6632
|
-
|
|
6633
|
-
|
|
6634
|
-
|
|
6635
|
-
|
|
6636
|
-
|
|
6637
|
-
|
|
6638
|
-
|
|
6639
|
-
|
|
6640
|
-
|
|
6641
|
-
|
|
6642
|
-
|
|
6643
|
-
|
|
6644
|
-
|
|
6645
|
-
|
|
6646
|
-
|
|
6647
|
-
|
|
6648
|
-
|
|
6649
|
-
|
|
6650
|
-
|
|
6651
|
-
|
|
6652
|
-
|
|
6653
|
-
|
|
6654
|
-
|
|
6655
|
-
|
|
6656
|
-
|
|
6657
|
-
|
|
6658
|
-
|
|
6659
|
-
|
|
6660
|
-
|
|
6661
|
-
|
|
6662
|
-
|
|
6663
|
-
|
|
6664
|
-
|
|
6665
|
-
|
|
6666
|
-
|
|
6667
|
-
|
|
6668
|
-
|
|
6669
|
-
|
|
6670
|
-
|
|
6671
|
-
|
|
6672
|
-
|
|
6673
|
-
|
|
6674
|
-
|
|
6675
|
-
|
|
6676
|
-
|
|
6677
|
-
|
|
6678
|
-
|
|
6679
|
-
|
|
6680
|
-
|
|
6681
|
-
|
|
6682
|
-
|
|
6683
|
-
|
|
6684
|
-
|
|
6685
|
-
|
|
6686
|
-
|
|
6687
|
-
|
|
6688
|
-
|
|
6689
|
-
|
|
6690
|
-
|
|
6691
|
-
|
|
6692
|
-
|
|
6693
|
-
|
|
6694
|
-
|
|
6695
|
-
|
|
6696
|
-
|
|
6697
|
-
|
|
6698
|
-
|
|
6699
|
-
|
|
6700
|
-
|
|
6701
|
-
|
|
6702
|
-
|
|
6703
|
-
|
|
6704
|
-
|
|
6705
|
-
|
|
6706
|
-
|
|
6707
|
-
|
|
6708
|
-
|
|
6709
|
-
|
|
6710
|
-
|
|
6711
|
-
|
|
6712
|
-
|
|
6713
|
-
|
|
6714
|
-
|
|
6715
|
-
|
|
6716
|
-
|
|
6717
|
-
|
|
6718
|
-
|
|
6719
|
-
|
|
6720
|
-
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6724
|
-
|
|
6725
|
-
|
|
6726
|
-
|
|
6727
|
-
|
|
6728
|
-
|
|
6729
|
-
|
|
6730
|
-
|
|
6731
|
-
|
|
6732
|
-
|
|
6733
|
-
trackTransaction(transactionHash) {
|
|
6734
|
-
check2(/^0x[a-fA-F0-9]{64}$/.test(transactionHash), "invalid registry transaction hash");
|
|
6735
|
-
check2(
|
|
6736
|
-
this.#proof && ["ready", "uncertain"].includes(this.status),
|
|
6737
|
-
"registry operation is not ready"
|
|
6738
|
-
);
|
|
6739
|
-
return new _RegistrationOperation(
|
|
6740
|
-
this.#registry,
|
|
6741
|
-
this.#runtime,
|
|
6742
|
-
this.#plan,
|
|
6743
|
-
"uncertain",
|
|
6744
|
-
void 0,
|
|
6745
|
-
this.#proof,
|
|
6746
|
-
transactionHash
|
|
6747
|
-
);
|
|
6748
|
-
}
|
|
6749
|
-
async reconcile(options = {}) {
|
|
6750
|
-
options.signal?.throwIfAborted();
|
|
6751
|
-
const { reader } = this.#runtime;
|
|
6752
|
-
const p = this.#plan;
|
|
6753
|
-
await this.#registry.validateDeployment(reader);
|
|
6754
|
-
if (this.#anchor && (await reader.getBlock(this.#anchor.number)).hash !== this.#anchor.hash) {
|
|
6755
|
-
return new _RegistrationOperation(
|
|
6756
|
-
this.#registry,
|
|
6757
|
-
this.#runtime,
|
|
6758
|
-
p,
|
|
6759
|
-
"reorged",
|
|
6760
|
-
void 0,
|
|
6761
|
-
this.#proof,
|
|
6762
|
-
this.#hash
|
|
6763
|
-
);
|
|
6764
|
-
}
|
|
6765
|
-
const hash = options.transactionHash ?? this.#hash;
|
|
6766
|
-
const receipt = hash ? await reader.getReceipt(hash) : null;
|
|
6767
|
-
if (receipt) {
|
|
6768
|
-
check2(
|
|
6769
|
-
receipt.transactionHash === hash && (await reader.getBlock(receipt.block.number)).hash === receipt.block.hash,
|
|
6770
|
-
"registry receipt is not canonical"
|
|
6771
|
-
);
|
|
6772
|
-
const transaction = await reader.getTransaction(hash);
|
|
6773
|
-
const call = this.call();
|
|
6774
|
-
check2(
|
|
6775
|
-
transaction && transaction.transactionHash === hash && transaction.to.toLowerCase() === call.to.toLowerCase() && transaction.data.toLowerCase() === call.data.toLowerCase() && transaction.value === 0n,
|
|
6776
|
-
"registry transaction differs from frozen request"
|
|
6777
|
-
);
|
|
6778
|
-
check2(
|
|
6779
|
-
receipt.status === "success" || receipt.status === "reverted",
|
|
6780
|
-
"registry execution status is missing"
|
|
6781
|
-
);
|
|
6782
|
-
if (receipt.status === "success") {
|
|
6783
|
-
const found = receipt.logs.some((log) => {
|
|
6784
|
-
if (log.address.toLowerCase() !== p.context.registryAddress.toLowerCase() || log.transactionHash !== hash) {
|
|
6785
|
-
return false;
|
|
6786
|
-
}
|
|
6787
|
-
try {
|
|
6788
|
-
const event = ((decoded) => ({
|
|
6789
|
-
eventName: decoded.name,
|
|
6790
|
-
args: decoded.args.toObject()
|
|
6791
|
-
}))(
|
|
6792
|
-
new import_ethers6.Interface(invisiAddressRegistryAbi).parseLog({
|
|
6793
|
-
data: log.data,
|
|
6794
|
-
topics: log.topics
|
|
6795
|
-
})
|
|
6796
|
-
);
|
|
6797
|
-
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;
|
|
6798
|
-
} catch {
|
|
6799
|
-
return false;
|
|
6800
|
-
}
|
|
6801
|
-
});
|
|
6802
|
-
check2(found, "registry receipt has no matching key update event");
|
|
6803
|
-
check2(
|
|
6804
|
-
(await reader.getBlock(receipt.block.number)).hash === receipt.block.hash,
|
|
6805
|
-
"registry block changed during confirmation"
|
|
6806
|
-
);
|
|
6807
|
-
options.signal?.throwIfAborted();
|
|
6808
|
-
return new _RegistrationOperation(
|
|
6809
|
-
this.#registry,
|
|
6810
|
-
this.#runtime,
|
|
6811
|
-
p,
|
|
6812
|
-
"confirmed",
|
|
6813
|
-
void 0,
|
|
6814
|
-
this.#proof,
|
|
6815
|
-
hash,
|
|
6816
|
-
receipt.block
|
|
6817
|
-
);
|
|
6532
|
+
{
|
|
6533
|
+
name: "auth_digest_high",
|
|
6534
|
+
count: 1,
|
|
6535
|
+
array: false
|
|
6536
|
+
},
|
|
6537
|
+
{
|
|
6538
|
+
name: "auth_digest_low",
|
|
6539
|
+
count: 1,
|
|
6540
|
+
array: false
|
|
6541
|
+
}
|
|
6542
|
+
],
|
|
6543
|
+
private: [
|
|
6544
|
+
"public_key_x",
|
|
6545
|
+
"public_key_y",
|
|
6546
|
+
"signature",
|
|
6547
|
+
"spender_payout",
|
|
6548
|
+
"spender_wallet_identity",
|
|
6549
|
+
"owner_wallet_identity",
|
|
6550
|
+
"input_nonce",
|
|
6551
|
+
"expiry",
|
|
6552
|
+
"credit_shared_key",
|
|
6553
|
+
"leaf_index",
|
|
6554
|
+
"merkle_path"
|
|
6555
|
+
]
|
|
6556
|
+
},
|
|
6557
|
+
credit_top_up: {
|
|
6558
|
+
artifactSha256: "fbe662363d9814983f7940f74369117cd6c84783945fbf527b0ed48d011b58a4",
|
|
6559
|
+
keys: {
|
|
6560
|
+
evm: "44436f31414497a708355426da051ee48ba63fdebcb6cfd72347c37c34c98c50"
|
|
6561
|
+
},
|
|
6562
|
+
publicInputCount: 50,
|
|
6563
|
+
public: [
|
|
6564
|
+
{
|
|
6565
|
+
name: "chain_id",
|
|
6566
|
+
count: 1,
|
|
6567
|
+
array: false
|
|
6568
|
+
},
|
|
6569
|
+
{
|
|
6570
|
+
name: "protocol_address",
|
|
6571
|
+
count: 1,
|
|
6572
|
+
array: false
|
|
6573
|
+
},
|
|
6574
|
+
{
|
|
6575
|
+
name: "token_address",
|
|
6576
|
+
count: 1,
|
|
6577
|
+
array: false
|
|
6578
|
+
},
|
|
6579
|
+
{
|
|
6580
|
+
name: "owner_address",
|
|
6581
|
+
count: 1,
|
|
6582
|
+
array: false
|
|
6583
|
+
},
|
|
6584
|
+
{
|
|
6585
|
+
name: "actual_count",
|
|
6586
|
+
count: 1,
|
|
6587
|
+
array: false
|
|
6588
|
+
},
|
|
6589
|
+
{
|
|
6590
|
+
name: "source_count",
|
|
6591
|
+
count: 1,
|
|
6592
|
+
array: false
|
|
6593
|
+
},
|
|
6594
|
+
{
|
|
6595
|
+
name: "input_tree_ids",
|
|
6596
|
+
count: 10,
|
|
6597
|
+
array: true
|
|
6598
|
+
},
|
|
6599
|
+
{
|
|
6600
|
+
name: "merkle_roots",
|
|
6601
|
+
count: 10,
|
|
6602
|
+
array: true
|
|
6603
|
+
},
|
|
6604
|
+
{
|
|
6605
|
+
name: "nullifiers",
|
|
6606
|
+
count: 10,
|
|
6607
|
+
array: true
|
|
6608
|
+
},
|
|
6609
|
+
{
|
|
6610
|
+
name: "credit_commitment",
|
|
6611
|
+
count: 1,
|
|
6612
|
+
array: false
|
|
6613
|
+
},
|
|
6614
|
+
{
|
|
6615
|
+
name: "change_commitment",
|
|
6616
|
+
count: 1,
|
|
6617
|
+
array: false
|
|
6618
|
+
},
|
|
6619
|
+
{
|
|
6620
|
+
name: "delivery_hash_high",
|
|
6621
|
+
count: 1,
|
|
6622
|
+
array: false
|
|
6623
|
+
},
|
|
6624
|
+
{
|
|
6625
|
+
name: "delivery_hash_low",
|
|
6626
|
+
count: 1,
|
|
6627
|
+
array: false
|
|
6628
|
+
},
|
|
6629
|
+
{
|
|
6630
|
+
name: "expiry",
|
|
6631
|
+
count: 1,
|
|
6632
|
+
array: false
|
|
6633
|
+
},
|
|
6634
|
+
{
|
|
6635
|
+
name: "deadline",
|
|
6636
|
+
count: 1,
|
|
6637
|
+
array: false
|
|
6638
|
+
},
|
|
6639
|
+
{
|
|
6640
|
+
name: "deposit_amount",
|
|
6641
|
+
count: 1,
|
|
6642
|
+
array: false
|
|
6643
|
+
},
|
|
6644
|
+
{
|
|
6645
|
+
name: "deposit_payer",
|
|
6646
|
+
count: 1,
|
|
6647
|
+
array: false
|
|
6648
|
+
},
|
|
6649
|
+
{
|
|
6650
|
+
name: "credit_tree_id",
|
|
6651
|
+
count: 1,
|
|
6652
|
+
array: false
|
|
6653
|
+
},
|
|
6654
|
+
{
|
|
6655
|
+
name: "credit_merkle_root",
|
|
6656
|
+
count: 1,
|
|
6657
|
+
array: false
|
|
6658
|
+
},
|
|
6659
|
+
{
|
|
6660
|
+
name: "credit_nullifier",
|
|
6661
|
+
count: 1,
|
|
6662
|
+
array: false
|
|
6663
|
+
},
|
|
6664
|
+
{
|
|
6665
|
+
name: "previous_expiry",
|
|
6666
|
+
count: 1,
|
|
6667
|
+
array: false
|
|
6668
|
+
},
|
|
6669
|
+
{
|
|
6670
|
+
name: "auth_digest_high",
|
|
6671
|
+
count: 1,
|
|
6672
|
+
array: false
|
|
6673
|
+
},
|
|
6674
|
+
{
|
|
6675
|
+
name: "auth_digest_low",
|
|
6676
|
+
count: 1,
|
|
6677
|
+
array: false
|
|
6818
6678
|
}
|
|
6819
|
-
|
|
6820
|
-
|
|
6821
|
-
|
|
6822
|
-
|
|
6823
|
-
|
|
6824
|
-
"
|
|
6825
|
-
|
|
6826
|
-
|
|
6827
|
-
|
|
6828
|
-
|
|
6829
|
-
|
|
6830
|
-
|
|
6831
|
-
|
|
6832
|
-
|
|
6833
|
-
|
|
6834
|
-
|
|
6835
|
-
|
|
6836
|
-
|
|
6837
|
-
|
|
6838
|
-
|
|
6839
|
-
|
|
6840
|
-
|
|
6841
|
-
|
|
6842
|
-
}
|
|
6843
|
-
[/* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom")]() {
|
|
6844
|
-
return this.toJSON();
|
|
6845
|
-
}
|
|
6846
|
-
};
|
|
6847
|
-
|
|
6848
|
-
// src/AddressRegistry.ts
|
|
6849
|
-
var AddressRegistry = class {
|
|
6850
|
-
context;
|
|
6851
|
-
#lookup;
|
|
6852
|
-
expectedRuntimeCodeHash;
|
|
6853
|
-
constructor(context, options = {}) {
|
|
6854
|
-
if (typeof context.chainId !== "bigint" || context.chainId < 0n || context.chainId >= 1n << 64n || BigInt((0, import_ethers7.getAddress)(context.registryAddress)) === 0n) {
|
|
6855
|
-
throw new Error("invalid registry context");
|
|
6856
|
-
}
|
|
6857
|
-
this.context = Object.freeze({
|
|
6858
|
-
...context,
|
|
6859
|
-
registryAddress: (0, import_ethers7.getAddress)(context.registryAddress)
|
|
6860
|
-
});
|
|
6861
|
-
this.#lookup = options.lookup;
|
|
6862
|
-
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
6863
|
-
if (this.expectedRuntimeCodeHash && !/^0x[0-9a-f]{64}$/.test(this.expectedRuntimeCodeHash)) {
|
|
6864
|
-
throw new Error("invalid registry runtime profile");
|
|
6865
|
-
}
|
|
6866
|
-
Object.freeze(this);
|
|
6867
|
-
}
|
|
6868
|
-
async validateDeployment(reader) {
|
|
6869
|
-
if (!this.expectedRuntimeCodeHash) {
|
|
6870
|
-
throw new import_core7.MissingCapabilityError("trusted registry deployment profile");
|
|
6871
|
-
}
|
|
6872
|
-
if (await reader.getChainId() !== this.context.chainId) {
|
|
6873
|
-
throw new Error("registry chain mismatch");
|
|
6874
|
-
}
|
|
6875
|
-
const code = await reader.getCode(this.context.registryAddress);
|
|
6876
|
-
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || (0, import_ethers7.keccak256)(code) !== this.expectedRuntimeCodeHash) {
|
|
6877
|
-
throw new Error("registry runtime profile mismatch");
|
|
6878
|
-
}
|
|
6879
|
-
}
|
|
6880
|
-
prepareRegistration(options) {
|
|
6881
|
-
return RegistrationOperation.prepare(this, options);
|
|
6882
|
-
}
|
|
6883
|
-
async resolve(address) {
|
|
6884
|
-
const receiving = import_core7.ReceivingAddress.parse(address);
|
|
6885
|
-
if (receiving.kind === "short" && !this.#lookup) {
|
|
6886
|
-
throw new import_core7.MissingCapabilityError("registry reader");
|
|
6887
|
-
}
|
|
6888
|
-
return (await receiving.resolve(this.#lookup)).toString();
|
|
6889
|
-
}
|
|
6890
|
-
authorization(registration, options) {
|
|
6891
|
-
return registrationAuthorizationRequest(this.context, registration, options);
|
|
6892
|
-
}
|
|
6893
|
-
publicInputs(registration, options) {
|
|
6894
|
-
return registrationPublicInputs(this.context, registration, options);
|
|
6895
|
-
}
|
|
6896
|
-
buildCall(registration, proof, options) {
|
|
6897
|
-
return buildRegistrationCalldata(this.context, registration, proof, options);
|
|
6898
|
-
}
|
|
6899
|
-
};
|
|
6900
|
-
|
|
6901
|
-
// src/Protocol.ts
|
|
6902
|
-
var import_ethers9 = require("ethers");
|
|
6903
|
-
var import_rpc = require("@invisi-labs/rpc");
|
|
6904
|
-
|
|
6905
|
-
// src/TokenProtocol.ts
|
|
6906
|
-
var import_ethers8 = require("ethers");
|
|
6907
|
-
var import_core8 = require("@invisi-labs/core");
|
|
6908
|
-
var TokenProtocol = class {
|
|
6909
|
-
context;
|
|
6910
|
-
expectedRuntimeCodeHash;
|
|
6911
|
-
constructor(context, options = {}) {
|
|
6912
|
-
const normalized = normalizeContext(context);
|
|
6913
|
-
if (BigInt(normalized.protocolAddress) === 0n || BigInt(normalized.tokenAddress) === 0n) {
|
|
6914
|
-
throw new Error("deployment addresses must be nonzero");
|
|
6915
|
-
}
|
|
6916
|
-
if (options.expectedRuntimeCodeHash && !/^0x[0-9a-fA-F]{64}$/.test(options.expectedRuntimeCodeHash)) {
|
|
6917
|
-
throw new Error("invalid runtime code hash");
|
|
6918
|
-
}
|
|
6919
|
-
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
6920
|
-
this.context = Object.freeze(normalized);
|
|
6921
|
-
Object.freeze(this);
|
|
6922
|
-
}
|
|
6923
|
-
async validateDeployment(reader, options = {}) {
|
|
6924
|
-
if ((options.requireRuntimeProfile ?? true) && !this.expectedRuntimeCodeHash) {
|
|
6925
|
-
throw new import_core8.MissingCapabilityError("trusted deployment profile");
|
|
6926
|
-
}
|
|
6927
|
-
if (await reader.getChainId() !== this.context.chainId) {
|
|
6928
|
-
throw new Error("deployment chain mismatch");
|
|
6929
|
-
}
|
|
6930
|
-
const code = await reader.getCode(this.context.protocolAddress);
|
|
6931
|
-
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || this.expectedRuntimeCodeHash && (0, import_ethers8.keccak256)(code) !== this.expectedRuntimeCodeHash) {
|
|
6932
|
-
throw new Error("deployment runtime code profile mismatch");
|
|
6933
|
-
}
|
|
6934
|
-
const tokenCode = await reader.getCode(this.context.tokenAddress);
|
|
6935
|
-
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(tokenCode)) {
|
|
6936
|
-
throw new Error("token address must have contract code");
|
|
6937
|
-
}
|
|
6938
|
-
}
|
|
6939
|
-
transact(request) {
|
|
6940
|
-
return {
|
|
6941
|
-
to: this.context.protocolAddress,
|
|
6942
|
-
value: 0n,
|
|
6943
|
-
...buildTransactCalldata({ ...request, context: this.context })
|
|
6944
|
-
};
|
|
6679
|
+
],
|
|
6680
|
+
private: [
|
|
6681
|
+
"input_amounts",
|
|
6682
|
+
"input_nonces",
|
|
6683
|
+
"leaf_indices",
|
|
6684
|
+
"merkle_paths",
|
|
6685
|
+
"input_source_indices",
|
|
6686
|
+
"public_key_x",
|
|
6687
|
+
"public_key_y",
|
|
6688
|
+
"signature",
|
|
6689
|
+
"spender_payout",
|
|
6690
|
+
"spender_wallet_identity",
|
|
6691
|
+
"owner_wallet_identity",
|
|
6692
|
+
"credit_amount",
|
|
6693
|
+
"credit_nonce",
|
|
6694
|
+
"credit_shared_key",
|
|
6695
|
+
"change_amount",
|
|
6696
|
+
"change_nonce",
|
|
6697
|
+
"previous_credit_amount",
|
|
6698
|
+
"previous_credit_nonce",
|
|
6699
|
+
"previous_credit_leaf_index",
|
|
6700
|
+
"previous_credit_merkle_path"
|
|
6701
|
+
]
|
|
6945
6702
|
}
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6703
|
+
};
|
|
6704
|
+
|
|
6705
|
+
// src/witness.ts
|
|
6706
|
+
var pad2 = (values, count, zero) => {
|
|
6707
|
+
if (values.length > count) throw new Error("witness capacity exceeded");
|
|
6708
|
+
return [...values, ...Array.from({ length: count - values.length }, zero)];
|
|
6709
|
+
};
|
|
6710
|
+
var zeros = () => Array(16).fill(0n);
|
|
6711
|
+
var zeroAuthority = () => ({
|
|
6712
|
+
public_key_x: Array(32).fill(0),
|
|
6713
|
+
public_key_y: Array(32).fill(0),
|
|
6714
|
+
signature: Array(64).fill(0)
|
|
6715
|
+
});
|
|
6716
|
+
function check2(ok, message) {
|
|
6717
|
+
if (!ok) throw new Error(message);
|
|
6718
|
+
}
|
|
6719
|
+
function provingRequest(circuitName, privateInputs, expectedPublicInputs, target = "evm") {
|
|
6720
|
+
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
6721
|
+
check2(typeof key === "string", "unpublished proof target");
|
|
6722
|
+
check2(
|
|
6723
|
+
expectedPublicInputs.length === schema.publicInputCount,
|
|
6724
|
+
"public input order/width mismatch"
|
|
6725
|
+
);
|
|
6726
|
+
check2(
|
|
6727
|
+
Object.keys(privateInputs).length === schema.private.length && schema.private.every((name) => Object.hasOwn(privateInputs, name)),
|
|
6728
|
+
"private witness schema mismatch"
|
|
6729
|
+
);
|
|
6730
|
+
let offset = 0;
|
|
6731
|
+
const publicInputs = {};
|
|
6732
|
+
for (const entry of schema.public) {
|
|
6733
|
+
const values = expectedPublicInputs.slice(offset, offset + entry.count).map((value) => {
|
|
6734
|
+
const n = BigInt(value);
|
|
6735
|
+
check2(n >= 0n && n < FIELD_MODULUS, "noncanonical public input");
|
|
6736
|
+
return n;
|
|
6737
|
+
});
|
|
6738
|
+
publicInputs[entry.name] = entry.array ? values : values[0];
|
|
6739
|
+
offset += entry.count;
|
|
6952
6740
|
}
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6741
|
+
check2(offset === expectedPublicInputs.length, "public input layout mismatch");
|
|
6742
|
+
return {
|
|
6743
|
+
circuitName,
|
|
6744
|
+
target,
|
|
6745
|
+
artifactSha256: schema.artifactSha256,
|
|
6746
|
+
vkSha256: key,
|
|
6747
|
+
expectedPublicInputs: [...expectedPublicInputs],
|
|
6748
|
+
witness: new import_prover.LocalWitness({ ...privateInputs, ...publicInputs })
|
|
6749
|
+
};
|
|
6750
|
+
}
|
|
6751
|
+
var WitnessBuilder = class {
|
|
6752
|
+
#protocol;
|
|
6753
|
+
constructor(protocol) {
|
|
6754
|
+
this.#protocol = protocol;
|
|
6959
6755
|
}
|
|
6960
|
-
|
|
6756
|
+
static statement(circuitName, expectedPublicInputs, target = "evm") {
|
|
6757
|
+
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
6758
|
+
check2(
|
|
6759
|
+
typeof key === "string" && expectedPublicInputs.length === schema.publicInputCount,
|
|
6760
|
+
"unpublished target or statement width mismatch"
|
|
6761
|
+
);
|
|
6961
6762
|
return {
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6763
|
+
circuitName,
|
|
6764
|
+
target,
|
|
6765
|
+
artifactSha256: schema.artifactSha256,
|
|
6766
|
+
vkSha256: key,
|
|
6767
|
+
expectedPublicInputs: [...expectedPublicInputs]
|
|
6965
6768
|
};
|
|
6966
6769
|
}
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6770
|
+
context(note) {
|
|
6771
|
+
const c = this.#protocol.context;
|
|
6772
|
+
check2(
|
|
6773
|
+
note.chainId === c.chainId && note.protocolAddress === BigInt(c.protocolAddress) && note.tokenAddress === BigInt(c.tokenAddress),
|
|
6774
|
+
"note context mismatch"
|
|
6775
|
+
);
|
|
6973
6776
|
}
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6777
|
+
async authority(operation, capacity, words, signed, identity) {
|
|
6778
|
+
check2(!!signed, "private wallet authorization required");
|
|
6779
|
+
const c = this.#protocol.context, request = {
|
|
6780
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
6781
|
+
operation,
|
|
6782
|
+
capacity,
|
|
6783
|
+
words: words.slice(0, -2).map(BigInt)
|
|
6979
6784
|
};
|
|
6785
|
+
check2(
|
|
6786
|
+
signed.walletIdentity === identity && signed.digest === (0, import_core10.computeWalletAuthorizationDigest)(request),
|
|
6787
|
+
"authorization statement mismatch"
|
|
6788
|
+
);
|
|
6789
|
+
const witness = signed.withWitness((value) => value);
|
|
6790
|
+
check2(
|
|
6791
|
+
await (0, import_core10.verifyWalletAuthorization)(
|
|
6792
|
+
identity,
|
|
6793
|
+
Uint8Array.from([4, ...witness.public_key_x, ...witness.public_key_y]),
|
|
6794
|
+
Uint8Array.from(witness.signature),
|
|
6795
|
+
request
|
|
6796
|
+
),
|
|
6797
|
+
"invalid wallet authorization"
|
|
6798
|
+
);
|
|
6799
|
+
return witness;
|
|
6980
6800
|
}
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6801
|
+
async membership(leaf, input, sources) {
|
|
6802
|
+
const source = sources.findIndex((value) => value.treeId === input.treeId);
|
|
6803
|
+
check2(
|
|
6804
|
+
source >= 0 && Number.isInteger(input.leafIndex) && input.leafIndex >= 0 && input.leafIndex < 65536 && input.path.length === 16,
|
|
6805
|
+
"invalid membership position"
|
|
6806
|
+
);
|
|
6807
|
+
let root = BigInt(leaf);
|
|
6808
|
+
for (let level = 0; level < 16; level++)
|
|
6809
|
+
root = BigInt(
|
|
6810
|
+
await (0, import_core10.poseidonHash)(
|
|
6811
|
+
input.leafIndex >> level & 1 ? [input.path[level], root] : [root, input.path[level]]
|
|
6812
|
+
)
|
|
6813
|
+
);
|
|
6814
|
+
check2(root === BigInt(sources[source].merkleRoot), "membership root mismatch");
|
|
6815
|
+
return source;
|
|
6987
6816
|
}
|
|
6988
|
-
|
|
6989
|
-
|
|
6990
|
-
|
|
6991
|
-
|
|
6992
|
-
|
|
6993
|
-
|
|
6994
|
-
|
|
6995
|
-
|
|
6996
|
-
this.deployment = (0, import_rpc.defineDeployment)(options.deployment);
|
|
6997
|
-
this.context = Object.freeze({
|
|
6998
|
-
chainId: this.deployment.chainId,
|
|
6999
|
-
protocolAddress: this.deployment.protocol.address
|
|
7000
|
-
});
|
|
7001
|
-
Object.freeze(this);
|
|
6817
|
+
async noteLeaf(note) {
|
|
6818
|
+
this.context(note);
|
|
6819
|
+
return (0, import_core10.computeNoteCommitment)(
|
|
6820
|
+
note.chainId,
|
|
6821
|
+
await (0, import_core10.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
|
|
6822
|
+
note.tokenAddress,
|
|
6823
|
+
note.amount
|
|
6824
|
+
);
|
|
7002
6825
|
}
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
6826
|
+
async creditLeaf(note) {
|
|
6827
|
+
this.context(note);
|
|
6828
|
+
return (0, import_core10.computeCreditCommitment)(
|
|
6829
|
+
note.chainId,
|
|
6830
|
+
note.spenderWalletIdentity,
|
|
6831
|
+
note.ownerWalletIdentity,
|
|
6832
|
+
note.spenderPayout,
|
|
6833
|
+
note.ownerPayout,
|
|
6834
|
+
note.tokenAddress,
|
|
6835
|
+
note.amount,
|
|
6836
|
+
note.nonce,
|
|
6837
|
+
note.expiry,
|
|
6838
|
+
await (0, import_core10.computeCreditSharedKeyHash)(note.creditSharedKey)
|
|
7011
6839
|
);
|
|
7012
|
-
const protocol = new _Protocol({ deployment });
|
|
7013
|
-
if (protocol.context.chainId !== chainId) throw new Error("RPC deployment chain mismatch");
|
|
7014
|
-
await protocol.validateDeployment(provider);
|
|
7015
|
-
return protocol;
|
|
7016
6840
|
}
|
|
7017
|
-
async
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
await
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
)
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
6841
|
+
async noteInputs(inputs, sources, nullifiers, identity, authority) {
|
|
6842
|
+
check2(inputs.length === nullifiers.length, "input count mismatch");
|
|
6843
|
+
return Promise.all(
|
|
6844
|
+
inputs.map(async (input, i) => {
|
|
6845
|
+
check2(input.note.walletIdentity === identity, "input wallet mismatch");
|
|
6846
|
+
const leaf = await this.noteLeaf(input.note);
|
|
6847
|
+
check2(
|
|
6848
|
+
await (0, import_core10.computeNoteNullifier)(input.note.chainId, input.note.nonce, leaf) === nullifiers[i],
|
|
6849
|
+
"input nullifier mismatch"
|
|
6850
|
+
);
|
|
6851
|
+
return BigInt(await this.membership(leaf, input, sources));
|
|
6852
|
+
})
|
|
6853
|
+
);
|
|
6854
|
+
}
|
|
6855
|
+
async transact(p) {
|
|
6856
|
+
const c = this.#protocol.context, n = normalizeTransactRequest(c, p.params, p.deliveries, p.funding), words = transactUserPublicInputs(c, p.params, p.deliveries, p.funding);
|
|
6857
|
+
check2(
|
|
6858
|
+
p.inputs.length === n.inputCount && p.outputs.length === n.outputCount,
|
|
6859
|
+
"note count mismatch"
|
|
6860
|
+
);
|
|
6861
|
+
const identity = p.inputs[0]?.note.walletIdentity;
|
|
6862
|
+
const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
|
|
6863
|
+
const authority = identity && !unsignedSweep ? await this.authority("transact", n.capacity, words, p.authorization, identity) : zeroAuthority();
|
|
6864
|
+
const sources = await this.noteInputs(
|
|
6865
|
+
p.inputs,
|
|
6866
|
+
p.params.sources,
|
|
6867
|
+
p.params.nullifiers,
|
|
6868
|
+
identity ?? "0x" + "00".repeat(32),
|
|
6869
|
+
authority
|
|
6870
|
+
);
|
|
6871
|
+
for (const [i, note] of p.outputs.entries())
|
|
6872
|
+
check2(
|
|
6873
|
+
await this.noteLeaf(note) === p.params.outputCommitments[i],
|
|
6874
|
+
"output commitment mismatch"
|
|
6875
|
+
);
|
|
6876
|
+
const all = [...p.inputs.map((input) => input.note), ...p.outputs];
|
|
6877
|
+
return provingRequest(
|
|
6878
|
+
`transact_user_slots${n.capacity}`,
|
|
6879
|
+
{
|
|
6880
|
+
wallet_identity: identity ? BigInt(identity) : 0n,
|
|
6881
|
+
...authority,
|
|
6882
|
+
output_wallet_identities: pad2(
|
|
6883
|
+
[
|
|
6884
|
+
...p.inputs.map(() => 0n),
|
|
6885
|
+
...p.outputs.map((note) => BigInt(note.walletIdentity))
|
|
6886
|
+
],
|
|
6887
|
+
n.capacity,
|
|
6888
|
+
() => 0n
|
|
6889
|
+
),
|
|
6890
|
+
amounts: pad2(
|
|
6891
|
+
all.map((note) => note.amount),
|
|
6892
|
+
n.capacity,
|
|
6893
|
+
() => 0n
|
|
6894
|
+
),
|
|
6895
|
+
nonces: pad2(
|
|
6896
|
+
all.map((note) => note.nonce),
|
|
6897
|
+
n.capacity,
|
|
6898
|
+
() => 0n
|
|
6899
|
+
),
|
|
6900
|
+
leaf_indices: pad2(
|
|
6901
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6902
|
+
n.capacity,
|
|
6903
|
+
() => 0n
|
|
6904
|
+
),
|
|
6905
|
+
merkle_paths: pad2(
|
|
6906
|
+
p.inputs.map((input) => [...input.path]),
|
|
6907
|
+
n.capacity,
|
|
6908
|
+
zeros
|
|
6909
|
+
),
|
|
6910
|
+
input_source_indices: pad2(sources, n.capacity, () => 0n)
|
|
6911
|
+
},
|
|
6912
|
+
words,
|
|
6913
|
+
p.target
|
|
6914
|
+
);
|
|
7036
6915
|
}
|
|
7037
|
-
|
|
6916
|
+
async creation(p, operation, words) {
|
|
6917
|
+
const state = (0, import_core10.normalizeCreditDeliveryState)(p.state), note = state.note;
|
|
6918
|
+
check2(
|
|
6919
|
+
await this.creditLeaf(note) === p.params.creditCommitment && note.ownerPayout === BigInt(p.params.owner) && note.expiry === p.params.expiry,
|
|
6920
|
+
"Credit creation mismatch"
|
|
6921
|
+
);
|
|
6922
|
+
const authority = await this.authority(
|
|
6923
|
+
operation,
|
|
6924
|
+
10,
|
|
6925
|
+
words,
|
|
6926
|
+
p.authorization,
|
|
6927
|
+
note.ownerWalletIdentity
|
|
6928
|
+
);
|
|
6929
|
+
const sources = await this.noteInputs(
|
|
6930
|
+
p.inputs,
|
|
6931
|
+
p.params.sources,
|
|
6932
|
+
p.params.nullifiers,
|
|
6933
|
+
note.ownerWalletIdentity,
|
|
6934
|
+
authority
|
|
6935
|
+
);
|
|
6936
|
+
if (p.change)
|
|
6937
|
+
check2(
|
|
6938
|
+
p.change.walletIdentity === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
|
|
6939
|
+
"change commitment mismatch"
|
|
6940
|
+
);
|
|
6941
|
+
else check2(BigInt(p.params.changeCommitment) === 0n, "missing change note");
|
|
7038
6942
|
return {
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
6943
|
+
...authority,
|
|
6944
|
+
input_amounts: pad2(
|
|
6945
|
+
p.inputs.map((input) => input.note.amount),
|
|
6946
|
+
10,
|
|
6947
|
+
() => 0n
|
|
6948
|
+
),
|
|
6949
|
+
input_nonces: pad2(
|
|
6950
|
+
p.inputs.map((input) => input.note.nonce),
|
|
6951
|
+
10,
|
|
6952
|
+
() => 0n
|
|
6953
|
+
),
|
|
6954
|
+
leaf_indices: pad2(
|
|
6955
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6956
|
+
10,
|
|
6957
|
+
() => 0n
|
|
6958
|
+
),
|
|
6959
|
+
merkle_paths: pad2(
|
|
6960
|
+
p.inputs.map((input) => [...input.path]),
|
|
6961
|
+
10,
|
|
6962
|
+
zeros
|
|
6963
|
+
),
|
|
6964
|
+
input_source_indices: pad2(sources, 10, () => 0n),
|
|
6965
|
+
spender_payout: note.spenderPayout,
|
|
6966
|
+
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
6967
|
+
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
6968
|
+
credit_amount: note.amount,
|
|
6969
|
+
credit_nonce: note.nonce,
|
|
6970
|
+
credit_shared_key: note.creditSharedKey,
|
|
6971
|
+
change_amount: p.change?.amount ?? 0n,
|
|
6972
|
+
change_nonce: p.change?.nonce ?? 0n
|
|
7042
6973
|
};
|
|
7043
6974
|
}
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
6975
|
+
async createCredit(p) {
|
|
6976
|
+
const words = createCreditPublicInputs(
|
|
6977
|
+
this.#protocol.context,
|
|
6978
|
+
p.params,
|
|
6979
|
+
p.deliveries,
|
|
6980
|
+
p.funding
|
|
6981
|
+
);
|
|
6982
|
+
return provingRequest(
|
|
6983
|
+
"create_credit",
|
|
6984
|
+
await this.creation(p, "create-credit", words),
|
|
6985
|
+
words
|
|
7049
6986
|
);
|
|
7050
6987
|
}
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
params.
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
|
|
7067
|
-
|
|
7068
|
-
|
|
7069
|
-
|
|
7070
|
-
|
|
7071
|
-
|
|
7072
|
-
|
|
7073
|
-
|
|
7074
|
-
|
|
7075
|
-
|
|
7076
|
-
|
|
7077
|
-
|
|
7078
|
-
|
|
7079
|
-
|
|
7080
|
-
}
|
|
7081
|
-
|
|
7082
|
-
// src/withdrawal.ts
|
|
7083
|
-
var import_core10 = require("@invisi-labs/core");
|
|
7084
|
-
async function buildWithdrawalCalldata(p) {
|
|
7085
|
-
const r = normalizeTransactRequest(p.context, p.params, [], p.funding);
|
|
7086
|
-
if (r.outputCount !== 0 || r.depositAmount !== 0n || p.sourceNotes.length === 0 || p.sourceNotes.length !== r.inputCount) {
|
|
7087
|
-
throw new Error("full withdrawal requires inputs, no private outputs and no funding");
|
|
6988
|
+
async cancelCredit(p) {
|
|
6989
|
+
const note = (0, import_core10.normalizeCreditDeliveryState)(p.input.state).note, leaf = await this.creditLeaf(note), c = this.#protocol.context;
|
|
6990
|
+
check2(
|
|
6991
|
+
await (0, import_core10.computeCreditNullifier)(c.chainId, note.creditSharedKey, leaf) === p.params.nullifier && note.amount === p.params.amount && note.ownerPayout === BigInt(p.params.owner),
|
|
6992
|
+
"Credit cancellation mismatch"
|
|
6993
|
+
);
|
|
6994
|
+
await this.membership(leaf, p.input, [p.params.source]);
|
|
6995
|
+
const words = cancelCreditPublicInputs(c, p.params), authority = await this.authority(
|
|
6996
|
+
"cancel-credit",
|
|
6997
|
+
1,
|
|
6998
|
+
words,
|
|
6999
|
+
p.authorization,
|
|
7000
|
+
note.ownerWalletIdentity
|
|
7001
|
+
);
|
|
7002
|
+
return provingRequest(
|
|
7003
|
+
"credit_cancel",
|
|
7004
|
+
{
|
|
7005
|
+
...authority,
|
|
7006
|
+
spender_payout: note.spenderPayout,
|
|
7007
|
+
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
7008
|
+
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
7009
|
+
input_nonce: note.nonce,
|
|
7010
|
+
expiry: note.expiry,
|
|
7011
|
+
credit_shared_key: note.creditSharedKey,
|
|
7012
|
+
leaf_index: BigInt(p.input.leafIndex),
|
|
7013
|
+
merkle_path: [...p.input.path]
|
|
7014
|
+
},
|
|
7015
|
+
words
|
|
7016
|
+
);
|
|
7088
7017
|
}
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
const
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7018
|
+
async drawCredit(p) {
|
|
7019
|
+
const c = this.#protocol.context, profile = selectCreditDrawCircuit(p.inputs.length), capacity = profile.maxSize;
|
|
7020
|
+
check2(
|
|
7021
|
+
p.inputs.length === p.amounts.length && p.inputs.length === p.params.nullifiers.length,
|
|
7022
|
+
"draw input count mismatch"
|
|
7023
|
+
);
|
|
7024
|
+
const notes2 = p.inputs.map((input) => (0, import_core10.normalizeCreditDeliveryState)(input.state).note), identity = notes2[0].spenderWalletIdentity;
|
|
7025
|
+
const words = creditDrawPublicInputs(c, p.params, p.deliveries), authority = await this.authority(
|
|
7026
|
+
"credit-draw",
|
|
7027
|
+
capacity,
|
|
7028
|
+
words,
|
|
7029
|
+
p.authorization,
|
|
7030
|
+
identity
|
|
7031
|
+
);
|
|
7032
|
+
const sourceIndices = await Promise.all(
|
|
7033
|
+
notes2.map(async (note, i) => {
|
|
7034
|
+
const leaf = await this.creditLeaf(note);
|
|
7035
|
+
check2(
|
|
7036
|
+
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 (0, import_core10.computeCreditNullifier)(c.chainId, note.creditSharedKey, leaf) === p.params.nullifiers[i],
|
|
7037
|
+
"Credit draw mismatch"
|
|
7038
|
+
);
|
|
7039
|
+
return BigInt(await this.membership(leaf, p.inputs[i], p.params.sources));
|
|
7040
|
+
})
|
|
7041
|
+
);
|
|
7042
|
+
return provingRequest(
|
|
7043
|
+
profile.name,
|
|
7044
|
+
{
|
|
7045
|
+
...authority,
|
|
7046
|
+
spender_wallet_identity: BigInt(identity),
|
|
7047
|
+
owner_payouts: pad2(
|
|
7048
|
+
notes2.map((note) => note.ownerPayout),
|
|
7049
|
+
capacity,
|
|
7050
|
+
() => 0n
|
|
7051
|
+
),
|
|
7052
|
+
owner_wallet_identities: pad2(
|
|
7053
|
+
notes2.map((note) => BigInt(note.ownerWalletIdentity)),
|
|
7054
|
+
capacity,
|
|
7055
|
+
() => 0n
|
|
7056
|
+
),
|
|
7057
|
+
input_amounts: pad2(
|
|
7058
|
+
notes2.map((note) => note.amount),
|
|
7059
|
+
capacity,
|
|
7060
|
+
() => 0n
|
|
7061
|
+
),
|
|
7062
|
+
input_nonces: pad2(
|
|
7063
|
+
notes2.map((note) => note.nonce),
|
|
7064
|
+
capacity,
|
|
7065
|
+
() => 0n
|
|
7066
|
+
),
|
|
7067
|
+
credit_shared_keys: pad2(
|
|
7068
|
+
notes2.map((note) => note.creditSharedKey),
|
|
7069
|
+
capacity,
|
|
7070
|
+
() => 0n
|
|
7071
|
+
),
|
|
7072
|
+
leaf_indices: pad2(
|
|
7073
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
7074
|
+
capacity,
|
|
7075
|
+
() => 0n
|
|
7076
|
+
),
|
|
7077
|
+
merkle_paths: pad2(
|
|
7078
|
+
p.inputs.map((input) => [...input.path]),
|
|
7079
|
+
capacity,
|
|
7080
|
+
zeros
|
|
7081
|
+
),
|
|
7082
|
+
input_source_indices: pad2(sourceIndices, capacity, () => 0n),
|
|
7083
|
+
draw_amounts: pad2(p.amounts, capacity, () => 0n)
|
|
7084
|
+
},
|
|
7085
|
+
words
|
|
7101
7086
|
);
|
|
7102
|
-
const nullifier = await (0, import_core10.computeNoteNullifier)(note.chainId, note.nonce, commitment);
|
|
7103
|
-
if (nullifier.toLowerCase() !== r.nullifiers[index].toLowerCase())
|
|
7104
|
-
throw new Error("source note nullifier mismatch");
|
|
7105
|
-
total += note.amount;
|
|
7106
7087
|
}
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7088
|
+
async topUpCredit(p) {
|
|
7089
|
+
const c = this.#protocol.context, previous = (0, import_core10.normalizeCreditDeliveryState)(p.previous.state), next = (0, import_core10.normalizeCreditDeliveryState)(p.state), old = previous.note, note = next.note, leaf = await this.creditLeaf(old);
|
|
7090
|
+
for (const field2 of [
|
|
7091
|
+
"spenderWalletIdentity",
|
|
7092
|
+
"ownerWalletIdentity",
|
|
7093
|
+
"spenderPayout",
|
|
7094
|
+
"ownerPayout",
|
|
7095
|
+
"creditSharedKey"
|
|
7096
|
+
])
|
|
7097
|
+
check2(old[field2] === note[field2], "Credit role or payout changed");
|
|
7098
|
+
check2(
|
|
7099
|
+
JSON.stringify(previous.ownerReceivingKeys) === JSON.stringify(next.ownerReceivingKeys) && JSON.stringify(previous.spenderReceivingKeys) === JSON.stringify(next.spenderReceivingKeys),
|
|
7100
|
+
"Credit receiving snapshots changed"
|
|
7101
|
+
);
|
|
7102
|
+
check2(
|
|
7103
|
+
old.amount < note.amount && old.expiry <= note.expiry && old.expiry === p.params.previousExpiry && (c.now === void 0 || old.expiry > c.now),
|
|
7104
|
+
"invalid Credit top-up"
|
|
7105
|
+
);
|
|
7106
|
+
check2(
|
|
7107
|
+
await (0, import_core10.computeCreditNullifier)(c.chainId, old.creditSharedKey, leaf) === p.params.creditNullifier,
|
|
7108
|
+
"previous Credit nullifier mismatch"
|
|
7109
|
+
);
|
|
7110
|
+
await this.membership(leaf, p.previous, [p.params.creditSource]);
|
|
7111
|
+
const words = topUpCreditPublicInputs(c, p.params, p.deliveries, p.funding), base = await this.creation({ ...p, params: p.params.creation }, "top-up-credit", words);
|
|
7112
|
+
return provingRequest(
|
|
7113
|
+
"credit_top_up",
|
|
7114
|
+
{
|
|
7115
|
+
...base,
|
|
7116
|
+
previous_credit_amount: old.amount,
|
|
7117
|
+
previous_credit_nonce: old.nonce,
|
|
7118
|
+
previous_credit_leaf_index: BigInt(p.previous.leafIndex),
|
|
7119
|
+
previous_credit_merkle_path: [...p.previous.path]
|
|
7120
|
+
},
|
|
7121
|
+
words
|
|
7122
|
+
);
|
|
7123
|
+
}
|
|
7124
|
+
};
|
|
7111
7125
|
|
|
7112
7126
|
// src/factory.ts
|
|
7113
7127
|
var import_ethers10 = require("ethers");
|
|
@@ -7180,8 +7194,7 @@ async function resolveInstanceAddress(client, factoryAddress, salt) {
|
|
|
7180
7194
|
normalizeTransactRequest,
|
|
7181
7195
|
notes,
|
|
7182
7196
|
pad,
|
|
7183
|
-
|
|
7184
|
-
registrationPublicInputs,
|
|
7197
|
+
registrationDigest,
|
|
7185
7198
|
registrationTypedData,
|
|
7186
7199
|
resolveInstanceAddress,
|
|
7187
7200
|
selectCreditDrawCircuit,
|