@kohaku-eth/tornado-cash 0.0.2-alpha.15 → 0.0.2-alpha.16
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/index.d.ts +27 -6
- package/dist/index.js +5 -1
- package/dist/state-manager.worker.js +34 -17
- package/dist/state-manager.worker.node.js +34 -17
- package/dist/worker-loader.browser.d.ts +18 -6
- package/dist/worker-loader.node.d.ts +18 -6
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -33,6 +33,15 @@ type DeriveDepositSecretParams = BaseDeriveSecretParams & {
|
|
|
33
33
|
interface ISecretManager {
|
|
34
34
|
getDepositSecrets: (params: DeriveDepositSecretParams) => Promise<Secret>;
|
|
35
35
|
deriveEphemeralSigner: (params: DeriveDepositSecretParams) => Promise<`0x${string}`>;
|
|
36
|
+
/**
|
|
37
|
+
* Derives a delegator key from a classical wallet BIP-32 `path`, WITHOUT the
|
|
38
|
+
* `coalesceSecret` privacy transform, so it resolves to a recoverable,
|
|
39
|
+
* classical Ethereum address. Used for the tail-call batch delegator when the
|
|
40
|
+
* integrator supplies a wallet path (see `paymasterWithdrawThunk`).
|
|
41
|
+
*/
|
|
42
|
+
deriveDelegatorSigner: (params: {
|
|
43
|
+
path: string;
|
|
44
|
+
}) => Promise<`0x${string}`>;
|
|
36
45
|
}
|
|
37
46
|
interface SecretManagerParams {
|
|
38
47
|
host: Pick<Host, 'keystore'>;
|
|
@@ -352,6 +361,24 @@ declare enum DepositStrategy {
|
|
|
352
361
|
MinFee = 1
|
|
353
362
|
}
|
|
354
363
|
|
|
364
|
+
/**
|
|
365
|
+
* How the batch delegator for a tail-call paymaster withdrawal is produced.
|
|
366
|
+
* Only honored when `tailCalls` are present (see `paymasterWithdrawThunk`).
|
|
367
|
+
*
|
|
368
|
+
* - `deterministic` (default): recoverable. With `path`, the delegator is a
|
|
369
|
+
* classical wallet-path address; without `path`, an ephemeral address keyed by
|
|
370
|
+
* the batch's first deposit.
|
|
371
|
+
* - `random`: a throwaway, unrecoverable EOA — an explicit opt-out of
|
|
372
|
+
* recoverability. Never the default, because in the tail-call path the
|
|
373
|
+
* delegator holds the withdrawn funds.
|
|
374
|
+
*/
|
|
375
|
+
type DelegationConfig = {
|
|
376
|
+
mode: 'deterministic';
|
|
377
|
+
path?: string;
|
|
378
|
+
} | {
|
|
379
|
+
mode: 'random';
|
|
380
|
+
};
|
|
381
|
+
|
|
355
382
|
interface SerializedAuth {
|
|
356
383
|
address: Address$1;
|
|
357
384
|
chainId: Hex;
|
|
@@ -410,12 +437,6 @@ interface IPaymasterBroadcasterClient {
|
|
|
410
437
|
broadcast(withdrawals: IPaymasterWithdrawalPayload[]): Promise<PaymasterBroadcastResult[]>;
|
|
411
438
|
}
|
|
412
439
|
|
|
413
|
-
type DelegationConfig = {
|
|
414
|
-
mode: 'deterministic';
|
|
415
|
-
path?: string;
|
|
416
|
-
} | {
|
|
417
|
-
mode: 'random';
|
|
418
|
-
};
|
|
419
440
|
type StringAddress = `0x${string}`;
|
|
420
441
|
interface IPaymasterConfig {
|
|
421
442
|
paymasterAddress: StringAddress;
|
package/dist/index.js
CHANGED
|
@@ -764,9 +764,13 @@ async function SecretManager({
|
|
|
764
764
|
const coalesced = coalesceSecret({ secret: raw, chainId, poolAddress });
|
|
765
765
|
return `0x${coalesced.toString(16).padStart(64, "0")}`;
|
|
766
766
|
};
|
|
767
|
+
const deriveDelegatorSigner = async ({ path }) => {
|
|
768
|
+
return Promise.resolve(keystore.deriveAt(path));
|
|
769
|
+
};
|
|
767
770
|
return {
|
|
768
771
|
getDepositSecrets: (params) => deriveSecrets(params),
|
|
769
|
-
deriveEphemeralSigner
|
|
772
|
+
deriveEphemeralSigner,
|
|
773
|
+
deriveDelegatorSigner
|
|
770
774
|
};
|
|
771
775
|
}
|
|
772
776
|
function tcPath({ accountIndex, secretType, depositIndex }) {
|
|
@@ -17281,9 +17281,13 @@ async function SecretManager({
|
|
|
17281
17281
|
const coalesced = coalesceSecret({ secret: raw, chainId, poolAddress });
|
|
17282
17282
|
return `0x${coalesced.toString(16).padStart(64, "0")}`;
|
|
17283
17283
|
};
|
|
17284
|
+
const deriveDelegatorSigner = async ({ path }) => {
|
|
17285
|
+
return Promise.resolve(keystore.deriveAt(path));
|
|
17286
|
+
};
|
|
17284
17287
|
return {
|
|
17285
17288
|
getDepositSecrets: (params) => deriveSecrets(params),
|
|
17286
|
-
deriveEphemeralSigner
|
|
17289
|
+
deriveEphemeralSigner,
|
|
17290
|
+
deriveDelegatorSigner
|
|
17287
17291
|
};
|
|
17288
17292
|
}
|
|
17289
17293
|
function tcPath({ accountIndex, secretType, depositIndex }) {
|
|
@@ -24087,11 +24091,8 @@ async function getUserOperationGasPrice(client) {
|
|
|
24087
24091
|
fast: parse(result.fast)
|
|
24088
24092
|
};
|
|
24089
24093
|
}
|
|
24090
|
-
function ephemeralSenderAddress(privateKey) {
|
|
24091
|
-
return privateKeyToAccount(privateKey).address;
|
|
24092
|
-
}
|
|
24093
24094
|
async function buildSignedTornadoUserOp({
|
|
24094
|
-
|
|
24095
|
+
signer,
|
|
24095
24096
|
chainId,
|
|
24096
24097
|
paymasterAddress,
|
|
24097
24098
|
paymasterData,
|
|
@@ -24101,7 +24102,7 @@ async function buildSignedTornadoUserOp({
|
|
|
24101
24102
|
tailCalls = async () => [],
|
|
24102
24103
|
nonce = 0n
|
|
24103
24104
|
}) {
|
|
24104
|
-
const owner =
|
|
24105
|
+
const owner = signer;
|
|
24105
24106
|
const calls = await tailCalls(owner.address);
|
|
24106
24107
|
let callData = "0x";
|
|
24107
24108
|
if (calls.length === 1) {
|
|
@@ -24174,6 +24175,12 @@ function serializeAuth(auth) {
|
|
|
24174
24175
|
}
|
|
24175
24176
|
|
|
24176
24177
|
// src/state/thunks/paymasterWithdrawThunk.ts
|
|
24178
|
+
var BIP32_PATH = /^m(\/\d+'?)+$/;
|
|
24179
|
+
function assertValidDelegatorPath(path) {
|
|
24180
|
+
if (!BIP32_PATH.test(path)) {
|
|
24181
|
+
throw new Error(`Invalid delegation path "${path}": expected a BIP-32 path like m/44'/60'/0'/0/0`);
|
|
24182
|
+
}
|
|
24183
|
+
}
|
|
24177
24184
|
var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdrawals", async ({
|
|
24178
24185
|
dataService,
|
|
24179
24186
|
assetAddress,
|
|
@@ -24220,18 +24227,28 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
24220
24227
|
const relayerAddress = BigInt(paymasterAddress);
|
|
24221
24228
|
const bigintChainId = await dataService.getChainId();
|
|
24222
24229
|
const { recipient: originalRecipient, ...restWithoutRecipient } = rest;
|
|
24223
|
-
const
|
|
24230
|
+
const ephemeralSigner = async (deposit) => privateKeyToAccount(await secretManager.deriveEphemeralSigner({
|
|
24231
|
+
depositIndex: deposit.index,
|
|
24232
|
+
chainId: bigintChainId,
|
|
24233
|
+
poolAddress: deposit.pool
|
|
24234
|
+
}));
|
|
24235
|
+
const resolveBatchDelegator = async () => {
|
|
24236
|
+
if (delegation?.mode === "random") return privateKeyToAccount(generatePrivateKey());
|
|
24237
|
+
if (delegation?.mode === "deterministic" && delegation.path) {
|
|
24238
|
+
assertValidDelegatorPath(delegation.path);
|
|
24239
|
+
return privateKeyToAccount(await secretManager.deriveDelegatorSigner({ path: delegation.path }));
|
|
24240
|
+
}
|
|
24241
|
+
return ephemeralSigner(deposits[0]);
|
|
24242
|
+
};
|
|
24243
|
+
const resolveIndependentSigner = (deposit) => delegation?.mode === "deterministic" ? ephemeralSigner(deposit) : Promise.resolve(privateKeyToAccount(generatePrivateKey()));
|
|
24244
|
+
const sharedDelegator = tailCalls ? await resolveBatchDelegator() : null;
|
|
24224
24245
|
const proofOutputs = [];
|
|
24225
24246
|
const userOperations = [];
|
|
24226
24247
|
for (let i = 0; i < deposits.length; i++) {
|
|
24227
24248
|
const deposit = deposits[i];
|
|
24228
24249
|
const isLast = i === deposits.length - 1;
|
|
24229
|
-
const
|
|
24230
|
-
|
|
24231
|
-
chainId: bigintChainId,
|
|
24232
|
-
poolAddress: deposit.pool
|
|
24233
|
-
}) : generatePrivateKey());
|
|
24234
|
-
const recipient = sharedPrivateKey ? BigInt(ephemeralSenderAddress(privateKey)) : originalRecipient;
|
|
24250
|
+
const signer = sharedDelegator ?? await resolveIndependentSigner(deposit);
|
|
24251
|
+
const recipient = sharedDelegator ? BigInt(signer.address) : originalRecipient;
|
|
24235
24252
|
const effectiveTailCalls = isLast ? tailCalls : void 0;
|
|
24236
24253
|
const gas = { ...gasUnits, callGasLimit: effectiveTailCalls ? gasUnits.callGasLimit : 0n };
|
|
24237
24254
|
const withdrawResultAction = await dispatch(
|
|
@@ -24261,7 +24278,7 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
24261
24278
|
);
|
|
24262
24279
|
userOperations.push(
|
|
24263
24280
|
await buildSignedTornadoUserOp({
|
|
24264
|
-
|
|
24281
|
+
signer,
|
|
24265
24282
|
chainId,
|
|
24266
24283
|
paymasterAddress,
|
|
24267
24284
|
paymasterData,
|
|
@@ -24269,9 +24286,9 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
24269
24286
|
maxFeePerGas,
|
|
24270
24287
|
maxPriorityFeePerGas,
|
|
24271
24288
|
tailCalls: effectiveTailCalls,
|
|
24272
|
-
// When sharing one
|
|
24273
|
-
//
|
|
24274
|
-
nonce:
|
|
24289
|
+
// When sharing one delegator across multiple deposits each userOp needs
|
|
24290
|
+
// a distinct nonce (0, 1, 2 …) on the shared sender.
|
|
24291
|
+
nonce: sharedDelegator ? BigInt(i) : 0n
|
|
24275
24292
|
})
|
|
24276
24293
|
);
|
|
24277
24294
|
}
|
|
@@ -16853,9 +16853,13 @@ async function SecretManager({
|
|
|
16853
16853
|
const coalesced = coalesceSecret({ secret: raw, chainId, poolAddress });
|
|
16854
16854
|
return `0x${coalesced.toString(16).padStart(64, "0")}`;
|
|
16855
16855
|
};
|
|
16856
|
+
const deriveDelegatorSigner = async ({ path }) => {
|
|
16857
|
+
return Promise.resolve(keystore.deriveAt(path));
|
|
16858
|
+
};
|
|
16856
16859
|
return {
|
|
16857
16860
|
getDepositSecrets: (params) => deriveSecrets(params),
|
|
16858
|
-
deriveEphemeralSigner
|
|
16861
|
+
deriveEphemeralSigner,
|
|
16862
|
+
deriveDelegatorSigner
|
|
16859
16863
|
};
|
|
16860
16864
|
}
|
|
16861
16865
|
function tcPath({ accountIndex, secretType, depositIndex }) {
|
|
@@ -23313,11 +23317,8 @@ async function getUserOperationGasPrice(client) {
|
|
|
23313
23317
|
fast: parse(result.fast)
|
|
23314
23318
|
};
|
|
23315
23319
|
}
|
|
23316
|
-
function ephemeralSenderAddress(privateKey) {
|
|
23317
|
-
return privateKeyToAccount(privateKey).address;
|
|
23318
|
-
}
|
|
23319
23320
|
async function buildSignedTornadoUserOp({
|
|
23320
|
-
|
|
23321
|
+
signer,
|
|
23321
23322
|
chainId,
|
|
23322
23323
|
paymasterAddress,
|
|
23323
23324
|
paymasterData,
|
|
@@ -23327,7 +23328,7 @@ async function buildSignedTornadoUserOp({
|
|
|
23327
23328
|
tailCalls = async () => [],
|
|
23328
23329
|
nonce = 0n
|
|
23329
23330
|
}) {
|
|
23330
|
-
const owner =
|
|
23331
|
+
const owner = signer;
|
|
23331
23332
|
const calls = await tailCalls(owner.address);
|
|
23332
23333
|
let callData = "0x";
|
|
23333
23334
|
if (calls.length === 1) {
|
|
@@ -23400,6 +23401,12 @@ function serializeAuth(auth) {
|
|
|
23400
23401
|
}
|
|
23401
23402
|
|
|
23402
23403
|
// src/state/thunks/paymasterWithdrawThunk.ts
|
|
23404
|
+
var BIP32_PATH = /^m(\/\d+'?)+$/;
|
|
23405
|
+
function assertValidDelegatorPath(path) {
|
|
23406
|
+
if (!BIP32_PATH.test(path)) {
|
|
23407
|
+
throw new Error(`Invalid delegation path "${path}": expected a BIP-32 path like m/44'/60'/0'/0/0`);
|
|
23408
|
+
}
|
|
23409
|
+
}
|
|
23403
23410
|
var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdrawals", async ({
|
|
23404
23411
|
dataService,
|
|
23405
23412
|
assetAddress,
|
|
@@ -23446,18 +23453,28 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
23446
23453
|
const relayerAddress = BigInt(paymasterAddress);
|
|
23447
23454
|
const bigintChainId = await dataService.getChainId();
|
|
23448
23455
|
const { recipient: originalRecipient, ...restWithoutRecipient } = rest;
|
|
23449
|
-
const
|
|
23456
|
+
const ephemeralSigner = async (deposit) => privateKeyToAccount(await secretManager.deriveEphemeralSigner({
|
|
23457
|
+
depositIndex: deposit.index,
|
|
23458
|
+
chainId: bigintChainId,
|
|
23459
|
+
poolAddress: deposit.pool
|
|
23460
|
+
}));
|
|
23461
|
+
const resolveBatchDelegator = async () => {
|
|
23462
|
+
if (delegation?.mode === "random") return privateKeyToAccount(generatePrivateKey());
|
|
23463
|
+
if (delegation?.mode === "deterministic" && delegation.path) {
|
|
23464
|
+
assertValidDelegatorPath(delegation.path);
|
|
23465
|
+
return privateKeyToAccount(await secretManager.deriveDelegatorSigner({ path: delegation.path }));
|
|
23466
|
+
}
|
|
23467
|
+
return ephemeralSigner(deposits[0]);
|
|
23468
|
+
};
|
|
23469
|
+
const resolveIndependentSigner = (deposit) => delegation?.mode === "deterministic" ? ephemeralSigner(deposit) : Promise.resolve(privateKeyToAccount(generatePrivateKey()));
|
|
23470
|
+
const sharedDelegator = tailCalls ? await resolveBatchDelegator() : null;
|
|
23450
23471
|
const proofOutputs = [];
|
|
23451
23472
|
const userOperations = [];
|
|
23452
23473
|
for (let i = 0; i < deposits.length; i++) {
|
|
23453
23474
|
const deposit = deposits[i];
|
|
23454
23475
|
const isLast = i === deposits.length - 1;
|
|
23455
|
-
const
|
|
23456
|
-
|
|
23457
|
-
chainId: bigintChainId,
|
|
23458
|
-
poolAddress: deposit.pool
|
|
23459
|
-
}) : generatePrivateKey());
|
|
23460
|
-
const recipient = sharedPrivateKey ? BigInt(ephemeralSenderAddress(privateKey)) : originalRecipient;
|
|
23476
|
+
const signer = sharedDelegator ?? await resolveIndependentSigner(deposit);
|
|
23477
|
+
const recipient = sharedDelegator ? BigInt(signer.address) : originalRecipient;
|
|
23461
23478
|
const effectiveTailCalls = isLast ? tailCalls : void 0;
|
|
23462
23479
|
const gas = { ...gasUnits, callGasLimit: effectiveTailCalls ? gasUnits.callGasLimit : 0n };
|
|
23463
23480
|
const withdrawResultAction = await dispatch(
|
|
@@ -23487,7 +23504,7 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
23487
23504
|
);
|
|
23488
23505
|
userOperations.push(
|
|
23489
23506
|
await buildSignedTornadoUserOp({
|
|
23490
|
-
|
|
23507
|
+
signer,
|
|
23491
23508
|
chainId,
|
|
23492
23509
|
paymasterAddress,
|
|
23493
23510
|
paymasterData,
|
|
@@ -23495,9 +23512,9 @@ var paymasterWithdrawThunk = createAsyncThunk("withdraw/executePaymasterWithdraw
|
|
|
23495
23512
|
maxFeePerGas,
|
|
23496
23513
|
maxPriorityFeePerGas,
|
|
23497
23514
|
tailCalls: effectiveTailCalls,
|
|
23498
|
-
// When sharing one
|
|
23499
|
-
//
|
|
23500
|
-
nonce:
|
|
23515
|
+
// When sharing one delegator across multiple deposits each userOp needs
|
|
23516
|
+
// a distinct nonce (0, 1, 2 …) on the shared sender.
|
|
23517
|
+
nonce: sharedDelegator ? BigInt(i) : 0n
|
|
23501
23518
|
})
|
|
23502
23519
|
);
|
|
23503
23520
|
}
|
|
@@ -113,6 +113,24 @@ declare enum DepositStrategy {
|
|
|
113
113
|
MinFee = 1
|
|
114
114
|
}
|
|
115
115
|
|
|
116
|
+
/**
|
|
117
|
+
* How the batch delegator for a tail-call paymaster withdrawal is produced.
|
|
118
|
+
* Only honored when `tailCalls` are present (see `paymasterWithdrawThunk`).
|
|
119
|
+
*
|
|
120
|
+
* - `deterministic` (default): recoverable. With `path`, the delegator is a
|
|
121
|
+
* classical wallet-path address; without `path`, an ephemeral address keyed by
|
|
122
|
+
* the batch's first deposit.
|
|
123
|
+
* - `random`: a throwaway, unrecoverable EOA — an explicit opt-out of
|
|
124
|
+
* recoverability. Never the default, because in the tail-call path the
|
|
125
|
+
* delegator holds the withdrawn funds.
|
|
126
|
+
*/
|
|
127
|
+
type DelegationConfig = {
|
|
128
|
+
mode: 'deterministic';
|
|
129
|
+
path?: string;
|
|
130
|
+
} | {
|
|
131
|
+
mode: 'random';
|
|
132
|
+
};
|
|
133
|
+
|
|
116
134
|
interface SerializedAuth {
|
|
117
135
|
address: Address$1;
|
|
118
136
|
chainId: Hex;
|
|
@@ -154,12 +172,6 @@ interface IGenericPaymasterWithdrawalPayload {
|
|
|
154
172
|
userOperation: SerializedUserOperation;
|
|
155
173
|
}
|
|
156
174
|
|
|
157
|
-
type DelegationConfig = {
|
|
158
|
-
mode: 'deterministic';
|
|
159
|
-
path?: string;
|
|
160
|
-
} | {
|
|
161
|
-
mode: 'random';
|
|
162
|
-
};
|
|
163
175
|
type StringAddress = `0x${string}`;
|
|
164
176
|
interface IPaymasterConfig {
|
|
165
177
|
paymasterAddress: StringAddress;
|
|
@@ -114,6 +114,24 @@ declare enum DepositStrategy {
|
|
|
114
114
|
MinFee = 1
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
+
/**
|
|
118
|
+
* How the batch delegator for a tail-call paymaster withdrawal is produced.
|
|
119
|
+
* Only honored when `tailCalls` are present (see `paymasterWithdrawThunk`).
|
|
120
|
+
*
|
|
121
|
+
* - `deterministic` (default): recoverable. With `path`, the delegator is a
|
|
122
|
+
* classical wallet-path address; without `path`, an ephemeral address keyed by
|
|
123
|
+
* the batch's first deposit.
|
|
124
|
+
* - `random`: a throwaway, unrecoverable EOA — an explicit opt-out of
|
|
125
|
+
* recoverability. Never the default, because in the tail-call path the
|
|
126
|
+
* delegator holds the withdrawn funds.
|
|
127
|
+
*/
|
|
128
|
+
type DelegationConfig = {
|
|
129
|
+
mode: 'deterministic';
|
|
130
|
+
path?: string;
|
|
131
|
+
} | {
|
|
132
|
+
mode: 'random';
|
|
133
|
+
};
|
|
134
|
+
|
|
117
135
|
interface SerializedAuth {
|
|
118
136
|
address: Address$1;
|
|
119
137
|
chainId: Hex;
|
|
@@ -155,12 +173,6 @@ interface IGenericPaymasterWithdrawalPayload {
|
|
|
155
173
|
userOperation: SerializedUserOperation;
|
|
156
174
|
}
|
|
157
175
|
|
|
158
|
-
type DelegationConfig = {
|
|
159
|
-
mode: 'deterministic';
|
|
160
|
-
path?: string;
|
|
161
|
-
} | {
|
|
162
|
-
mode: 'random';
|
|
163
|
-
};
|
|
164
176
|
type StringAddress = `0x${string}`;
|
|
165
177
|
interface IPaymasterConfig {
|
|
166
178
|
paymasterAddress: StringAddress;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kohaku-eth/tornado-cash",
|
|
3
|
-
"version": "0.0.2-alpha.
|
|
3
|
+
"version": "0.0.2-alpha.16",
|
|
4
4
|
"description": "Tornado Cash Shielded Pool Kohaku Plugin",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -74,9 +74,9 @@
|
|
|
74
74
|
"micro-zk-proofs": "0.3.1",
|
|
75
75
|
"ox": "^0.12.0",
|
|
76
76
|
"viem": "^2.51.3",
|
|
77
|
+
"@kohaku-eth/plugins": "0.0.1-alpha.11",
|
|
77
78
|
"@kohaku-eth/mimc-tree": "0.0.3",
|
|
78
|
-
"@kohaku-eth/provider": "0.1.0-alpha.8"
|
|
79
|
-
"@kohaku-eth/plugins": "0.0.1-alpha.11"
|
|
79
|
+
"@kohaku-eth/provider": "0.1.0-alpha.8"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@types/node": "^24.12.2",
|