@opaquecash/privacy-pool 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crypto.d.ts +43 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +73 -0
- package/dist/crypto.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/dist/prove.d.ts +69 -0
- package/dist/prove.d.ts.map +1 -0
- package/dist/prove.js +73 -0
- package/dist/prove.js.map +1 -0
- package/dist/tx.d.ts +128 -0
- package/dist/tx.d.ts.map +1 -0
- package/dist/tx.js +100 -0
- package/dist/tx.js.map +1 -0
- package/package.json +38 -0
package/dist/crypto.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy-pool commitments and Poseidon Merkle trees (spec/privacy-pool.md §1–§3),
|
|
3
|
+
* byte-identical to `withdrawal.circom` and `OpaquePrivacyPool` / `MerkleTreeWithHistory`.
|
|
4
|
+
* All hashing is circomlib Poseidon over BN254; the empty leaf is 0 and
|
|
5
|
+
* `zeros[i] = Poseidon(zeros[i-1], zeros[i-1])`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const POOL_LEVELS = 20;
|
|
8
|
+
export declare const FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
9
|
+
export interface PoolCrypto {
|
|
10
|
+
/** Poseidon over field elements; returns a bigint. */
|
|
11
|
+
hash(inputs: bigint[]): bigint;
|
|
12
|
+
/** precommitment = Poseidon(nullifier, secret). */
|
|
13
|
+
precommitment(nullifier: bigint, secret: bigint): bigint;
|
|
14
|
+
/** commitment = Poseidon(value, label, precommitment). */
|
|
15
|
+
commitment(value: bigint, label: bigint, precommitment: bigint): bigint;
|
|
16
|
+
/** label = Poseidon(scope, depositIndex). */
|
|
17
|
+
label(scope: bigint, depositIndex: bigint): bigint;
|
|
18
|
+
/** nullifierHash = Poseidon(nullifier). */
|
|
19
|
+
nullifierHash(nullifier: bigint): bigint;
|
|
20
|
+
/** Zero-subtree roots, `zeros[0..LEVELS]`. */
|
|
21
|
+
zeros: bigint[];
|
|
22
|
+
}
|
|
23
|
+
/** Build the Poseidon-backed pool crypto (async: circomlibjs loads a wasm). */
|
|
24
|
+
export declare function buildPoolCrypto(): Promise<PoolCrypto>;
|
|
25
|
+
/**
|
|
26
|
+
* An append-only Poseidon Merkle tree mirroring `MerkleTreeWithHistory`. Build it from
|
|
27
|
+
* the pool's ordered leaves (deposit/remainder commitments for the state tree, approved
|
|
28
|
+
* labels for the association tree) to derive inclusion paths for the withdrawal witness.
|
|
29
|
+
*/
|
|
30
|
+
export declare class PoolMerkleTree {
|
|
31
|
+
private readonly crypto;
|
|
32
|
+
private readonly levels;
|
|
33
|
+
private layers;
|
|
34
|
+
constructor(crypto: PoolCrypto, leaves: bigint[], levels?: number);
|
|
35
|
+
/** The current root (matches the contract after inserting the same leaves in order). */
|
|
36
|
+
root(): bigint;
|
|
37
|
+
/** Inclusion path for the leaf at `index`: siblings + direction bits (0=left). */
|
|
38
|
+
proof(index: number): {
|
|
39
|
+
siblings: bigint[];
|
|
40
|
+
pathIndices: number[];
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=crypto.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.d.ts","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,eAAO,MAAM,WAAW,KAAK,CAAC;AAC9B,eAAO,MAAM,KAAK,iFAC8D,CAAC;AAEjF,MAAM,WAAW,UAAU;IACzB,sDAAsD;IACtD,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;IAC/B,mDAAmD;IACnD,aAAa,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC;IACzD,0DAA0D;IAC1D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,MAAM,CAAC;IACxE,6CAA6C;IAC7C,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC;IACnD,2CAA2C;IAC3C,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IACzC,8CAA8C;IAC9C,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,+EAA+E;AAC/E,wBAAsB,eAAe,IAAI,OAAO,CAAC,UAAU,CAAC,CAgB3D;AAED;;;;GAIG;AACH,qBAAa,cAAc;IAIvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAEvB,OAAO,CAAC,QAAQ,CAAC,MAAM;IALzB,OAAO,CAAC,MAAM,CAAa;gBAGR,MAAM,EAAE,UAAU,EACnC,MAAM,EAAE,MAAM,EAAE,EACC,MAAM,SAAc;IAevC,wFAAwF;IACxF,IAAI,IAAI,MAAM;IAKd,kFAAkF;IAClF,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG;QAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;QAAC,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE;CAcpE"}
|
package/dist/crypto.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Privacy-pool commitments and Poseidon Merkle trees (spec/privacy-pool.md §1–§3),
|
|
3
|
+
* byte-identical to `withdrawal.circom` and `OpaquePrivacyPool` / `MerkleTreeWithHistory`.
|
|
4
|
+
* All hashing is circomlib Poseidon over BN254; the empty leaf is 0 and
|
|
5
|
+
* `zeros[i] = Poseidon(zeros[i-1], zeros[i-1])`.
|
|
6
|
+
*/
|
|
7
|
+
// @ts-expect-error untyped
|
|
8
|
+
import { buildPoseidon } from "circomlibjs";
|
|
9
|
+
export const POOL_LEVELS = 20;
|
|
10
|
+
export const FIELD = 21888242871839275222246405745257275088548364400416034343698204186575808495617n;
|
|
11
|
+
/** Build the Poseidon-backed pool crypto (async: circomlibjs loads a wasm). */
|
|
12
|
+
export async function buildPoolCrypto() {
|
|
13
|
+
const poseidon = await buildPoseidon();
|
|
14
|
+
const F = poseidon.F;
|
|
15
|
+
const hash = (inputs) => F.toObject(poseidon(inputs));
|
|
16
|
+
const zeros = [0n];
|
|
17
|
+
for (let i = 1; i <= POOL_LEVELS; i++)
|
|
18
|
+
zeros.push(hash([zeros[i - 1], zeros[i - 1]]));
|
|
19
|
+
return {
|
|
20
|
+
hash,
|
|
21
|
+
zeros,
|
|
22
|
+
precommitment: (nullifier, secret) => hash([nullifier, secret]),
|
|
23
|
+
commitment: (value, label, precommitment) => hash([value, label, precommitment]),
|
|
24
|
+
label: (scope, depositIndex) => hash([scope, depositIndex]),
|
|
25
|
+
nullifierHash: (nullifier) => hash([nullifier]),
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* An append-only Poseidon Merkle tree mirroring `MerkleTreeWithHistory`. Build it from
|
|
30
|
+
* the pool's ordered leaves (deposit/remainder commitments for the state tree, approved
|
|
31
|
+
* labels for the association tree) to derive inclusion paths for the withdrawal witness.
|
|
32
|
+
*/
|
|
33
|
+
export class PoolMerkleTree {
|
|
34
|
+
crypto;
|
|
35
|
+
levels;
|
|
36
|
+
layers;
|
|
37
|
+
constructor(crypto, leaves, levels = POOL_LEVELS) {
|
|
38
|
+
this.crypto = crypto;
|
|
39
|
+
this.levels = levels;
|
|
40
|
+
this.layers = [leaves.slice()];
|
|
41
|
+
for (let level = 0; level < levels; level++) {
|
|
42
|
+
const cur = this.layers[level];
|
|
43
|
+
const next = [];
|
|
44
|
+
for (let i = 0; i < cur.length; i += 2) {
|
|
45
|
+
const left = cur[i];
|
|
46
|
+
const right = i + 1 < cur.length ? cur[i + 1] : crypto.zeros[level];
|
|
47
|
+
next.push(crypto.hash([left, right]));
|
|
48
|
+
}
|
|
49
|
+
this.layers.push(next);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/** The current root (matches the contract after inserting the same leaves in order). */
|
|
53
|
+
root() {
|
|
54
|
+
const top = this.layers[this.levels];
|
|
55
|
+
return top.length > 0 ? top[0] : this.crypto.zeros[this.levels];
|
|
56
|
+
}
|
|
57
|
+
/** Inclusion path for the leaf at `index`: siblings + direction bits (0=left). */
|
|
58
|
+
proof(index) {
|
|
59
|
+
const siblings = [];
|
|
60
|
+
const pathIndices = [];
|
|
61
|
+
let idx = index;
|
|
62
|
+
for (let level = 0; level < this.levels; level++) {
|
|
63
|
+
const layer = this.layers[level];
|
|
64
|
+
const isRight = idx % 2 === 1;
|
|
65
|
+
const siblingIdx = isRight ? idx - 1 : idx + 1;
|
|
66
|
+
siblings.push(siblingIdx < layer.length ? layer[siblingIdx] : this.crypto.zeros[level]);
|
|
67
|
+
pathIndices.push(isRight ? 1 : 0);
|
|
68
|
+
idx = Math.floor(idx / 2);
|
|
69
|
+
}
|
|
70
|
+
return { siblings, pathIndices };
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=crypto.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"crypto.js","sourceRoot":"","sources":["../src/crypto.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@opaquecash/privacy-pool` — client for the Opaque privacy pool (spec/privacy-pool.md).
|
|
3
|
+
* Amount privacy via the Privacy Pools (Buterin/Soleimani association-set) construction:
|
|
4
|
+
* deposit a value-bearing commitment, then withdraw to a fresh stealth address with a
|
|
5
|
+
* zero-knowledge proof of state-tree membership AND association-set membership.
|
|
6
|
+
*
|
|
7
|
+
* Building blocks (compose into a shielded `deposit → withdraw` flow):
|
|
8
|
+
* - {@link buildPoolCrypto} + {@link PoolMerkleTree}: Poseidon commitments + trees,
|
|
9
|
+
* byte-identical to the circuit and contract.
|
|
10
|
+
* - {@link generateDepositNote} + {@link buildDepositTx}: shielded deposit.
|
|
11
|
+
* - {@link buildWithdrawalWitness} + {@link generateWithdrawalProof}: the ZK proof.
|
|
12
|
+
* - {@link buildWithdrawTx}: the on-chain withdrawal call.
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
*/
|
|
16
|
+
export { POOL_LEVELS, FIELD, buildPoolCrypto, PoolMerkleTree, type PoolCrypto, } from "./crypto.js";
|
|
17
|
+
export { buildWithdrawalWitness, generateWithdrawalProof, toSolidityProof, type PoolArtifacts, type CommitmentNote, type BuildWithdrawalWitnessParams, type WithdrawalWitness, type SolidityProof, } from "./prove.js";
|
|
18
|
+
export { opaquePrivacyPoolAbi, generateDepositNote, buildDepositTx, buildWithdrawTx, type WithdrawalParams, type DepositNote, type EvmTxRequest, } from "./tx.js";
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,WAAW,EACX,KAAK,EACL,eAAe,EACf,cAAc,EACd,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,4BAA4B,EACjC,KAAK,iBAAiB,EACtB,KAAK,aAAa,GACnB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,KAAK,gBAAgB,EACrB,KAAK,WAAW,EAChB,KAAK,YAAY,GAClB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@opaquecash/privacy-pool` — client for the Opaque privacy pool (spec/privacy-pool.md).
|
|
3
|
+
* Amount privacy via the Privacy Pools (Buterin/Soleimani association-set) construction:
|
|
4
|
+
* deposit a value-bearing commitment, then withdraw to a fresh stealth address with a
|
|
5
|
+
* zero-knowledge proof of state-tree membership AND association-set membership.
|
|
6
|
+
*
|
|
7
|
+
* Building blocks (compose into a shielded `deposit → withdraw` flow):
|
|
8
|
+
* - {@link buildPoolCrypto} + {@link PoolMerkleTree}: Poseidon commitments + trees,
|
|
9
|
+
* byte-identical to the circuit and contract.
|
|
10
|
+
* - {@link generateDepositNote} + {@link buildDepositTx}: shielded deposit.
|
|
11
|
+
* - {@link buildWithdrawalWitness} + {@link generateWithdrawalProof}: the ZK proof.
|
|
12
|
+
* - {@link buildWithdrawTx}: the on-chain withdrawal call.
|
|
13
|
+
*
|
|
14
|
+
* @packageDocumentation
|
|
15
|
+
*/
|
|
16
|
+
export { POOL_LEVELS, FIELD, buildPoolCrypto, PoolMerkleTree, } from "./crypto.js";
|
|
17
|
+
export { buildWithdrawalWitness, generateWithdrawalProof, toSolidityProof, } from "./prove.js";
|
|
18
|
+
export { opaquePrivacyPoolAbi, generateDepositNote, buildDepositTx, buildWithdrawTx, } from "./tx.js";
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EACL,WAAW,EACX,KAAK,EACL,eAAe,EACf,cAAc,GAEf,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,GAMhB,MAAM,YAAY,CAAC;AAEpB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,eAAe,GAIhB,MAAM,SAAS,CAAC"}
|
package/dist/prove.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Withdrawal witness assembly + Groth16 proof generation (spec/privacy-pool.md §4.1).
|
|
3
|
+
* The witness binds the spent commitment's openings, both Merkle inclusion paths, the
|
|
4
|
+
* value accounting, and the contract-supplied `context`. Public-signal order matches
|
|
5
|
+
* the circuit: withdrawn_value, state_root, asp_root, nullifier_hash, new_commitment,
|
|
6
|
+
* context.
|
|
7
|
+
*/
|
|
8
|
+
import { POOL_LEVELS, type PoolCrypto } from "./crypto.js";
|
|
9
|
+
/** Paths/URLs to the withdrawal circuit artifacts (Node: file paths; browser: static URLs). */
|
|
10
|
+
export interface PoolArtifacts {
|
|
11
|
+
wasmPath: string;
|
|
12
|
+
zkeyPath: string;
|
|
13
|
+
}
|
|
14
|
+
/** The opening of a spendable commitment the user holds. */
|
|
15
|
+
export interface CommitmentNote {
|
|
16
|
+
value: bigint;
|
|
17
|
+
label: bigint;
|
|
18
|
+
nullifier: bigint;
|
|
19
|
+
secret: bigint;
|
|
20
|
+
}
|
|
21
|
+
export interface BuildWithdrawalWitnessParams {
|
|
22
|
+
note: CommitmentNote;
|
|
23
|
+
/** Amount to pay out (≤ note.value). */
|
|
24
|
+
withdrawnValue: bigint;
|
|
25
|
+
/** Fresh openings for the remainder commitment. */
|
|
26
|
+
newNullifier: bigint;
|
|
27
|
+
newSecret: bigint;
|
|
28
|
+
/** Ordered state-tree leaves (all commitments) and the note's leaf index. */
|
|
29
|
+
stateLeaves: bigint[];
|
|
30
|
+
stateIndex: number;
|
|
31
|
+
/** Ordered association-tree leaves (approved labels) and the note's label index. */
|
|
32
|
+
aspLeaves: bigint[];
|
|
33
|
+
aspIndex: number;
|
|
34
|
+
/** The pool's `context(params)` value for this withdrawal (read from the contract). */
|
|
35
|
+
context: bigint;
|
|
36
|
+
}
|
|
37
|
+
export interface WithdrawalWitness {
|
|
38
|
+
input: Record<string, string | string[]>;
|
|
39
|
+
/** Public values the caller passes to `withdraw` alongside the proof. */
|
|
40
|
+
publics: {
|
|
41
|
+
withdrawnValue: bigint;
|
|
42
|
+
stateRoot: bigint;
|
|
43
|
+
aspRoot: bigint;
|
|
44
|
+
nullifierHash: bigint;
|
|
45
|
+
newCommitment: bigint;
|
|
46
|
+
context: bigint;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
/** Assemble the circuit input + the public values for an on-chain `withdraw` call. */
|
|
50
|
+
export declare function buildWithdrawalWitness(crypto: PoolCrypto, p: BuildWithdrawalWitnessParams): WithdrawalWitness;
|
|
51
|
+
/** Groth16 proof formatted for the Solidity verifier's `verifyProof` argument order. */
|
|
52
|
+
export interface SolidityProof {
|
|
53
|
+
a: [bigint, bigint];
|
|
54
|
+
b: [[bigint, bigint], [bigint, bigint]];
|
|
55
|
+
c: [bigint, bigint];
|
|
56
|
+
}
|
|
57
|
+
/** Generate a withdrawal proof and format it for the on-chain verifier. */
|
|
58
|
+
export declare function generateWithdrawalProof(witness: WithdrawalWitness, artifacts: PoolArtifacts): Promise<{
|
|
59
|
+
proof: SolidityProof;
|
|
60
|
+
publicSignals: string[];
|
|
61
|
+
}>;
|
|
62
|
+
/** Convert a snarkjs proof object to the verifier's (a, b, c) calldata shape. */
|
|
63
|
+
export declare function toSolidityProof(proof: {
|
|
64
|
+
pi_a: string[];
|
|
65
|
+
pi_b: string[][];
|
|
66
|
+
pi_c: string[];
|
|
67
|
+
}): SolidityProof;
|
|
68
|
+
export { POOL_LEVELS };
|
|
69
|
+
//# sourceMappingURL=prove.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prove.d.ts","sourceRoot":"","sources":["../src/prove.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAkB,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3E,+FAA+F;AAC/F,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,4DAA4D;AAC5D,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,cAAc,CAAC;IACrB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,6EAA6E;IAC7E,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;IACzC,yEAAyE;IACzE,OAAO,EAAE;QACP,cAAc,EAAE,MAAM,CAAC;QACvB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,UAAU,EAClB,CAAC,EAAE,4BAA4B,GAC9B,iBAAiB,CAiDnB;AAED,wFAAwF;AACxF,MAAM,WAAW,aAAa;IAC5B,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACpB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACxC,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrB;AAED,2EAA2E;AAC3E,wBAAsB,uBAAuB,CAC3C,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,aAAa,GACvB,OAAO,CAAC;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAO5D;AAED,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,KAAK,EAAE;IACrC,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,GAAG,aAAa,CAUhB;AAED,OAAO,EAAE,WAAW,EAAE,CAAC"}
|
package/dist/prove.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Withdrawal witness assembly + Groth16 proof generation (spec/privacy-pool.md §4.1).
|
|
3
|
+
* The witness binds the spent commitment's openings, both Merkle inclusion paths, the
|
|
4
|
+
* value accounting, and the contract-supplied `context`. Public-signal order matches
|
|
5
|
+
* the circuit: withdrawn_value, state_root, asp_root, nullifier_hash, new_commitment,
|
|
6
|
+
* context.
|
|
7
|
+
*/
|
|
8
|
+
// @ts-expect-error snarkjs is untyped
|
|
9
|
+
import * as snarkjs from "snarkjs";
|
|
10
|
+
import { PoolMerkleTree, POOL_LEVELS } from "./crypto.js";
|
|
11
|
+
/** Assemble the circuit input + the public values for an on-chain `withdraw` call. */
|
|
12
|
+
export function buildWithdrawalWitness(crypto, p) {
|
|
13
|
+
if (p.withdrawnValue > p.note.value) {
|
|
14
|
+
throw new Error("Opaque pool: withdrawnValue exceeds the note value");
|
|
15
|
+
}
|
|
16
|
+
const stateTree = new PoolMerkleTree(crypto, p.stateLeaves);
|
|
17
|
+
const aspTree = new PoolMerkleTree(crypto, p.aspLeaves);
|
|
18
|
+
const statePath = stateTree.proof(p.stateIndex);
|
|
19
|
+
const aspPath = aspTree.proof(p.aspIndex);
|
|
20
|
+
const remainder = p.note.value - p.withdrawnValue;
|
|
21
|
+
const newCommitment = crypto.commitment(remainder, p.note.label, crypto.precommitment(p.newNullifier, p.newSecret));
|
|
22
|
+
const nullifierHash = crypto.nullifierHash(p.note.nullifier);
|
|
23
|
+
const stateRoot = stateTree.root();
|
|
24
|
+
const aspRoot = aspTree.root();
|
|
25
|
+
const input = {
|
|
26
|
+
value: p.note.value.toString(),
|
|
27
|
+
label: p.note.label.toString(),
|
|
28
|
+
nullifier: p.note.nullifier.toString(),
|
|
29
|
+
secret: p.note.secret.toString(),
|
|
30
|
+
new_nullifier: p.newNullifier.toString(),
|
|
31
|
+
new_secret: p.newSecret.toString(),
|
|
32
|
+
state_siblings: statePath.siblings.map(String),
|
|
33
|
+
state_index: statePath.pathIndices.map(String),
|
|
34
|
+
asp_siblings: aspPath.siblings.map(String),
|
|
35
|
+
asp_index: aspPath.pathIndices.map(String),
|
|
36
|
+
withdrawn_value: p.withdrawnValue.toString(),
|
|
37
|
+
state_root: stateRoot.toString(),
|
|
38
|
+
asp_root: aspRoot.toString(),
|
|
39
|
+
nullifier_hash: nullifierHash.toString(),
|
|
40
|
+
new_commitment: newCommitment.toString(),
|
|
41
|
+
context: p.context.toString(),
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
input,
|
|
45
|
+
publics: {
|
|
46
|
+
withdrawnValue: p.withdrawnValue,
|
|
47
|
+
stateRoot,
|
|
48
|
+
aspRoot,
|
|
49
|
+
nullifierHash,
|
|
50
|
+
newCommitment,
|
|
51
|
+
context: p.context,
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
/** Generate a withdrawal proof and format it for the on-chain verifier. */
|
|
56
|
+
export async function generateWithdrawalProof(witness, artifacts) {
|
|
57
|
+
const { proof, publicSignals } = await snarkjs.groth16.fullProve(witness.input, artifacts.wasmPath, artifacts.zkeyPath);
|
|
58
|
+
return { proof: toSolidityProof(proof), publicSignals };
|
|
59
|
+
}
|
|
60
|
+
/** Convert a snarkjs proof object to the verifier's (a, b, c) calldata shape. */
|
|
61
|
+
export function toSolidityProof(proof) {
|
|
62
|
+
return {
|
|
63
|
+
a: [BigInt(proof.pi_a[0]), BigInt(proof.pi_a[1])],
|
|
64
|
+
// G2 point coordinates are swapped for the EVM pairing precompile.
|
|
65
|
+
b: [
|
|
66
|
+
[BigInt(proof.pi_b[0][1]), BigInt(proof.pi_b[0][0])],
|
|
67
|
+
[BigInt(proof.pi_b[1][1]), BigInt(proof.pi_b[1][0])],
|
|
68
|
+
],
|
|
69
|
+
c: [BigInt(proof.pi_c[0]), BigInt(proof.pi_c[1])],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export { POOL_LEVELS };
|
|
73
|
+
//# sourceMappingURL=prove.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prove.js","sourceRoot":"","sources":["../src/prove.ts"],"names":[],"mappings":"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"}
|
package/dist/tx.d.ts
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deposit / withdraw transaction building for `OpaquePrivacyPool` and the random note
|
|
3
|
+
* generation behind a shielded deposit (spec/privacy-pool.md §5–§6).
|
|
4
|
+
*/
|
|
5
|
+
import { type Address, type Hex } from "viem";
|
|
6
|
+
import { type PoolCrypto } from "./crypto.js";
|
|
7
|
+
import type { SolidityProof } from "./prove.js";
|
|
8
|
+
/** Minimal pool ABI for deposit + withdraw + the reads a client needs. */
|
|
9
|
+
export declare const opaquePrivacyPoolAbi: readonly [{
|
|
10
|
+
readonly type: "function";
|
|
11
|
+
readonly name: "deposit";
|
|
12
|
+
readonly stateMutability: "payable";
|
|
13
|
+
readonly inputs: readonly [{
|
|
14
|
+
readonly name: "precommitment";
|
|
15
|
+
readonly type: "uint256";
|
|
16
|
+
}];
|
|
17
|
+
readonly outputs: readonly [{
|
|
18
|
+
readonly name: "commitment";
|
|
19
|
+
readonly type: "bytes32";
|
|
20
|
+
}];
|
|
21
|
+
}, {
|
|
22
|
+
readonly type: "function";
|
|
23
|
+
readonly name: "withdraw";
|
|
24
|
+
readonly stateMutability: "nonpayable";
|
|
25
|
+
readonly inputs: readonly [{
|
|
26
|
+
readonly name: "a";
|
|
27
|
+
readonly type: "uint256[2]";
|
|
28
|
+
}, {
|
|
29
|
+
readonly name: "b";
|
|
30
|
+
readonly type: "uint256[2][2]";
|
|
31
|
+
}, {
|
|
32
|
+
readonly name: "c";
|
|
33
|
+
readonly type: "uint256[2]";
|
|
34
|
+
}, {
|
|
35
|
+
readonly name: "withdrawnValue";
|
|
36
|
+
readonly type: "uint256";
|
|
37
|
+
}, {
|
|
38
|
+
readonly name: "stateRoot";
|
|
39
|
+
readonly type: "uint256";
|
|
40
|
+
}, {
|
|
41
|
+
readonly name: "nullifierHash";
|
|
42
|
+
readonly type: "uint256";
|
|
43
|
+
}, {
|
|
44
|
+
readonly name: "newCommitment";
|
|
45
|
+
readonly type: "uint256";
|
|
46
|
+
}, {
|
|
47
|
+
readonly name: "params";
|
|
48
|
+
readonly type: "tuple";
|
|
49
|
+
readonly components: readonly [{
|
|
50
|
+
readonly name: "recipient";
|
|
51
|
+
readonly type: "address";
|
|
52
|
+
}, {
|
|
53
|
+
readonly name: "feeRecipient";
|
|
54
|
+
readonly type: "address";
|
|
55
|
+
}, {
|
|
56
|
+
readonly name: "fee";
|
|
57
|
+
readonly type: "uint256";
|
|
58
|
+
}];
|
|
59
|
+
}];
|
|
60
|
+
readonly outputs: readonly [];
|
|
61
|
+
}, {
|
|
62
|
+
readonly type: "function";
|
|
63
|
+
readonly name: "scope";
|
|
64
|
+
readonly stateMutability: "view";
|
|
65
|
+
readonly inputs: readonly [];
|
|
66
|
+
readonly outputs: readonly [{
|
|
67
|
+
readonly type: "uint256";
|
|
68
|
+
}];
|
|
69
|
+
}, {
|
|
70
|
+
readonly type: "function";
|
|
71
|
+
readonly name: "aspRoot";
|
|
72
|
+
readonly stateMutability: "view";
|
|
73
|
+
readonly inputs: readonly [];
|
|
74
|
+
readonly outputs: readonly [{
|
|
75
|
+
readonly type: "uint256";
|
|
76
|
+
}];
|
|
77
|
+
}, {
|
|
78
|
+
readonly type: "function";
|
|
79
|
+
readonly name: "context";
|
|
80
|
+
readonly stateMutability: "view";
|
|
81
|
+
readonly inputs: readonly [{
|
|
82
|
+
readonly name: "params";
|
|
83
|
+
readonly type: "tuple";
|
|
84
|
+
readonly components: readonly [{
|
|
85
|
+
readonly name: "recipient";
|
|
86
|
+
readonly type: "address";
|
|
87
|
+
}, {
|
|
88
|
+
readonly name: "feeRecipient";
|
|
89
|
+
readonly type: "address";
|
|
90
|
+
}, {
|
|
91
|
+
readonly name: "fee";
|
|
92
|
+
readonly type: "uint256";
|
|
93
|
+
}];
|
|
94
|
+
}];
|
|
95
|
+
readonly outputs: readonly [{
|
|
96
|
+
readonly type: "uint256";
|
|
97
|
+
}];
|
|
98
|
+
}];
|
|
99
|
+
/** Payout parameters bound into the withdrawal proof's `context`. */
|
|
100
|
+
export interface WithdrawalParams {
|
|
101
|
+
recipient: Address;
|
|
102
|
+
feeRecipient: Address;
|
|
103
|
+
fee: bigint;
|
|
104
|
+
}
|
|
105
|
+
/** A freshly generated deposit note: secret openings the user must keep to withdraw. */
|
|
106
|
+
export interface DepositNote {
|
|
107
|
+
nullifier: bigint;
|
|
108
|
+
secret: bigint;
|
|
109
|
+
precommitment: bigint;
|
|
110
|
+
}
|
|
111
|
+
/** Generate fresh `(nullifier, secret)` and the `precommitment` to deposit. */
|
|
112
|
+
export declare function generateDepositNote(crypto: PoolCrypto, randomBytes: (n: number) => Uint8Array): DepositNote;
|
|
113
|
+
/** EVM transaction request the depositor sends (value = deposit amount). */
|
|
114
|
+
export interface EvmTxRequest {
|
|
115
|
+
to: Address;
|
|
116
|
+
data: Hex;
|
|
117
|
+
value: bigint;
|
|
118
|
+
}
|
|
119
|
+
/** Build the `deposit(precommitment)` call. */
|
|
120
|
+
export declare function buildDepositTx(pool: Address, note: DepositNote, value: bigint): EvmTxRequest;
|
|
121
|
+
/** Build the `withdraw(...)` calldata from a proof + public values + payout params. */
|
|
122
|
+
export declare function buildWithdrawTx(pool: Address, proof: SolidityProof, publics: {
|
|
123
|
+
withdrawnValue: bigint;
|
|
124
|
+
stateRoot: bigint;
|
|
125
|
+
nullifierHash: bigint;
|
|
126
|
+
newCommitment: bigint;
|
|
127
|
+
}, params: WithdrawalParams): EvmTxRequest;
|
|
128
|
+
//# sourceMappingURL=tx.d.ts.map
|
package/dist/tx.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tx.d.ts","sourceRoot":"","sources":["../src/tx.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAsB,KAAK,OAAO,EAAE,KAAK,GAAG,EAAE,MAAM,MAAM,CAAC;AAClE,OAAO,EAAS,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,0EAA0E;AAC1E,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA6CvB,CAAC;AAEX,qEAAqE;AACrE,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,YAAY,EAAE,OAAO,CAAC;IACtB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wFAAwF;AACxF,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;CACvB;AASD,+EAA+E;AAC/E,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,UAAU,GACrC,WAAW,CAIb;AAED,4EAA4E;AAC5E,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,GAAG,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;CACf;AAED,+CAA+C;AAC/C,wBAAgB,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAU5F;AAED,uFAAuF;AACvF,wBAAgB,eAAe,CAC7B,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE;IACP,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;CACvB,EACD,MAAM,EAAE,gBAAgB,GACvB,YAAY,CAmBd"}
|
package/dist/tx.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deposit / withdraw transaction building for `OpaquePrivacyPool` and the random note
|
|
3
|
+
* generation behind a shielded deposit (spec/privacy-pool.md §5–§6).
|
|
4
|
+
*/
|
|
5
|
+
import { encodeFunctionData } from "viem";
|
|
6
|
+
import { FIELD } from "./crypto.js";
|
|
7
|
+
/** Minimal pool ABI for deposit + withdraw + the reads a client needs. */
|
|
8
|
+
export const opaquePrivacyPoolAbi = [
|
|
9
|
+
{
|
|
10
|
+
type: "function",
|
|
11
|
+
name: "deposit",
|
|
12
|
+
stateMutability: "payable",
|
|
13
|
+
inputs: [{ name: "precommitment", type: "uint256" }],
|
|
14
|
+
outputs: [{ name: "commitment", type: "bytes32" }],
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: "function",
|
|
18
|
+
name: "withdraw",
|
|
19
|
+
stateMutability: "nonpayable",
|
|
20
|
+
inputs: [
|
|
21
|
+
{ name: "a", type: "uint256[2]" },
|
|
22
|
+
{ name: "b", type: "uint256[2][2]" },
|
|
23
|
+
{ name: "c", type: "uint256[2]" },
|
|
24
|
+
{ name: "withdrawnValue", type: "uint256" },
|
|
25
|
+
{ name: "stateRoot", type: "uint256" },
|
|
26
|
+
{ name: "nullifierHash", type: "uint256" },
|
|
27
|
+
{ name: "newCommitment", type: "uint256" },
|
|
28
|
+
{
|
|
29
|
+
name: "params",
|
|
30
|
+
type: "tuple",
|
|
31
|
+
components: [
|
|
32
|
+
{ name: "recipient", type: "address" },
|
|
33
|
+
{ name: "feeRecipient", type: "address" },
|
|
34
|
+
{ name: "fee", type: "uint256" },
|
|
35
|
+
],
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
outputs: [],
|
|
39
|
+
},
|
|
40
|
+
{ type: "function", name: "scope", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
|
|
41
|
+
{ type: "function", name: "aspRoot", stateMutability: "view", inputs: [], outputs: [{ type: "uint256" }] },
|
|
42
|
+
{
|
|
43
|
+
type: "function",
|
|
44
|
+
name: "context",
|
|
45
|
+
stateMutability: "view",
|
|
46
|
+
inputs: [{ name: "params", type: "tuple", components: [
|
|
47
|
+
{ name: "recipient", type: "address" },
|
|
48
|
+
{ name: "feeRecipient", type: "address" },
|
|
49
|
+
{ name: "fee", type: "uint256" },
|
|
50
|
+
] }],
|
|
51
|
+
outputs: [{ type: "uint256" }],
|
|
52
|
+
},
|
|
53
|
+
];
|
|
54
|
+
/** A uniformly random field element from injected randomness. */
|
|
55
|
+
function randomField(randomBytes) {
|
|
56
|
+
let x = 0n;
|
|
57
|
+
for (const byte of randomBytes(32))
|
|
58
|
+
x = (x << 8n) | BigInt(byte);
|
|
59
|
+
return x % FIELD;
|
|
60
|
+
}
|
|
61
|
+
/** Generate fresh `(nullifier, secret)` and the `precommitment` to deposit. */
|
|
62
|
+
export function generateDepositNote(crypto, randomBytes) {
|
|
63
|
+
const nullifier = randomField(randomBytes);
|
|
64
|
+
const secret = randomField(randomBytes);
|
|
65
|
+
return { nullifier, secret, precommitment: crypto.precommitment(nullifier, secret) };
|
|
66
|
+
}
|
|
67
|
+
/** Build the `deposit(precommitment)` call. */
|
|
68
|
+
export function buildDepositTx(pool, note, value) {
|
|
69
|
+
return {
|
|
70
|
+
to: pool,
|
|
71
|
+
data: encodeFunctionData({
|
|
72
|
+
abi: opaquePrivacyPoolAbi,
|
|
73
|
+
functionName: "deposit",
|
|
74
|
+
args: [note.precommitment],
|
|
75
|
+
}),
|
|
76
|
+
value,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Build the `withdraw(...)` calldata from a proof + public values + payout params. */
|
|
80
|
+
export function buildWithdrawTx(pool, proof, publics, params) {
|
|
81
|
+
return {
|
|
82
|
+
to: pool,
|
|
83
|
+
data: encodeFunctionData({
|
|
84
|
+
abi: opaquePrivacyPoolAbi,
|
|
85
|
+
functionName: "withdraw",
|
|
86
|
+
args: [
|
|
87
|
+
proof.a,
|
|
88
|
+
proof.b,
|
|
89
|
+
proof.c,
|
|
90
|
+
publics.withdrawnValue,
|
|
91
|
+
publics.stateRoot,
|
|
92
|
+
publics.nullifierHash,
|
|
93
|
+
publics.newCommitment,
|
|
94
|
+
params,
|
|
95
|
+
],
|
|
96
|
+
}),
|
|
97
|
+
value: 0n,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=tx.js.map
|
package/dist/tx.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tx.js","sourceRoot":"","sources":["../src/tx.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@opaquecash/privacy-pool",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Privacy pool client: deposit commitments, Poseidon Merkle trees, withdrawal witness + Groth16 proof generation, and deposit/withdraw tx building (spec/privacy-pool.md)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc -p tsconfig.json",
|
|
19
|
+
"clean": "rm -rf dist"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"@opaquecash/deployments": "0.2.0",
|
|
23
|
+
"circomlibjs": "^0.1.7",
|
|
24
|
+
"snarkjs": "^0.7.5",
|
|
25
|
+
"viem": "^2.21.0"
|
|
26
|
+
},
|
|
27
|
+
"sideEffects": false,
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/opaquecash/sdk.git",
|
|
32
|
+
"directory": "packages/privacy-pool"
|
|
33
|
+
},
|
|
34
|
+
"homepage": "https://docs.opaque.cash",
|
|
35
|
+
"publishConfig": {
|
|
36
|
+
"access": "public"
|
|
37
|
+
}
|
|
38
|
+
}
|