@invisi-labs/protocol 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/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 +1589 -1575
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +83 -37
- package/dist/index.d.ts +83 -37
- package/dist/index.js +2669 -2733
- 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,513 @@ 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
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
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, maximum = length) {
|
|
4275
|
+
if (!(0, import_ethers4.isHexString)(v) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(v) || (0, import_ethers4.dataLength)(v) < length || (0, import_ethers4.dataLength)(v) > maximum)
|
|
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 ? 402 : 160,
|
|
4322
|
+
options.credit ? 4 : 2,
|
|
4323
|
+
options.credit ? 658 : 416
|
|
4324
|
+
);
|
|
4325
|
+
const clue = envelope(value.clue, 68);
|
|
4326
|
+
if (clue.slice(130, 132).toLowerCase() !== "18") throw new Error("clue precision must be 24");
|
|
4327
|
+
return { ciphertext, clue };
|
|
4328
|
+
}
|
|
4329
|
+
var deliveriesHash = (v) => (0, import_ethers4.keccak256)(
|
|
4330
|
+
import_ethers4.AbiCoder.defaultAbiCoder().encode(
|
|
4331
|
+
[
|
|
4332
|
+
{
|
|
4333
|
+
type: "tuple[]",
|
|
4334
|
+
components: [
|
|
4335
|
+
{ name: "ciphertext", type: "bytes" },
|
|
4336
|
+
{ name: "clue", type: "bytes" }
|
|
4337
|
+
]
|
|
4338
|
+
}
|
|
4339
|
+
].map((parameter) => import_ethers4.ParamType.from(parameter)),
|
|
4340
|
+
[dense(v, "deliveries")]
|
|
4341
|
+
)
|
|
4342
|
+
);
|
|
4343
|
+
function normalizeFunding(input = {}) {
|
|
4344
|
+
const f = { ...EMPTY_FUNDING, ...input };
|
|
4345
|
+
(0, import_ethers4.getAddress)(f.payer);
|
|
4346
|
+
uint(f.amount, 128, "depositAmount");
|
|
4347
|
+
uint(f.sigNonce, 256, "sigNonce");
|
|
4348
|
+
uint(f.deadline, 256, "funding deadline");
|
|
4349
|
+
if (!(0, import_ethers4.isHexString)(f.signature) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(f.signature))
|
|
4350
|
+
throw new Error("invalid signature bytes");
|
|
4351
|
+
const p = f.permit;
|
|
3932
4352
|
uint(p.deadline, 256);
|
|
3933
4353
|
uint(p.v, 8);
|
|
3934
4354
|
for (const v of [p.r, p.s])
|
|
3935
|
-
if (!(0,
|
|
4355
|
+
if (!(0, import_ethers4.isHexString)(v) || (0, import_ethers4.dataLength)(v) !== 32) throw new Error("permit r/s must be bytes32");
|
|
3936
4356
|
if (f.amount === 0n !== (BigInt(f.payer) === 0n))
|
|
3937
4357
|
throw new Error("deposit amount and payer must both be zero or positive");
|
|
3938
4358
|
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
4359
|
throw new Error("zero funding must be entirely empty");
|
|
3940
|
-
return { ...f, payer: (0,
|
|
4360
|
+
return { ...f, payer: (0, import_ethers4.getAddress)(f.payer) };
|
|
3941
4361
|
}
|
|
3942
4362
|
function validateFundingSubmission(f, caller, now) {
|
|
3943
4363
|
if (f.signature !== "0x" && now !== void 0 && uint(now, 64, "now") > f.deadline)
|
|
3944
4364
|
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,
|
|
4365
|
+
if (f.signature === "0x" && (f.sigNonce !== 0n || f.deadline !== 0n || caller !== void 0 && f.amount > 0n && (0, import_ethers4.getAddress)(caller) !== f.payer))
|
|
3946
4366
|
throw new Error("direct funding requires payer caller and zero nonce/deadline");
|
|
3947
4367
|
}
|
|
3948
4368
|
var getEIP712Domain = (c) => ({
|
|
3949
4369
|
name: "InvisibleProtocol",
|
|
3950
4370
|
version: "1",
|
|
3951
4371
|
chainId: uint(c.chainId, 64),
|
|
3952
|
-
verifyingContract: (0,
|
|
4372
|
+
verifyingContract: (0, import_ethers4.getAddress)(c.protocolAddress)
|
|
3953
4373
|
});
|
|
3954
4374
|
var fundingFields = [
|
|
3955
4375
|
{ name: "requestHash", type: "bytes32" },
|
|
@@ -3975,9 +4395,9 @@ var CREATE_CREDIT_FIELDS = [
|
|
|
3975
4395
|
];
|
|
3976
4396
|
function validateCreateCreditRequest(c, p, cs, funding = {}) {
|
|
3977
4397
|
known(p, CREATE_CREDIT_FIELDS);
|
|
3978
|
-
if ((0,
|
|
4398
|
+
if ((0, import_ethers5.getAddress)(p.token) !== (0, import_ethers5.getAddress)(c.tokenAddress))
|
|
3979
4399
|
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,
|
|
4400
|
+
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
4401
|
if (BigInt(creditCommitment) === 0n || creditCommitment === changeCommitment)
|
|
3982
4402
|
throw new Error("zero or duplicate commitment");
|
|
3983
4403
|
if (BigInt(owner) === 0n || expiry === 0n || c.now !== void 0 && expiry <= c.now)
|
|
@@ -4034,7 +4454,7 @@ function createCreditBaseInputs(c, p, cs, f = {}) {
|
|
|
4034
4454
|
function createCreditPublicInputs(c, p, deliveries, funding = {}) {
|
|
4035
4455
|
const base = createCreditBaseInputs(c, p, deliveries, funding);
|
|
4036
4456
|
const digest = BigInt(
|
|
4037
|
-
(0,
|
|
4457
|
+
(0, import_core4.computeWalletAuthorizationDigest)({
|
|
4038
4458
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4039
4459
|
operation: "create-credit",
|
|
4040
4460
|
capacity: 10,
|
|
@@ -4050,17 +4470,17 @@ var hashContext = {
|
|
|
4050
4470
|
};
|
|
4051
4471
|
function createCreditRequestHash(p, cs, f = {}) {
|
|
4052
4472
|
const r = validateCreateCreditRequest({ ...hashContext, tokenAddress: p.token }, p, cs, f);
|
|
4053
|
-
return (0,
|
|
4054
|
-
|
|
4473
|
+
return (0, import_ethers5.keccak256)(
|
|
4474
|
+
import_ethers5.AbiCoder.defaultAbiCoder().encode(
|
|
4055
4475
|
[
|
|
4056
4476
|
{ type: "bytes32" },
|
|
4057
4477
|
creationTuple,
|
|
4058
4478
|
{ type: "bytes32" },
|
|
4059
4479
|
{ type: "address" },
|
|
4060
4480
|
{ type: "uint256" }
|
|
4061
|
-
].map((parameter) =>
|
|
4481
|
+
].map((parameter) => import_ethers5.ParamType.from(parameter)),
|
|
4062
4482
|
[
|
|
4063
|
-
(0,
|
|
4483
|
+
(0, import_ethers5.keccak256)(new TextEncoder().encode("InvisiCreateCredit")),
|
|
4064
4484
|
p,
|
|
4065
4485
|
deliveriesHash(cs),
|
|
4066
4486
|
r.funding.payer,
|
|
@@ -4070,7 +4490,7 @@ function createCreditRequestHash(p, cs, f = {}) {
|
|
|
4070
4490
|
);
|
|
4071
4491
|
}
|
|
4072
4492
|
function encodeCreateCreditTypedData(c, p, deliveries, funding = {}) {
|
|
4073
|
-
return (0,
|
|
4493
|
+
return (0, import_core4.walletAuthorizationTypedData)({
|
|
4074
4494
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4075
4495
|
operation: "create-credit",
|
|
4076
4496
|
capacity: 10,
|
|
@@ -4097,7 +4517,7 @@ function buildCreateCreditCalldata(p) {
|
|
|
4097
4517
|
const r = validateCreateCreditRequest(p.context, p.params, p.deliveries, p.funding);
|
|
4098
4518
|
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
4099
4519
|
return {
|
|
4100
|
-
data: new
|
|
4520
|
+
data: new import_ethers5.Interface(invisiProtocolAbi).encodeFunctionData("createCredit", [
|
|
4101
4521
|
encodeCreditProof(p.proof),
|
|
4102
4522
|
p.params,
|
|
4103
4523
|
p.deliveries,
|
|
@@ -4107,17 +4527,17 @@ function buildCreateCreditCalldata(p) {
|
|
|
4107
4527
|
};
|
|
4108
4528
|
}
|
|
4109
4529
|
function encodeCreditProof(proof) {
|
|
4110
|
-
if (!(0,
|
|
4530
|
+
if (!(0, import_ethers5.isHexString)(proof) || !/^0x(?:[a-fA-F0-9]{2})*$/.test(proof) || (0, import_ethers5.dataLength)(proof) === 0)
|
|
4111
4531
|
throw new Error("empty or malformed Credit proof");
|
|
4112
|
-
return
|
|
4113
|
-
["uint8", "bytes"].map((parameter) =>
|
|
4532
|
+
return import_ethers5.AbiCoder.defaultAbiCoder().encode(
|
|
4533
|
+
["uint8", "bytes"].map((parameter) => import_ethers5.ParamType.from(parameter)),
|
|
4114
4534
|
[0, proof]
|
|
4115
4535
|
);
|
|
4116
4536
|
}
|
|
4117
4537
|
|
|
4118
4538
|
// src/credit-lifecycle.ts
|
|
4119
|
-
var
|
|
4120
|
-
var
|
|
4539
|
+
var import_ethers6 = require("ethers");
|
|
4540
|
+
var import_core5 = require("@invisi-labs/core");
|
|
4121
4541
|
var CREDIT_DRAW_CAPACITIES = [1, 12, 50, 120];
|
|
4122
4542
|
function selectCreditDrawCircuit(count) {
|
|
4123
4543
|
if (!Number.isInteger(count) || count < 1 || count > 120)
|
|
@@ -4142,7 +4562,7 @@ function validateCreditDrawRequest(c, p, cs) {
|
|
|
4142
4562
|
"totalAmount",
|
|
4143
4563
|
"deadline"
|
|
4144
4564
|
]);
|
|
4145
|
-
if ((0,
|
|
4565
|
+
if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
|
|
4146
4566
|
throw new Error("request token mismatch");
|
|
4147
4567
|
const ctx = normalizeContext(c), ns = notes(p.nullifiers, "nullifiers"), profile = selectCreditDrawCircuit(ns.length), sources = normalizeSources(p.sources, ns.length, profile.maxSize);
|
|
4148
4568
|
for (const [key, v] of Object.entries({
|
|
@@ -4160,7 +4580,7 @@ function validateCreditDrawRequest(c, p, cs) {
|
|
|
4160
4580
|
if (BigInt(remainderCommitments[i]) === 0n && BigInt(recoveryAmounts[i]) !== 0n)
|
|
4161
4581
|
throw new Error("full draw requires zero recovery amount");
|
|
4162
4582
|
}
|
|
4163
|
-
const spender = (0,
|
|
4583
|
+
const spender = (0, import_ethers6.getAddress)(p.spender), totalAmount = uint(p.totalAmount, profile.totalBits, "totalAmount");
|
|
4164
4584
|
if (BigInt(spender) === 0n || totalAmount === 0n)
|
|
4165
4585
|
throw new Error("spender and total amount must be positive");
|
|
4166
4586
|
if (dense(cs, "deliveries").length !== 2 * ns.length)
|
|
@@ -4211,9 +4631,9 @@ function creditDrawBaseInputs(c, p, cs) {
|
|
|
4211
4631
|
}
|
|
4212
4632
|
function validateCancelCreditRequest(c, p) {
|
|
4213
4633
|
known(p, ["token", "source", "nullifier", "owner", "amount", "deadline"]);
|
|
4214
|
-
if ((0,
|
|
4634
|
+
if ((0, import_ethers6.getAddress)(p.token) !== (0, import_ethers6.getAddress)(c.tokenAddress))
|
|
4215
4635
|
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,
|
|
4636
|
+
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
4637
|
if (BigInt(owner) === 0n || amount === 0n) throw new Error("owner and amount must be positive");
|
|
4218
4638
|
return {
|
|
4219
4639
|
...ctx,
|
|
@@ -4271,10 +4691,10 @@ var hashContext2 = {
|
|
|
4271
4691
|
};
|
|
4272
4692
|
function cancelCreditRequestHash(p) {
|
|
4273
4693
|
validateCancelCreditRequest({ ...hashContext2, tokenAddress: p.token }, p);
|
|
4274
|
-
return (0,
|
|
4275
|
-
|
|
4276
|
-
[{ type: "bytes32" }, cancelTuple].map((parameter) =>
|
|
4277
|
-
[(0,
|
|
4694
|
+
return (0, import_ethers6.keccak256)(
|
|
4695
|
+
import_ethers6.AbiCoder.defaultAbiCoder().encode(
|
|
4696
|
+
[{ type: "bytes32" }, cancelTuple].map((parameter) => import_ethers6.ParamType.from(parameter)),
|
|
4697
|
+
[(0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiCancelCredit")), p]
|
|
4278
4698
|
)
|
|
4279
4699
|
);
|
|
4280
4700
|
}
|
|
@@ -4285,17 +4705,17 @@ function topUpCreditRequestHash(p, cs, f = {}) {
|
|
|
4285
4705
|
cs,
|
|
4286
4706
|
f
|
|
4287
4707
|
);
|
|
4288
|
-
return (0,
|
|
4289
|
-
|
|
4708
|
+
return (0, import_ethers6.keccak256)(
|
|
4709
|
+
import_ethers6.AbiCoder.defaultAbiCoder().encode(
|
|
4290
4710
|
[
|
|
4291
4711
|
{ type: "bytes32" },
|
|
4292
4712
|
topTuple,
|
|
4293
4713
|
{ type: "bytes32" },
|
|
4294
4714
|
{ type: "address" },
|
|
4295
4715
|
{ type: "uint256" }
|
|
4296
|
-
].map((parameter) =>
|
|
4716
|
+
].map((parameter) => import_ethers6.ParamType.from(parameter)),
|
|
4297
4717
|
[
|
|
4298
|
-
(0,
|
|
4718
|
+
(0, import_ethers6.keccak256)(new TextEncoder().encode("InvisiTopUpCredit")),
|
|
4299
4719
|
p,
|
|
4300
4720
|
deliveriesHash(cs),
|
|
4301
4721
|
r.creation.funding.payer,
|
|
@@ -4305,7 +4725,7 @@ function topUpCreditRequestHash(p, cs, f = {}) {
|
|
|
4305
4725
|
);
|
|
4306
4726
|
}
|
|
4307
4727
|
function authorize(c, operation, capacity, words) {
|
|
4308
|
-
return (0,
|
|
4728
|
+
return (0, import_core5.walletAuthorizationTypedData)({
|
|
4309
4729
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4310
4730
|
operation,
|
|
4311
4731
|
capacity,
|
|
@@ -4314,7 +4734,7 @@ function authorize(c, operation, capacity, words) {
|
|
|
4314
4734
|
}
|
|
4315
4735
|
function appendDigest(c, operation, capacity, words) {
|
|
4316
4736
|
const digest = BigInt(
|
|
4317
|
-
(0,
|
|
4737
|
+
(0, import_core5.computeWalletAuthorizationDigest)({
|
|
4318
4738
|
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
4319
4739
|
operation,
|
|
4320
4740
|
capacity,
|
|
@@ -4370,7 +4790,7 @@ function encodeTopUpCreditFundingTypedData(c, p, cs, f) {
|
|
|
4370
4790
|
function buildCreditDrawCalldata(p) {
|
|
4371
4791
|
validateCreditDrawRequest(p.context, p.params, p.deliveries);
|
|
4372
4792
|
return {
|
|
4373
|
-
data: new
|
|
4793
|
+
data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("creditDraw", [
|
|
4374
4794
|
encodeCreditProof(p.proof),
|
|
4375
4795
|
p.params,
|
|
4376
4796
|
p.deliveries
|
|
@@ -4382,7 +4802,7 @@ function buildCreditDrawCalldata(p) {
|
|
|
4382
4802
|
function buildCancelCreditCalldata(p) {
|
|
4383
4803
|
validateCancelCreditRequest(p.context, p.params);
|
|
4384
4804
|
return {
|
|
4385
|
-
data: new
|
|
4805
|
+
data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("cancelCredit", [
|
|
4386
4806
|
encodeCreditProof(p.proof),
|
|
4387
4807
|
p.params
|
|
4388
4808
|
])
|
|
@@ -4392,7 +4812,7 @@ function buildTopUpCreditCalldata(p) {
|
|
|
4392
4812
|
const r = validateTopUpCreditRequest(p.context, p.params, p.deliveries, p.funding);
|
|
4393
4813
|
validateFundingSubmission(r.creation.funding, p.caller, p.context.now);
|
|
4394
4814
|
return {
|
|
4395
|
-
data: new
|
|
4815
|
+
data: new import_ethers6.Interface(invisiProtocolAbi).encodeFunctionData("topUpCredit", [
|
|
4396
4816
|
encodeCreditProof(p.proof),
|
|
4397
4817
|
p.params,
|
|
4398
4818
|
p.deliveries,
|
|
@@ -4403,8 +4823,8 @@ function buildTopUpCreditCalldata(p) {
|
|
|
4403
4823
|
}
|
|
4404
4824
|
|
|
4405
4825
|
// src/funds.ts
|
|
4406
|
-
var
|
|
4407
|
-
var
|
|
4826
|
+
var import_ethers7 = require("ethers");
|
|
4827
|
+
var import_core6 = require("@invisi-labs/core");
|
|
4408
4828
|
var TRANSACT_CAPACITIES = [14, 56, 112, 168];
|
|
4409
4829
|
function selectTransactCapacity(inputs, outputs) {
|
|
4410
4830
|
if (!Number.isInteger(inputs) || !Number.isInteger(outputs) || inputs < 0 || outputs < 0 || inputs + outputs < 1 || inputs === 0 && outputs < 2 || inputs + outputs > 168)
|
|
@@ -4413,7 +4833,7 @@ function selectTransactCapacity(inputs, outputs) {
|
|
|
4413
4833
|
}
|
|
4414
4834
|
function normalizeTransactRequest(c, p, cs, funding = {}) {
|
|
4415
4835
|
const ctx = normalizeContext(c);
|
|
4416
|
-
if ((0,
|
|
4836
|
+
if ((0, import_ethers7.getAddress)(p.token) !== ctx.tokenAddress)
|
|
4417
4837
|
throw new Error("request token mismatch");
|
|
4418
4838
|
known(p, [
|
|
4419
4839
|
"token",
|
|
@@ -4427,7 +4847,7 @@ function normalizeTransactRequest(c, p, cs, funding = {}) {
|
|
|
4427
4847
|
const ns = notes(p.nullifiers, "nullifiers"), os = notes(p.outputCommitments, "outputCommitments"), capacity = selectTransactCapacity(ns.length, os.length);
|
|
4428
4848
|
const sources = normalizeSources(p.sources, ns.length, capacity), deliveries = dense(cs, "deliveries").map((v) => normalizeDelivery(v));
|
|
4429
4849
|
if (deliveries.length !== os.length) throw new Error("deliveries count mismatch");
|
|
4430
|
-
const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = (0,
|
|
4850
|
+
const withdrawalAmount = uint(p.withdrawalAmount, 128, "withdrawalAmount"), withdrawalAddress = (0, import_ethers7.getAddress)(p.withdrawalAddress), f = normalizeFunding(funding);
|
|
4431
4851
|
if (withdrawalAmount === 0n !== (BigInt(withdrawalAddress) === 0n) || os.length === 0 && withdrawalAmount === 0n)
|
|
4432
4852
|
throw new Error("invalid withdrawal");
|
|
4433
4853
|
if (ns.length === 0 && (f.amount === 0n || withdrawalAmount !== 0n))
|
|
@@ -4483,7 +4903,7 @@ function transactPublicInputs(c, p, cs, f = {}) {
|
|
|
4483
4903
|
}
|
|
4484
4904
|
function encodeTransactTypedData(c, p, deliveries, f = {}) {
|
|
4485
4905
|
const r = normalizeTransactRequest(c, p, deliveries, f);
|
|
4486
|
-
return (0,
|
|
4906
|
+
return (0, import_core6.walletAuthorizationTypedData)({
|
|
4487
4907
|
context: { chainId: r.chainId, protocolAddress: BigInt(r.protocolAddress) },
|
|
4488
4908
|
operation: "transact",
|
|
4489
4909
|
capacity: r.capacity,
|
|
@@ -4507,24 +4927,24 @@ function transactFundingRequestHash(proof, p, cs) {
|
|
|
4507
4927
|
withdrawalAmount: p.withdrawalAmount,
|
|
4508
4928
|
deadline: p.deadline
|
|
4509
4929
|
};
|
|
4510
|
-
return p.sources.length > 1 ? (0,
|
|
4511
|
-
|
|
4930
|
+
return p.sources.length > 1 ? (0, import_ethers7.keccak256)(
|
|
4931
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
4512
4932
|
[{ type: "bytes32" }, { type: "bytes32" }, crossTuple, { type: "bytes32" }].map(
|
|
4513
|
-
(parameter) =>
|
|
4933
|
+
(parameter) => import_ethers7.ParamType.from(parameter)
|
|
4514
4934
|
),
|
|
4515
4935
|
[
|
|
4516
|
-
(0,
|
|
4517
|
-
(0,
|
|
4936
|
+
(0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiCrossTreeTransact")),
|
|
4937
|
+
(0, import_ethers7.keccak256)(proof),
|
|
4518
4938
|
p,
|
|
4519
4939
|
deliveriesHash(cs)
|
|
4520
4940
|
]
|
|
4521
4941
|
)
|
|
4522
|
-
) : (0,
|
|
4523
|
-
|
|
4942
|
+
) : (0, import_ethers7.keccak256)(
|
|
4943
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
4524
4944
|
[{ type: "bytes32" }, singleTuple, { type: "bytes32" }].map(
|
|
4525
|
-
(parameter) =>
|
|
4945
|
+
(parameter) => import_ethers7.ParamType.from(parameter)
|
|
4526
4946
|
),
|
|
4527
|
-
[(0,
|
|
4947
|
+
[(0, import_ethers7.keccak256)(proof), single, deliveriesHash(cs)]
|
|
4528
4948
|
)
|
|
4529
4949
|
);
|
|
4530
4950
|
}
|
|
@@ -4564,7 +4984,7 @@ function buildTransactCalldata(p) {
|
|
|
4564
4984
|
const abi = invisiProtocolAbi.filter(
|
|
4565
4985
|
(item) => item.type === "function" && item.name === "transact" && item.inputs.length === 2 && item.inputs[1]?.type === "tuple"
|
|
4566
4986
|
);
|
|
4567
|
-
const data = new
|
|
4987
|
+
const data = new import_ethers7.Interface(abi).encodeFunctionData("transact", [p.proof, request]);
|
|
4568
4988
|
return { data, capacity: r.capacity, approveAmount: r.depositAmount };
|
|
4569
4989
|
}
|
|
4570
4990
|
function buildTransactAggregateCalldata(p) {
|
|
@@ -4581,7 +5001,7 @@ function buildTransactAggregateCalldata(p) {
|
|
|
4581
5001
|
validateFundingSubmission(r.funding, p.caller, p.context.now);
|
|
4582
5002
|
}
|
|
4583
5003
|
return {
|
|
4584
|
-
data: new
|
|
5004
|
+
data: new import_ethers7.Interface(
|
|
4585
5005
|
invisiProtocolAbi.filter(
|
|
4586
5006
|
(item) => item.type === "function" && item.name === "transact" && item.inputs[1]?.type === "tuple[]"
|
|
4587
5007
|
)
|
|
@@ -4591,7 +5011,7 @@ function buildTransactAggregateCalldata(p) {
|
|
|
4591
5011
|
}
|
|
4592
5012
|
async function validateShieldRequest(p) {
|
|
4593
5013
|
normalizeContext(p.context);
|
|
4594
|
-
if ((0,
|
|
5014
|
+
if ((0, import_ethers7.getAddress)(p.params.token) !== (0, import_ethers7.getAddress)(p.context.tokenAddress))
|
|
4595
5015
|
throw new Error("request token mismatch");
|
|
4596
5016
|
known(p.params, ["token", "outputCommitments", "deadline"]);
|
|
4597
5017
|
checkDeadline(p.context, p.params.deadline);
|
|
@@ -4605,7 +5025,7 @@ async function validateShieldRequest(p) {
|
|
|
4605
5025
|
if (o.amount === 0n) throw new Error("amount must be positive");
|
|
4606
5026
|
field(o.identity);
|
|
4607
5027
|
normalizeDelivery(cs[i]);
|
|
4608
|
-
if (await (0,
|
|
5028
|
+
if (await (0, import_core6.computeNoteCommitment)(
|
|
4609
5029
|
p.context.chainId,
|
|
4610
5030
|
o.identity,
|
|
4611
5031
|
BigInt(p.context.tokenAddress),
|
|
@@ -4618,22 +5038,22 @@ async function validateShieldRequest(p) {
|
|
|
4618
5038
|
return f;
|
|
4619
5039
|
}
|
|
4620
5040
|
function shieldFundingRequestHash(params, outputs, cs) {
|
|
4621
|
-
const outputHash = (0,
|
|
4622
|
-
|
|
4623
|
-
["(bytes32 identity,uint256 amount)[]"].map((parameter) =>
|
|
5041
|
+
const outputHash = (0, import_ethers7.keccak256)(
|
|
5042
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
5043
|
+
["(bytes32 identity,uint256 amount)[]"].map((parameter) => import_ethers7.ParamType.from(parameter)),
|
|
4624
5044
|
[outputs]
|
|
4625
5045
|
)
|
|
4626
5046
|
);
|
|
4627
|
-
return (0,
|
|
4628
|
-
|
|
5047
|
+
return (0, import_ethers7.keccak256)(
|
|
5048
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
4629
5049
|
[
|
|
4630
5050
|
"bytes32",
|
|
4631
5051
|
"(address token,bytes32[] outputCommitments,uint256 deadline)",
|
|
4632
5052
|
"bytes32",
|
|
4633
5053
|
"bytes32"
|
|
4634
|
-
].map((parameter) =>
|
|
5054
|
+
].map((parameter) => import_ethers7.ParamType.from(parameter)),
|
|
4635
5055
|
[
|
|
4636
|
-
(0,
|
|
5056
|
+
(0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiShield")),
|
|
4637
5057
|
params,
|
|
4638
5058
|
outputHash,
|
|
4639
5059
|
deliveriesHash(cs)
|
|
@@ -4660,7 +5080,7 @@ async function buildShieldCalldata(p) {
|
|
|
4660
5080
|
const f = await validateShieldRequest(p);
|
|
4661
5081
|
validateFundingSubmission(f, p.caller, p.context.now);
|
|
4662
5082
|
return {
|
|
4663
|
-
data: new
|
|
5083
|
+
data: new import_ethers7.Interface(invisiProtocolAbi).encodeFunctionData("shield", [
|
|
4664
5084
|
p.params,
|
|
4665
5085
|
p.outputs,
|
|
4666
5086
|
p.deliveries,
|
|
@@ -4671,7 +5091,7 @@ async function buildShieldCalldata(p) {
|
|
|
4671
5091
|
}
|
|
4672
5092
|
function transactUserPublicInputs(c, p, cs, f = {}) {
|
|
4673
5093
|
const words = transactPublicInputs(c, p, cs, f), digest = BigInt(
|
|
4674
|
-
((typed) =>
|
|
5094
|
+
((typed) => import_ethers7.TypedDataEncoder.hash(
|
|
4675
5095
|
typed.domain,
|
|
4676
5096
|
Object.fromEntries(
|
|
4677
5097
|
Object.entries(typed.types).map(([name, fields]) => [
|
|
@@ -4690,11 +5110,11 @@ function aggregateMemberRequestHash(c, r) {
|
|
|
4690
5110
|
r.params.outputCommitments.length
|
|
4691
5111
|
);
|
|
4692
5112
|
if (capacity !== 14) throw new Error("aggregate supports only capacity 14");
|
|
4693
|
-
return (0,
|
|
4694
|
-
|
|
4695
|
-
["bytes32", "uint256", "bytes32[]"].map((parameter) =>
|
|
5113
|
+
return (0, import_ethers7.keccak256)(
|
|
5114
|
+
import_ethers7.AbiCoder.defaultAbiCoder().encode(
|
|
5115
|
+
["bytes32", "uint256", "bytes32[]"].map((parameter) => import_ethers7.ParamType.from(parameter)),
|
|
4696
5116
|
[
|
|
4697
|
-
(0,
|
|
5117
|
+
(0, import_ethers7.keccak256)(new TextEncoder().encode("InvisiAtomicBatchMemberV1")),
|
|
4698
5118
|
BigInt(capacity),
|
|
4699
5119
|
transactPublicInputs(c, r.params, r.deliveries, r.funding)
|
|
4700
5120
|
]
|
|
@@ -4727,6 +5147,240 @@ function encodeAggregateFundingTypedData(c, r) {
|
|
|
4727
5147
|
};
|
|
4728
5148
|
}
|
|
4729
5149
|
|
|
5150
|
+
// src/Protocol.ts
|
|
5151
|
+
var import_ethers9 = require("ethers");
|
|
5152
|
+
var import_rpc = require("@invisi-labs/rpc");
|
|
5153
|
+
|
|
5154
|
+
// src/TokenProtocol.ts
|
|
5155
|
+
var import_ethers8 = require("ethers");
|
|
5156
|
+
var import_core7 = require("@invisi-labs/core");
|
|
5157
|
+
var TokenProtocol = class {
|
|
5158
|
+
context;
|
|
5159
|
+
expectedRuntimeCodeHash;
|
|
5160
|
+
constructor(context, options = {}) {
|
|
5161
|
+
const normalized = normalizeContext(context);
|
|
5162
|
+
if (BigInt(normalized.protocolAddress) === 0n || BigInt(normalized.tokenAddress) === 0n) {
|
|
5163
|
+
throw new Error("deployment addresses must be nonzero");
|
|
5164
|
+
}
|
|
5165
|
+
if (options.expectedRuntimeCodeHash && !/^0x[0-9a-fA-F]{64}$/.test(options.expectedRuntimeCodeHash)) {
|
|
5166
|
+
throw new Error("invalid runtime code hash");
|
|
5167
|
+
}
|
|
5168
|
+
this.expectedRuntimeCodeHash = options.expectedRuntimeCodeHash?.toLowerCase();
|
|
5169
|
+
this.context = Object.freeze(normalized);
|
|
5170
|
+
Object.freeze(this);
|
|
5171
|
+
}
|
|
5172
|
+
async validateDeployment(reader, options = {}) {
|
|
5173
|
+
if ((options.requireRuntimeProfile ?? true) && !this.expectedRuntimeCodeHash) {
|
|
5174
|
+
throw new import_core7.MissingCapabilityError("trusted deployment profile");
|
|
5175
|
+
}
|
|
5176
|
+
if (await reader.getChainId() !== this.context.chainId) {
|
|
5177
|
+
throw new Error("deployment chain mismatch");
|
|
5178
|
+
}
|
|
5179
|
+
const code = await reader.getCode(this.context.protocolAddress);
|
|
5180
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || this.expectedRuntimeCodeHash && (0, import_ethers8.keccak256)(code) !== this.expectedRuntimeCodeHash) {
|
|
5181
|
+
throw new Error("deployment runtime code profile mismatch");
|
|
5182
|
+
}
|
|
5183
|
+
const tokenCode = await reader.getCode(this.context.tokenAddress);
|
|
5184
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(tokenCode)) {
|
|
5185
|
+
throw new Error("token address must have contract code");
|
|
5186
|
+
}
|
|
5187
|
+
}
|
|
5188
|
+
transact(request) {
|
|
5189
|
+
return {
|
|
5190
|
+
to: this.context.protocolAddress,
|
|
5191
|
+
value: 0n,
|
|
5192
|
+
...buildTransactCalldata({ ...request, context: this.context })
|
|
5193
|
+
};
|
|
5194
|
+
}
|
|
5195
|
+
aggregate(request) {
|
|
5196
|
+
return {
|
|
5197
|
+
to: this.context.protocolAddress,
|
|
5198
|
+
value: 0n,
|
|
5199
|
+
...buildTransactAggregateCalldata({ ...request, context: this.context })
|
|
5200
|
+
};
|
|
5201
|
+
}
|
|
5202
|
+
async shield(request) {
|
|
5203
|
+
return {
|
|
5204
|
+
to: this.context.protocolAddress,
|
|
5205
|
+
value: 0n,
|
|
5206
|
+
...await buildShieldCalldata({ ...request, context: this.context })
|
|
5207
|
+
};
|
|
5208
|
+
}
|
|
5209
|
+
createCredit(request) {
|
|
5210
|
+
return {
|
|
5211
|
+
to: this.context.protocolAddress,
|
|
5212
|
+
value: 0n,
|
|
5213
|
+
...buildCreateCreditCalldata({ ...request, context: this.context })
|
|
5214
|
+
};
|
|
5215
|
+
}
|
|
5216
|
+
drawCredit(request) {
|
|
5217
|
+
return {
|
|
5218
|
+
to: this.context.protocolAddress,
|
|
5219
|
+
value: 0n,
|
|
5220
|
+
...buildCreditDrawCalldata({ ...request, context: this.context })
|
|
5221
|
+
};
|
|
5222
|
+
}
|
|
5223
|
+
cancelCredit(request) {
|
|
5224
|
+
return {
|
|
5225
|
+
to: this.context.protocolAddress,
|
|
5226
|
+
value: 0n,
|
|
5227
|
+
...buildCancelCreditCalldata({ ...request, context: this.context })
|
|
5228
|
+
};
|
|
5229
|
+
}
|
|
5230
|
+
topUpCredit(request) {
|
|
5231
|
+
return {
|
|
5232
|
+
to: this.context.protocolAddress,
|
|
5233
|
+
value: 0n,
|
|
5234
|
+
...buildTopUpCreditCalldata({ ...request, context: this.context })
|
|
5235
|
+
};
|
|
5236
|
+
}
|
|
5237
|
+
};
|
|
5238
|
+
|
|
5239
|
+
// src/Protocol.ts
|
|
5240
|
+
var Protocol = class _Protocol {
|
|
5241
|
+
deployment;
|
|
5242
|
+
context;
|
|
5243
|
+
constructor(options) {
|
|
5244
|
+
known(options, ["deployment"], "protocol options");
|
|
5245
|
+
this.deployment = (0, import_rpc.defineDeployment)(options.deployment);
|
|
5246
|
+
this.context = Object.freeze({
|
|
5247
|
+
chainId: this.deployment.chainId,
|
|
5248
|
+
protocolAddress: this.deployment.protocol.address
|
|
5249
|
+
});
|
|
5250
|
+
Object.freeze(this);
|
|
5251
|
+
}
|
|
5252
|
+
/** Load the selected deployment and verify its contract against Chain RPC before returning. */
|
|
5253
|
+
static async fromRpc(rpc, provider, options = {}) {
|
|
5254
|
+
const chainId = (await provider.getNetwork()).chainId;
|
|
5255
|
+
if (typeof chainId !== "bigint" || chainId <= 0n || chainId >= 1n << 64n)
|
|
5256
|
+
throw new Error("invalid protocol chainId");
|
|
5257
|
+
const deployment = await rpc.getDeployment(
|
|
5258
|
+
chainId,
|
|
5259
|
+
options.signal ? { signal: options.signal } : {}
|
|
5260
|
+
);
|
|
5261
|
+
const protocol = new _Protocol({ deployment });
|
|
5262
|
+
if (protocol.context.chainId !== chainId) throw new Error("RPC deployment chain mismatch");
|
|
5263
|
+
await protocol.validateDeployment(provider);
|
|
5264
|
+
return protocol;
|
|
5265
|
+
}
|
|
5266
|
+
async validateDeployment(connection) {
|
|
5267
|
+
const reader = "getNetwork" in connection ? {
|
|
5268
|
+
getChainId: async () => (await connection.getNetwork()).chainId,
|
|
5269
|
+
getCode: async (address) => await connection.getCode(address),
|
|
5270
|
+
getProtocolAddressRegistry: async (address) => (0, import_ethers9.getAddress)(
|
|
5271
|
+
await new import_ethers9.Contract(
|
|
5272
|
+
address,
|
|
5273
|
+
["function addressRegistry() view returns (address)"],
|
|
5274
|
+
connection
|
|
5275
|
+
).getFunction("addressRegistry")()
|
|
5276
|
+
),
|
|
5277
|
+
getProtocolVersion: async (address) => BigInt(
|
|
5278
|
+
await new import_ethers9.Contract(
|
|
5279
|
+
address,
|
|
5280
|
+
["function VERSION() view returns (uint256)"],
|
|
5281
|
+
connection
|
|
5282
|
+
).getFunction("VERSION")()
|
|
5283
|
+
)
|
|
5284
|
+
} : connection;
|
|
5285
|
+
if (await reader.getChainId() !== this.context.chainId)
|
|
5286
|
+
throw new Error("deployment chain mismatch");
|
|
5287
|
+
const code = await reader.getCode(this.context.protocolAddress);
|
|
5288
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(code) || (0, import_ethers9.keccak256)(code) !== this.deployment.protocol.runtimeCodeHash)
|
|
5289
|
+
throw new Error("protocol runtime code profile mismatch");
|
|
5290
|
+
if (reader.getProtocolVersion && await reader.getProtocolVersion(this.context.protocolAddress) !== 1n)
|
|
5291
|
+
throw new Error("unsupported onchain protocol version");
|
|
5292
|
+
const registry = this.deployment.registry;
|
|
5293
|
+
if (registry) {
|
|
5294
|
+
if (!reader.getProtocolAddressRegistry)
|
|
5295
|
+
throw new Error("registry binding reader capability is missing");
|
|
5296
|
+
if ((0, import_ethers9.getAddress)(
|
|
5297
|
+
await reader.getProtocolAddressRegistry(this.context.protocolAddress)
|
|
5298
|
+
) !== (0, import_ethers9.getAddress)(registry.address))
|
|
5299
|
+
throw new Error("protocol registry binding mismatch");
|
|
5300
|
+
const registryCode = await reader.getCode(registry.address);
|
|
5301
|
+
if (!/^0x(?:[0-9a-fA-F]{2})+$/.test(registryCode) || (0, import_ethers9.keccak256)(registryCode) !== registry.runtimeCodeHash)
|
|
5302
|
+
throw new Error("registry runtime code profile mismatch");
|
|
5303
|
+
}
|
|
5304
|
+
}
|
|
5305
|
+
aggregate(request) {
|
|
5306
|
+
return {
|
|
5307
|
+
to: this.context.protocolAddress,
|
|
5308
|
+
value: 0n,
|
|
5309
|
+
...buildTransactAggregateCalldata({ ...request, context: this.context })
|
|
5310
|
+
};
|
|
5311
|
+
}
|
|
5312
|
+
/** Build an operation context for one asset within this same deployment. */
|
|
5313
|
+
forToken(tokenAddress) {
|
|
5314
|
+
return new TokenProtocol(
|
|
5315
|
+
{ ...this.context, tokenAddress: (0, import_ethers9.getAddress)(tokenAddress) },
|
|
5316
|
+
{ expectedRuntimeCodeHash: this.deployment.protocol.runtimeCodeHash }
|
|
5317
|
+
);
|
|
5318
|
+
}
|
|
5319
|
+
};
|
|
5320
|
+
|
|
5321
|
+
// src/verify.ts
|
|
5322
|
+
var import_core8 = require("@invisi-labs/core");
|
|
5323
|
+
async function verifyNoteCommitment(params) {
|
|
5324
|
+
const expected = await (0, import_core8.computeNoteCommitment)(
|
|
5325
|
+
params.chainId,
|
|
5326
|
+
await (0, import_core8.computeNoteIdentity)(BigInt(params.walletIdentity), BigInt(params.nonce)),
|
|
5327
|
+
BigInt(params.tokenAddress),
|
|
5328
|
+
params.amount
|
|
5329
|
+
);
|
|
5330
|
+
return BigInt(expected) === BigInt(params.noteCommitment);
|
|
5331
|
+
}
|
|
5332
|
+
async function verifyCreditCommitment(params) {
|
|
5333
|
+
if (params.creditSharedKey <= 0n || params.creditSharedKey >= import_core8.FIELD_MODULUS)
|
|
5334
|
+
throw new RangeError("creditSharedKey must be a nonzero canonical Field");
|
|
5335
|
+
const expected = await (0, import_core8.computeCreditCommitment)(
|
|
5336
|
+
params.chainId,
|
|
5337
|
+
params.spenderWalletIdentity,
|
|
5338
|
+
params.ownerWalletIdentity,
|
|
5339
|
+
BigInt(params.spenderPayout),
|
|
5340
|
+
BigInt(params.ownerPayout),
|
|
5341
|
+
BigInt(params.tokenAddress),
|
|
5342
|
+
params.amount,
|
|
5343
|
+
params.nonce,
|
|
5344
|
+
params.expiry,
|
|
5345
|
+
await (0, import_core8.computeCreditSharedKeyHash)(params.creditSharedKey)
|
|
5346
|
+
);
|
|
5347
|
+
return BigInt(expected) === BigInt(params.creditCommitment);
|
|
5348
|
+
}
|
|
5349
|
+
|
|
5350
|
+
// src/withdrawal.ts
|
|
5351
|
+
var import_core9 = require("@invisi-labs/core");
|
|
5352
|
+
async function buildWithdrawalCalldata(p) {
|
|
5353
|
+
const r = normalizeTransactRequest(p.context, p.params, [], p.funding);
|
|
5354
|
+
if (r.outputCount !== 0 || r.depositAmount !== 0n || p.sourceNotes.length === 0 || p.sourceNotes.length !== r.inputCount) {
|
|
5355
|
+
throw new Error("full withdrawal requires inputs, no private outputs and no funding");
|
|
5356
|
+
}
|
|
5357
|
+
const walletIdentity = BigInt(p.sourceNotes[0].walletIdentity);
|
|
5358
|
+
let total = 0n;
|
|
5359
|
+
for (const [index, note] of p.sourceNotes.entries()) {
|
|
5360
|
+
if (note.chainId !== p.context.chainId || note.protocolAddress !== BigInt(p.context.protocolAddress))
|
|
5361
|
+
throw new Error("source note context mismatch");
|
|
5362
|
+
if (BigInt(note.walletIdentity) !== walletIdentity || note.tokenAddress !== BigInt(p.context.tokenAddress) || note.amount <= 0n)
|
|
5363
|
+
throw new Error("source note wallet/token/amount mismatch");
|
|
5364
|
+
const commitment = await (0, import_core9.computeNoteCommitment)(
|
|
5365
|
+
note.chainId,
|
|
5366
|
+
await (0, import_core9.computeNoteIdentity)(walletIdentity, note.nonce),
|
|
5367
|
+
note.tokenAddress,
|
|
5368
|
+
note.amount
|
|
5369
|
+
);
|
|
5370
|
+
const nullifier = await (0, import_core9.computeNoteNullifier)(note.chainId, note.nonce, commitment);
|
|
5371
|
+
if (nullifier.toLowerCase() !== r.nullifiers[index].toLowerCase())
|
|
5372
|
+
throw new Error("source note nullifier mismatch");
|
|
5373
|
+
total += note.amount;
|
|
5374
|
+
}
|
|
5375
|
+
if (r.withdrawalAmount !== total)
|
|
5376
|
+
throw new Error("withdrawal must equal the full input balance");
|
|
5377
|
+
return buildTransactCalldata({ ...p, deliveries: [] });
|
|
5378
|
+
}
|
|
5379
|
+
|
|
5380
|
+
// src/witness.ts
|
|
5381
|
+
var import_core10 = require("@invisi-labs/core");
|
|
5382
|
+
var import_prover = require("@invisi-labs/prover");
|
|
5383
|
+
|
|
4730
5384
|
// src/witness-layouts.json
|
|
4731
5385
|
var witness_layouts_default = {
|
|
4732
5386
|
transact_user_slots14: {
|
|
@@ -5718,301 +6372,85 @@ var witness_layouts_default = {
|
|
|
5718
6372
|
publicInputCount: 732,
|
|
5719
6373
|
public: [
|
|
5720
6374
|
{
|
|
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",
|
|
6375
|
+
name: "chain_id",
|
|
5958
6376
|
count: 1,
|
|
5959
6377
|
array: false
|
|
5960
6378
|
},
|
|
5961
6379
|
{
|
|
5962
|
-
name: "
|
|
6380
|
+
name: "protocol_address",
|
|
5963
6381
|
count: 1,
|
|
5964
6382
|
array: false
|
|
5965
6383
|
},
|
|
5966
6384
|
{
|
|
5967
|
-
name: "
|
|
6385
|
+
name: "token_address",
|
|
5968
6386
|
count: 1,
|
|
5969
6387
|
array: false
|
|
5970
6388
|
},
|
|
5971
6389
|
{
|
|
5972
|
-
name: "
|
|
6390
|
+
name: "spender_address",
|
|
5973
6391
|
count: 1,
|
|
5974
6392
|
array: false
|
|
5975
6393
|
},
|
|
5976
6394
|
{
|
|
5977
|
-
name: "
|
|
6395
|
+
name: "actual_count",
|
|
5978
6396
|
count: 1,
|
|
5979
6397
|
array: false
|
|
5980
6398
|
},
|
|
5981
6399
|
{
|
|
5982
|
-
name: "
|
|
6400
|
+
name: "source_count",
|
|
5983
6401
|
count: 1,
|
|
5984
6402
|
array: false
|
|
5985
6403
|
},
|
|
5986
6404
|
{
|
|
5987
|
-
name: "
|
|
5988
|
-
count:
|
|
5989
|
-
array:
|
|
6405
|
+
name: "tree_ids",
|
|
6406
|
+
count: 120,
|
|
6407
|
+
array: true
|
|
5990
6408
|
},
|
|
5991
6409
|
{
|
|
5992
|
-
name: "
|
|
5993
|
-
count:
|
|
5994
|
-
array:
|
|
6410
|
+
name: "roots",
|
|
6411
|
+
count: 120,
|
|
6412
|
+
array: true
|
|
5995
6413
|
},
|
|
5996
6414
|
{
|
|
5997
|
-
name: "
|
|
6415
|
+
name: "nullifiers",
|
|
6416
|
+
count: 120,
|
|
6417
|
+
array: true
|
|
6418
|
+
},
|
|
6419
|
+
{
|
|
6420
|
+
name: "remainder_commitments",
|
|
6421
|
+
count: 120,
|
|
6422
|
+
array: true
|
|
6423
|
+
},
|
|
6424
|
+
{
|
|
6425
|
+
name: "expiries",
|
|
6426
|
+
count: 120,
|
|
6427
|
+
array: true
|
|
6428
|
+
},
|
|
6429
|
+
{
|
|
6430
|
+
name: "total_amount",
|
|
5998
6431
|
count: 1,
|
|
5999
6432
|
array: false
|
|
6000
6433
|
},
|
|
6001
6434
|
{
|
|
6002
|
-
name: "
|
|
6435
|
+
name: "deadline",
|
|
6003
6436
|
count: 1,
|
|
6004
6437
|
array: false
|
|
6005
6438
|
},
|
|
6006
6439
|
{
|
|
6007
|
-
name: "
|
|
6440
|
+
name: "delivery_hash_high",
|
|
6008
6441
|
count: 1,
|
|
6009
6442
|
array: false
|
|
6010
6443
|
},
|
|
6011
6444
|
{
|
|
6012
|
-
name: "
|
|
6445
|
+
name: "delivery_hash_low",
|
|
6013
6446
|
count: 1,
|
|
6014
6447
|
array: false
|
|
6015
6448
|
},
|
|
6449
|
+
{
|
|
6450
|
+
name: "recovery_amounts",
|
|
6451
|
+
count: 120,
|
|
6452
|
+
array: true
|
|
6453
|
+
},
|
|
6016
6454
|
{
|
|
6017
6455
|
name: "auth_digest_high",
|
|
6018
6456
|
count: 1,
|
|
@@ -6025,1089 +6463,666 @@ var witness_layouts_default = {
|
|
|
6025
6463
|
}
|
|
6026
6464
|
],
|
|
6027
6465
|
private: [
|
|
6466
|
+
"public_key_x",
|
|
6467
|
+
"public_key_y",
|
|
6468
|
+
"signature",
|
|
6469
|
+
"spender_wallet_identity",
|
|
6470
|
+
"owner_payouts",
|
|
6471
|
+
"owner_wallet_identities",
|
|
6028
6472
|
"input_amounts",
|
|
6029
6473
|
"input_nonces",
|
|
6474
|
+
"credit_shared_keys",
|
|
6030
6475
|
"leaf_indices",
|
|
6031
6476
|
"merkle_paths",
|
|
6032
6477
|
"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"
|
|
6478
|
+
"draw_amounts"
|
|
6048
6479
|
]
|
|
6049
6480
|
},
|
|
6050
|
-
|
|
6051
|
-
artifactSha256: "
|
|
6481
|
+
credit_cancel: {
|
|
6482
|
+
artifactSha256: "ff278a04f22d2886c9f27f7785a0b8fc317dd242fd4aa9d0d9398d18b7513daf",
|
|
6052
6483
|
keys: {
|
|
6053
|
-
evm: "
|
|
6484
|
+
evm: "1f8a3c20cb081d6a90962556da3124919cc4e5675e59ad31562af39299da02fb"
|
|
6054
6485
|
},
|
|
6055
|
-
publicInputCount:
|
|
6486
|
+
publicInputCount: 11,
|
|
6056
6487
|
public: [
|
|
6057
6488
|
{
|
|
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}`,
|
|
6489
|
+
name: "chain_id",
|
|
6490
|
+
count: 1,
|
|
6491
|
+
array: false
|
|
6492
|
+
},
|
|
6255
6493
|
{
|
|
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)
|
|
6494
|
+
name: "protocol_address",
|
|
6495
|
+
count: 1,
|
|
6496
|
+
array: false
|
|
6287
6497
|
},
|
|
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
6498
|
{
|
|
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]
|
|
6499
|
+
name: "token_address",
|
|
6500
|
+
count: 1,
|
|
6501
|
+
array: false
|
|
6390
6502
|
},
|
|
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
6503
|
{
|
|
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)
|
|
6504
|
+
name: "owner_address",
|
|
6505
|
+
count: 1,
|
|
6506
|
+
array: false
|
|
6460
6507
|
},
|
|
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
6508
|
{
|
|
6491
|
-
|
|
6492
|
-
|
|
6493
|
-
|
|
6494
|
-
|
|
6495
|
-
|
|
6509
|
+
name: "tree_id",
|
|
6510
|
+
count: 1,
|
|
6511
|
+
array: false
|
|
6512
|
+
},
|
|
6513
|
+
{
|
|
6514
|
+
name: "merkle_root",
|
|
6515
|
+
count: 1,
|
|
6516
|
+
array: false
|
|
6517
|
+
},
|
|
6518
|
+
{
|
|
6519
|
+
name: "nullifier",
|
|
6520
|
+
count: 1,
|
|
6521
|
+
array: false
|
|
6522
|
+
},
|
|
6523
|
+
{
|
|
6524
|
+
name: "amount",
|
|
6525
|
+
count: 1,
|
|
6526
|
+
array: false
|
|
6496
6527
|
},
|
|
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)
|
|
6528
|
+
{
|
|
6529
|
+
name: "deadline",
|
|
6530
|
+
count: 1,
|
|
6531
|
+
array: false
|
|
6586
6532
|
},
|
|
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
|
-
);
|
|
6533
|
+
{
|
|
6534
|
+
name: "auth_digest_high",
|
|
6535
|
+
count: 1,
|
|
6536
|
+
array: false
|
|
6537
|
+
},
|
|
6538
|
+
{
|
|
6539
|
+
name: "auth_digest_low",
|
|
6540
|
+
count: 1,
|
|
6541
|
+
array: false
|
|
6542
|
+
}
|
|
6543
|
+
],
|
|
6544
|
+
private: [
|
|
6545
|
+
"public_key_x",
|
|
6546
|
+
"public_key_y",
|
|
6547
|
+
"signature",
|
|
6548
|
+
"spender_payout",
|
|
6549
|
+
"spender_wallet_identity",
|
|
6550
|
+
"owner_wallet_identity",
|
|
6551
|
+
"input_nonce",
|
|
6552
|
+
"expiry",
|
|
6553
|
+
"credit_shared_key",
|
|
6554
|
+
"leaf_index",
|
|
6555
|
+
"merkle_path"
|
|
6556
|
+
]
|
|
6557
|
+
},
|
|
6558
|
+
credit_top_up: {
|
|
6559
|
+
artifactSha256: "fbe662363d9814983f7940f74369117cd6c84783945fbf527b0ed48d011b58a4",
|
|
6560
|
+
keys: {
|
|
6561
|
+
evm: "44436f31414497a708355426da051ee48ba63fdebcb6cfd72347c37c34c98c50"
|
|
6562
|
+
},
|
|
6563
|
+
publicInputCount: 50,
|
|
6564
|
+
public: [
|
|
6565
|
+
{
|
|
6566
|
+
name: "chain_id",
|
|
6567
|
+
count: 1,
|
|
6568
|
+
array: false
|
|
6569
|
+
},
|
|
6570
|
+
{
|
|
6571
|
+
name: "protocol_address",
|
|
6572
|
+
count: 1,
|
|
6573
|
+
array: false
|
|
6574
|
+
},
|
|
6575
|
+
{
|
|
6576
|
+
name: "token_address",
|
|
6577
|
+
count: 1,
|
|
6578
|
+
array: false
|
|
6579
|
+
},
|
|
6580
|
+
{
|
|
6581
|
+
name: "owner_address",
|
|
6582
|
+
count: 1,
|
|
6583
|
+
array: false
|
|
6584
|
+
},
|
|
6585
|
+
{
|
|
6586
|
+
name: "actual_count",
|
|
6587
|
+
count: 1,
|
|
6588
|
+
array: false
|
|
6589
|
+
},
|
|
6590
|
+
{
|
|
6591
|
+
name: "source_count",
|
|
6592
|
+
count: 1,
|
|
6593
|
+
array: false
|
|
6594
|
+
},
|
|
6595
|
+
{
|
|
6596
|
+
name: "input_tree_ids",
|
|
6597
|
+
count: 10,
|
|
6598
|
+
array: true
|
|
6599
|
+
},
|
|
6600
|
+
{
|
|
6601
|
+
name: "merkle_roots",
|
|
6602
|
+
count: 10,
|
|
6603
|
+
array: true
|
|
6604
|
+
},
|
|
6605
|
+
{
|
|
6606
|
+
name: "nullifiers",
|
|
6607
|
+
count: 10,
|
|
6608
|
+
array: true
|
|
6609
|
+
},
|
|
6610
|
+
{
|
|
6611
|
+
name: "credit_commitment",
|
|
6612
|
+
count: 1,
|
|
6613
|
+
array: false
|
|
6614
|
+
},
|
|
6615
|
+
{
|
|
6616
|
+
name: "change_commitment",
|
|
6617
|
+
count: 1,
|
|
6618
|
+
array: false
|
|
6619
|
+
},
|
|
6620
|
+
{
|
|
6621
|
+
name: "delivery_hash_high",
|
|
6622
|
+
count: 1,
|
|
6623
|
+
array: false
|
|
6624
|
+
},
|
|
6625
|
+
{
|
|
6626
|
+
name: "delivery_hash_low",
|
|
6627
|
+
count: 1,
|
|
6628
|
+
array: false
|
|
6629
|
+
},
|
|
6630
|
+
{
|
|
6631
|
+
name: "expiry",
|
|
6632
|
+
count: 1,
|
|
6633
|
+
array: false
|
|
6634
|
+
},
|
|
6635
|
+
{
|
|
6636
|
+
name: "deadline",
|
|
6637
|
+
count: 1,
|
|
6638
|
+
array: false
|
|
6639
|
+
},
|
|
6640
|
+
{
|
|
6641
|
+
name: "deposit_amount",
|
|
6642
|
+
count: 1,
|
|
6643
|
+
array: false
|
|
6644
|
+
},
|
|
6645
|
+
{
|
|
6646
|
+
name: "deposit_payer",
|
|
6647
|
+
count: 1,
|
|
6648
|
+
array: false
|
|
6649
|
+
},
|
|
6650
|
+
{
|
|
6651
|
+
name: "credit_tree_id",
|
|
6652
|
+
count: 1,
|
|
6653
|
+
array: false
|
|
6654
|
+
},
|
|
6655
|
+
{
|
|
6656
|
+
name: "credit_merkle_root",
|
|
6657
|
+
count: 1,
|
|
6658
|
+
array: false
|
|
6659
|
+
},
|
|
6660
|
+
{
|
|
6661
|
+
name: "credit_nullifier",
|
|
6662
|
+
count: 1,
|
|
6663
|
+
array: false
|
|
6664
|
+
},
|
|
6665
|
+
{
|
|
6666
|
+
name: "previous_expiry",
|
|
6667
|
+
count: 1,
|
|
6668
|
+
array: false
|
|
6669
|
+
},
|
|
6670
|
+
{
|
|
6671
|
+
name: "auth_digest_high",
|
|
6672
|
+
count: 1,
|
|
6673
|
+
array: false
|
|
6674
|
+
},
|
|
6675
|
+
{
|
|
6676
|
+
name: "auth_digest_low",
|
|
6677
|
+
count: 1,
|
|
6678
|
+
array: false
|
|
6818
6679
|
}
|
|
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
|
-
};
|
|
6680
|
+
],
|
|
6681
|
+
private: [
|
|
6682
|
+
"input_amounts",
|
|
6683
|
+
"input_nonces",
|
|
6684
|
+
"leaf_indices",
|
|
6685
|
+
"merkle_paths",
|
|
6686
|
+
"input_source_indices",
|
|
6687
|
+
"public_key_x",
|
|
6688
|
+
"public_key_y",
|
|
6689
|
+
"signature",
|
|
6690
|
+
"spender_payout",
|
|
6691
|
+
"spender_wallet_identity",
|
|
6692
|
+
"owner_wallet_identity",
|
|
6693
|
+
"credit_amount",
|
|
6694
|
+
"credit_nonce",
|
|
6695
|
+
"credit_shared_key",
|
|
6696
|
+
"change_amount",
|
|
6697
|
+
"change_nonce",
|
|
6698
|
+
"previous_credit_amount",
|
|
6699
|
+
"previous_credit_nonce",
|
|
6700
|
+
"previous_credit_leaf_index",
|
|
6701
|
+
"previous_credit_merkle_path"
|
|
6702
|
+
]
|
|
6945
6703
|
}
|
|
6946
|
-
|
|
6947
|
-
|
|
6948
|
-
|
|
6949
|
-
|
|
6950
|
-
|
|
6951
|
-
|
|
6704
|
+
};
|
|
6705
|
+
|
|
6706
|
+
// src/witness.ts
|
|
6707
|
+
var pad2 = (values, count, zero) => {
|
|
6708
|
+
if (values.length > count) throw new Error("witness capacity exceeded");
|
|
6709
|
+
return [...values, ...Array.from({ length: count - values.length }, zero)];
|
|
6710
|
+
};
|
|
6711
|
+
var zeros = () => Array(16).fill(0n);
|
|
6712
|
+
var zeroAuthority = () => ({
|
|
6713
|
+
public_key_x: Array(32).fill(0),
|
|
6714
|
+
public_key_y: Array(32).fill(0),
|
|
6715
|
+
signature: Array(64).fill(0)
|
|
6716
|
+
});
|
|
6717
|
+
function check2(ok, message) {
|
|
6718
|
+
if (!ok) throw new Error(message);
|
|
6719
|
+
}
|
|
6720
|
+
function provingRequest(circuitName, privateInputs, expectedPublicInputs, target = "evm") {
|
|
6721
|
+
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
6722
|
+
check2(typeof key === "string", "unpublished proof target");
|
|
6723
|
+
check2(
|
|
6724
|
+
expectedPublicInputs.length === schema.publicInputCount,
|
|
6725
|
+
"public input order/width mismatch"
|
|
6726
|
+
);
|
|
6727
|
+
check2(
|
|
6728
|
+
Object.keys(privateInputs).length === schema.private.length && schema.private.every((name) => Object.hasOwn(privateInputs, name)),
|
|
6729
|
+
"private witness schema mismatch"
|
|
6730
|
+
);
|
|
6731
|
+
let offset = 0;
|
|
6732
|
+
const publicInputs = {};
|
|
6733
|
+
for (const entry of schema.public) {
|
|
6734
|
+
const values = expectedPublicInputs.slice(offset, offset + entry.count).map((value) => {
|
|
6735
|
+
const n = BigInt(value);
|
|
6736
|
+
check2(n >= 0n && n < FIELD_MODULUS, "noncanonical public input");
|
|
6737
|
+
return n;
|
|
6738
|
+
});
|
|
6739
|
+
publicInputs[entry.name] = entry.array ? values : values[0];
|
|
6740
|
+
offset += entry.count;
|
|
6952
6741
|
}
|
|
6953
|
-
|
|
6954
|
-
|
|
6955
|
-
|
|
6956
|
-
|
|
6957
|
-
|
|
6958
|
-
|
|
6742
|
+
check2(offset === expectedPublicInputs.length, "public input layout mismatch");
|
|
6743
|
+
return {
|
|
6744
|
+
circuitName,
|
|
6745
|
+
target,
|
|
6746
|
+
artifactSha256: schema.artifactSha256,
|
|
6747
|
+
vkSha256: key,
|
|
6748
|
+
expectedPublicInputs: [...expectedPublicInputs],
|
|
6749
|
+
witness: new import_prover.LocalWitness({ ...privateInputs, ...publicInputs })
|
|
6750
|
+
};
|
|
6751
|
+
}
|
|
6752
|
+
var WitnessBuilder = class {
|
|
6753
|
+
#protocol;
|
|
6754
|
+
constructor(protocol) {
|
|
6755
|
+
this.#protocol = protocol;
|
|
6959
6756
|
}
|
|
6960
|
-
|
|
6757
|
+
static statement(circuitName, expectedPublicInputs, target = "evm") {
|
|
6758
|
+
const schema = witness_layouts_default[circuitName], key = schema.keys[target];
|
|
6759
|
+
check2(
|
|
6760
|
+
typeof key === "string" && expectedPublicInputs.length === schema.publicInputCount,
|
|
6761
|
+
"unpublished target or statement width mismatch"
|
|
6762
|
+
);
|
|
6961
6763
|
return {
|
|
6962
|
-
|
|
6963
|
-
|
|
6964
|
-
|
|
6764
|
+
circuitName,
|
|
6765
|
+
target,
|
|
6766
|
+
artifactSha256: schema.artifactSha256,
|
|
6767
|
+
vkSha256: key,
|
|
6768
|
+
expectedPublicInputs: [...expectedPublicInputs]
|
|
6965
6769
|
};
|
|
6966
6770
|
}
|
|
6967
|
-
|
|
6968
|
-
|
|
6969
|
-
|
|
6970
|
-
|
|
6971
|
-
|
|
6972
|
-
|
|
6771
|
+
context(note) {
|
|
6772
|
+
const c = this.#protocol.context;
|
|
6773
|
+
check2(
|
|
6774
|
+
note.chainId === c.chainId && note.protocolAddress === BigInt(c.protocolAddress) && note.tokenAddress === BigInt(c.tokenAddress),
|
|
6775
|
+
"note context mismatch"
|
|
6776
|
+
);
|
|
6973
6777
|
}
|
|
6974
|
-
|
|
6975
|
-
|
|
6976
|
-
|
|
6977
|
-
|
|
6978
|
-
|
|
6778
|
+
async authority(operation, capacity, words, signed, identity) {
|
|
6779
|
+
check2(!!signed, "private wallet authorization required");
|
|
6780
|
+
const c = this.#protocol.context, request = {
|
|
6781
|
+
context: { chainId: c.chainId, protocolAddress: BigInt(c.protocolAddress) },
|
|
6782
|
+
operation,
|
|
6783
|
+
capacity,
|
|
6784
|
+
words: words.slice(0, -2).map(BigInt)
|
|
6979
6785
|
};
|
|
6786
|
+
check2(
|
|
6787
|
+
signed.walletIdentity === identity && signed.digest === (0, import_core10.computeWalletAuthorizationDigest)(request),
|
|
6788
|
+
"authorization statement mismatch"
|
|
6789
|
+
);
|
|
6790
|
+
const witness = signed.withWitness((value) => value);
|
|
6791
|
+
check2(
|
|
6792
|
+
await (0, import_core10.verifyWalletAuthorization)(
|
|
6793
|
+
identity,
|
|
6794
|
+
Uint8Array.from([4, ...witness.public_key_x, ...witness.public_key_y]),
|
|
6795
|
+
Uint8Array.from(witness.signature),
|
|
6796
|
+
request
|
|
6797
|
+
),
|
|
6798
|
+
"invalid wallet authorization"
|
|
6799
|
+
);
|
|
6800
|
+
return witness;
|
|
6980
6801
|
}
|
|
6981
|
-
|
|
6982
|
-
|
|
6983
|
-
|
|
6984
|
-
|
|
6985
|
-
|
|
6986
|
-
|
|
6802
|
+
async membership(leaf, input, sources) {
|
|
6803
|
+
const source = sources.findIndex((value) => value.treeId === input.treeId);
|
|
6804
|
+
check2(
|
|
6805
|
+
source >= 0 && Number.isInteger(input.leafIndex) && input.leafIndex >= 0 && input.leafIndex < 65536 && input.path.length === 16,
|
|
6806
|
+
"invalid membership position"
|
|
6807
|
+
);
|
|
6808
|
+
let root = BigInt(leaf);
|
|
6809
|
+
for (let level = 0; level < 16; level++)
|
|
6810
|
+
root = BigInt(
|
|
6811
|
+
await (0, import_core10.poseidonHash)(
|
|
6812
|
+
input.leafIndex >> level & 1 ? [input.path[level], root] : [root, input.path[level]]
|
|
6813
|
+
)
|
|
6814
|
+
);
|
|
6815
|
+
check2(root === BigInt(sources[source].merkleRoot), "membership root mismatch");
|
|
6816
|
+
return source;
|
|
6987
6817
|
}
|
|
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);
|
|
6818
|
+
async noteLeaf(note) {
|
|
6819
|
+
this.context(note);
|
|
6820
|
+
return (0, import_core10.computeNoteCommitment)(
|
|
6821
|
+
note.chainId,
|
|
6822
|
+
await (0, import_core10.computeNoteIdentity)(BigInt(note.walletIdentity), note.nonce),
|
|
6823
|
+
note.tokenAddress,
|
|
6824
|
+
note.amount
|
|
6825
|
+
);
|
|
7002
6826
|
}
|
|
7003
|
-
|
|
7004
|
-
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
|
|
7009
|
-
|
|
7010
|
-
|
|
6827
|
+
async creditLeaf(note) {
|
|
6828
|
+
this.context(note);
|
|
6829
|
+
return (0, import_core10.computeCreditCommitment)(
|
|
6830
|
+
note.chainId,
|
|
6831
|
+
note.spenderWalletIdentity,
|
|
6832
|
+
note.ownerWalletIdentity,
|
|
6833
|
+
note.spenderPayout,
|
|
6834
|
+
note.ownerPayout,
|
|
6835
|
+
note.tokenAddress,
|
|
6836
|
+
note.amount,
|
|
6837
|
+
note.nonce,
|
|
6838
|
+
note.expiry,
|
|
6839
|
+
await (0, import_core10.computeCreditSharedKeyHash)(note.creditSharedKey)
|
|
7011
6840
|
);
|
|
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
6841
|
}
|
|
7017
|
-
async
|
|
7018
|
-
|
|
7019
|
-
|
|
7020
|
-
|
|
7021
|
-
|
|
7022
|
-
await
|
|
7023
|
-
|
|
7024
|
-
|
|
7025
|
-
|
|
7026
|
-
)
|
|
7027
|
-
|
|
7028
|
-
|
|
7029
|
-
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7034
|
-
|
|
7035
|
-
|
|
6842
|
+
async noteInputs(inputs, sources, nullifiers, identity, authority) {
|
|
6843
|
+
check2(inputs.length === nullifiers.length, "input count mismatch");
|
|
6844
|
+
return Promise.all(
|
|
6845
|
+
inputs.map(async (input, i) => {
|
|
6846
|
+
check2(input.note.walletIdentity === identity, "input wallet mismatch");
|
|
6847
|
+
const leaf = await this.noteLeaf(input.note);
|
|
6848
|
+
check2(
|
|
6849
|
+
await (0, import_core10.computeNoteNullifier)(input.note.chainId, input.note.nonce, leaf) === nullifiers[i],
|
|
6850
|
+
"input nullifier mismatch"
|
|
6851
|
+
);
|
|
6852
|
+
return BigInt(await this.membership(leaf, input, sources));
|
|
6853
|
+
})
|
|
6854
|
+
);
|
|
6855
|
+
}
|
|
6856
|
+
async transact(p) {
|
|
6857
|
+
const c = this.#protocol.context, n = normalizeTransactRequest(c, p.params, p.deliveries, p.funding), words = transactUserPublicInputs(c, p.params, p.deliveries, p.funding);
|
|
6858
|
+
check2(
|
|
6859
|
+
p.inputs.length === n.inputCount && p.outputs.length === n.outputCount,
|
|
6860
|
+
"note count mismatch"
|
|
6861
|
+
);
|
|
6862
|
+
const identity = p.inputs[0]?.note.walletIdentity;
|
|
6863
|
+
const unsignedSweep = !!identity && !p.authorization && n.outputCount === 0 && n.depositAmount === 0n && BigInt(p.params.withdrawalAddress) === BigInt(identity);
|
|
6864
|
+
const authority = identity && !unsignedSweep ? await this.authority("transact", n.capacity, words, p.authorization, identity) : zeroAuthority();
|
|
6865
|
+
const sources = await this.noteInputs(
|
|
6866
|
+
p.inputs,
|
|
6867
|
+
p.params.sources,
|
|
6868
|
+
p.params.nullifiers,
|
|
6869
|
+
identity ?? "0x" + "00".repeat(32),
|
|
6870
|
+
authority
|
|
6871
|
+
);
|
|
6872
|
+
for (const [i, note] of p.outputs.entries())
|
|
6873
|
+
check2(
|
|
6874
|
+
await this.noteLeaf(note) === p.params.outputCommitments[i],
|
|
6875
|
+
"output commitment mismatch"
|
|
6876
|
+
);
|
|
6877
|
+
const all = [...p.inputs.map((input) => input.note), ...p.outputs];
|
|
6878
|
+
return provingRequest(
|
|
6879
|
+
`transact_user_slots${n.capacity}`,
|
|
6880
|
+
{
|
|
6881
|
+
wallet_identity: identity ? BigInt(identity) : 0n,
|
|
6882
|
+
...authority,
|
|
6883
|
+
output_wallet_identities: pad2(
|
|
6884
|
+
[
|
|
6885
|
+
...p.inputs.map(() => 0n),
|
|
6886
|
+
...p.outputs.map((note) => BigInt(note.walletIdentity))
|
|
6887
|
+
],
|
|
6888
|
+
n.capacity,
|
|
6889
|
+
() => 0n
|
|
6890
|
+
),
|
|
6891
|
+
amounts: pad2(
|
|
6892
|
+
all.map((note) => note.amount),
|
|
6893
|
+
n.capacity,
|
|
6894
|
+
() => 0n
|
|
6895
|
+
),
|
|
6896
|
+
nonces: pad2(
|
|
6897
|
+
all.map((note) => note.nonce),
|
|
6898
|
+
n.capacity,
|
|
6899
|
+
() => 0n
|
|
6900
|
+
),
|
|
6901
|
+
leaf_indices: pad2(
|
|
6902
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6903
|
+
n.capacity,
|
|
6904
|
+
() => 0n
|
|
6905
|
+
),
|
|
6906
|
+
merkle_paths: pad2(
|
|
6907
|
+
p.inputs.map((input) => [...input.path]),
|
|
6908
|
+
n.capacity,
|
|
6909
|
+
zeros
|
|
6910
|
+
),
|
|
6911
|
+
input_source_indices: pad2(sources, n.capacity, () => 0n)
|
|
6912
|
+
},
|
|
6913
|
+
words,
|
|
6914
|
+
p.target
|
|
6915
|
+
);
|
|
7036
6916
|
}
|
|
7037
|
-
|
|
6917
|
+
async creation(p, operation, words) {
|
|
6918
|
+
const state = (0, import_core10.normalizeCreditDeliveryState)(p.state), note = state.note;
|
|
6919
|
+
check2(
|
|
6920
|
+
await this.creditLeaf(note) === p.params.creditCommitment && note.ownerPayout === BigInt(p.params.owner) && note.expiry === p.params.expiry,
|
|
6921
|
+
"Credit creation mismatch"
|
|
6922
|
+
);
|
|
6923
|
+
const authority = await this.authority(
|
|
6924
|
+
operation,
|
|
6925
|
+
10,
|
|
6926
|
+
words,
|
|
6927
|
+
p.authorization,
|
|
6928
|
+
note.ownerWalletIdentity
|
|
6929
|
+
);
|
|
6930
|
+
const sources = await this.noteInputs(
|
|
6931
|
+
p.inputs,
|
|
6932
|
+
p.params.sources,
|
|
6933
|
+
p.params.nullifiers,
|
|
6934
|
+
note.ownerWalletIdentity,
|
|
6935
|
+
authority
|
|
6936
|
+
);
|
|
6937
|
+
if (p.change)
|
|
6938
|
+
check2(
|
|
6939
|
+
p.change.walletIdentity === note.ownerWalletIdentity && await this.noteLeaf(p.change) === p.params.changeCommitment,
|
|
6940
|
+
"change commitment mismatch"
|
|
6941
|
+
);
|
|
6942
|
+
else check2(BigInt(p.params.changeCommitment) === 0n, "missing change note");
|
|
7038
6943
|
return {
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
6944
|
+
...authority,
|
|
6945
|
+
input_amounts: pad2(
|
|
6946
|
+
p.inputs.map((input) => input.note.amount),
|
|
6947
|
+
10,
|
|
6948
|
+
() => 0n
|
|
6949
|
+
),
|
|
6950
|
+
input_nonces: pad2(
|
|
6951
|
+
p.inputs.map((input) => input.note.nonce),
|
|
6952
|
+
10,
|
|
6953
|
+
() => 0n
|
|
6954
|
+
),
|
|
6955
|
+
leaf_indices: pad2(
|
|
6956
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
6957
|
+
10,
|
|
6958
|
+
() => 0n
|
|
6959
|
+
),
|
|
6960
|
+
merkle_paths: pad2(
|
|
6961
|
+
p.inputs.map((input) => [...input.path]),
|
|
6962
|
+
10,
|
|
6963
|
+
zeros
|
|
6964
|
+
),
|
|
6965
|
+
input_source_indices: pad2(sources, 10, () => 0n),
|
|
6966
|
+
spender_payout: note.spenderPayout,
|
|
6967
|
+
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
6968
|
+
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
6969
|
+
credit_amount: note.amount,
|
|
6970
|
+
credit_nonce: note.nonce,
|
|
6971
|
+
credit_shared_key: note.creditSharedKey,
|
|
6972
|
+
change_amount: p.change?.amount ?? 0n,
|
|
6973
|
+
change_nonce: p.change?.nonce ?? 0n
|
|
7042
6974
|
};
|
|
7043
6975
|
}
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
6976
|
+
async createCredit(p) {
|
|
6977
|
+
const words = createCreditPublicInputs(
|
|
6978
|
+
this.#protocol.context,
|
|
6979
|
+
p.params,
|
|
6980
|
+
p.deliveries,
|
|
6981
|
+
p.funding
|
|
6982
|
+
);
|
|
6983
|
+
return provingRequest(
|
|
6984
|
+
"create_credit",
|
|
6985
|
+
await this.creation(p, "create-credit", words),
|
|
6986
|
+
words
|
|
7049
6987
|
);
|
|
7050
6988
|
}
|
|
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");
|
|
6989
|
+
async cancelCredit(p) {
|
|
6990
|
+
const note = (0, import_core10.normalizeCreditDeliveryState)(p.input.state).note, leaf = await this.creditLeaf(note), c = this.#protocol.context;
|
|
6991
|
+
check2(
|
|
6992
|
+
await (0, import_core10.computeCreditNullifier)(c.chainId, note.creditSharedKey, leaf) === p.params.nullifier && note.amount === p.params.amount && note.ownerPayout === BigInt(p.params.owner),
|
|
6993
|
+
"Credit cancellation mismatch"
|
|
6994
|
+
);
|
|
6995
|
+
await this.membership(leaf, p.input, [p.params.source]);
|
|
6996
|
+
const words = cancelCreditPublicInputs(c, p.params), authority = await this.authority(
|
|
6997
|
+
"cancel-credit",
|
|
6998
|
+
1,
|
|
6999
|
+
words,
|
|
7000
|
+
p.authorization,
|
|
7001
|
+
note.ownerWalletIdentity
|
|
7002
|
+
);
|
|
7003
|
+
return provingRequest(
|
|
7004
|
+
"credit_cancel",
|
|
7005
|
+
{
|
|
7006
|
+
...authority,
|
|
7007
|
+
spender_payout: note.spenderPayout,
|
|
7008
|
+
spender_wallet_identity: BigInt(note.spenderWalletIdentity),
|
|
7009
|
+
owner_wallet_identity: BigInt(note.ownerWalletIdentity),
|
|
7010
|
+
input_nonce: note.nonce,
|
|
7011
|
+
expiry: note.expiry,
|
|
7012
|
+
credit_shared_key: note.creditSharedKey,
|
|
7013
|
+
leaf_index: BigInt(p.input.leafIndex),
|
|
7014
|
+
merkle_path: [...p.input.path]
|
|
7015
|
+
},
|
|
7016
|
+
words
|
|
7017
|
+
);
|
|
7088
7018
|
}
|
|
7089
|
-
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7094
|
-
|
|
7095
|
-
|
|
7096
|
-
const
|
|
7097
|
-
|
|
7098
|
-
|
|
7099
|
-
|
|
7100
|
-
|
|
7019
|
+
async drawCredit(p) {
|
|
7020
|
+
const c = this.#protocol.context, profile = selectCreditDrawCircuit(p.inputs.length), capacity = profile.maxSize;
|
|
7021
|
+
check2(
|
|
7022
|
+
p.inputs.length === p.amounts.length && p.inputs.length === p.params.nullifiers.length,
|
|
7023
|
+
"draw input count mismatch"
|
|
7024
|
+
);
|
|
7025
|
+
const notes2 = p.inputs.map((input) => (0, import_core10.normalizeCreditDeliveryState)(input.state).note), identity = notes2[0].spenderWalletIdentity;
|
|
7026
|
+
const words = creditDrawPublicInputs(c, p.params, p.deliveries), authority = await this.authority(
|
|
7027
|
+
"credit-draw",
|
|
7028
|
+
capacity,
|
|
7029
|
+
words,
|
|
7030
|
+
p.authorization,
|
|
7031
|
+
identity
|
|
7032
|
+
);
|
|
7033
|
+
const sourceIndices = await Promise.all(
|
|
7034
|
+
notes2.map(async (note, i) => {
|
|
7035
|
+
const leaf = await this.creditLeaf(note);
|
|
7036
|
+
check2(
|
|
7037
|
+
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],
|
|
7038
|
+
"Credit draw mismatch"
|
|
7039
|
+
);
|
|
7040
|
+
return BigInt(await this.membership(leaf, p.inputs[i], p.params.sources));
|
|
7041
|
+
})
|
|
7042
|
+
);
|
|
7043
|
+
return provingRequest(
|
|
7044
|
+
profile.name,
|
|
7045
|
+
{
|
|
7046
|
+
...authority,
|
|
7047
|
+
spender_wallet_identity: BigInt(identity),
|
|
7048
|
+
owner_payouts: pad2(
|
|
7049
|
+
notes2.map((note) => note.ownerPayout),
|
|
7050
|
+
capacity,
|
|
7051
|
+
() => 0n
|
|
7052
|
+
),
|
|
7053
|
+
owner_wallet_identities: pad2(
|
|
7054
|
+
notes2.map((note) => BigInt(note.ownerWalletIdentity)),
|
|
7055
|
+
capacity,
|
|
7056
|
+
() => 0n
|
|
7057
|
+
),
|
|
7058
|
+
input_amounts: pad2(
|
|
7059
|
+
notes2.map((note) => note.amount),
|
|
7060
|
+
capacity,
|
|
7061
|
+
() => 0n
|
|
7062
|
+
),
|
|
7063
|
+
input_nonces: pad2(
|
|
7064
|
+
notes2.map((note) => note.nonce),
|
|
7065
|
+
capacity,
|
|
7066
|
+
() => 0n
|
|
7067
|
+
),
|
|
7068
|
+
credit_shared_keys: pad2(
|
|
7069
|
+
notes2.map((note) => note.creditSharedKey),
|
|
7070
|
+
capacity,
|
|
7071
|
+
() => 0n
|
|
7072
|
+
),
|
|
7073
|
+
leaf_indices: pad2(
|
|
7074
|
+
p.inputs.map((input) => BigInt(input.leafIndex)),
|
|
7075
|
+
capacity,
|
|
7076
|
+
() => 0n
|
|
7077
|
+
),
|
|
7078
|
+
merkle_paths: pad2(
|
|
7079
|
+
p.inputs.map((input) => [...input.path]),
|
|
7080
|
+
capacity,
|
|
7081
|
+
zeros
|
|
7082
|
+
),
|
|
7083
|
+
input_source_indices: pad2(sourceIndices, capacity, () => 0n),
|
|
7084
|
+
draw_amounts: pad2(p.amounts, capacity, () => 0n)
|
|
7085
|
+
},
|
|
7086
|
+
words
|
|
7101
7087
|
);
|
|
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
7088
|
}
|
|
7107
|
-
|
|
7108
|
-
|
|
7109
|
-
|
|
7110
|
-
|
|
7089
|
+
async topUpCredit(p) {
|
|
7090
|
+
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);
|
|
7091
|
+
for (const field2 of [
|
|
7092
|
+
"spenderWalletIdentity",
|
|
7093
|
+
"ownerWalletIdentity",
|
|
7094
|
+
"spenderPayout",
|
|
7095
|
+
"ownerPayout",
|
|
7096
|
+
"creditSharedKey"
|
|
7097
|
+
])
|
|
7098
|
+
check2(old[field2] === note[field2], "Credit role or payout changed");
|
|
7099
|
+
check2(
|
|
7100
|
+
JSON.stringify(previous.ownerReceivingKeys) === JSON.stringify(next.ownerReceivingKeys) && JSON.stringify(previous.spenderReceivingKeys) === JSON.stringify(next.spenderReceivingKeys),
|
|
7101
|
+
"Credit receiving snapshots changed"
|
|
7102
|
+
);
|
|
7103
|
+
check2(
|
|
7104
|
+
old.amount < note.amount && old.expiry <= note.expiry && old.expiry === p.params.previousExpiry && (c.now === void 0 || old.expiry > c.now),
|
|
7105
|
+
"invalid Credit top-up"
|
|
7106
|
+
);
|
|
7107
|
+
check2(
|
|
7108
|
+
await (0, import_core10.computeCreditNullifier)(c.chainId, old.creditSharedKey, leaf) === p.params.creditNullifier,
|
|
7109
|
+
"previous Credit nullifier mismatch"
|
|
7110
|
+
);
|
|
7111
|
+
await this.membership(leaf, p.previous, [p.params.creditSource]);
|
|
7112
|
+
const words = topUpCreditPublicInputs(c, p.params, p.deliveries, p.funding), base = await this.creation({ ...p, params: p.params.creation }, "top-up-credit", words);
|
|
7113
|
+
return provingRequest(
|
|
7114
|
+
"credit_top_up",
|
|
7115
|
+
{
|
|
7116
|
+
...base,
|
|
7117
|
+
previous_credit_amount: old.amount,
|
|
7118
|
+
previous_credit_nonce: old.nonce,
|
|
7119
|
+
previous_credit_leaf_index: BigInt(p.previous.leafIndex),
|
|
7120
|
+
previous_credit_merkle_path: [...p.previous.path]
|
|
7121
|
+
},
|
|
7122
|
+
words
|
|
7123
|
+
);
|
|
7124
|
+
}
|
|
7125
|
+
};
|
|
7111
7126
|
|
|
7112
7127
|
// src/factory.ts
|
|
7113
7128
|
var import_ethers10 = require("ethers");
|
|
@@ -7180,8 +7195,7 @@ async function resolveInstanceAddress(client, factoryAddress, salt) {
|
|
|
7180
7195
|
normalizeTransactRequest,
|
|
7181
7196
|
notes,
|
|
7182
7197
|
pad,
|
|
7183
|
-
|
|
7184
|
-
registrationPublicInputs,
|
|
7198
|
+
registrationDigest,
|
|
7185
7199
|
registrationTypedData,
|
|
7186
7200
|
resolveInstanceAddress,
|
|
7187
7201
|
selectCreditDrawCircuit,
|