mirror of
https://github.com/tornadocash/tornado-nova
synced 2024-02-02 14:53:56 +01:00
transaaction circuit with custom input count
This commit is contained in:
parent
a19a226277
commit
960b6adb30
@ -14,7 +14,7 @@ commitment = hash(amount, blinding, pubKey)
|
|||||||
nullifier = hash(commitment, privKey, merklePath)
|
nullifier = hash(commitment, privKey, merklePath)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Universal JoinSplit transaction with 2 inputs and 2 outputs
|
// Universal JoinSplit transaction with nIns inputs and 2 outputs
|
||||||
template Transaction(levels, nIns, nOuts, zeroLeaf) {
|
template Transaction(levels, nIns, nOuts, zeroLeaf) {
|
||||||
signal input root;
|
signal input root;
|
||||||
signal input newRoot;
|
signal input newRoot;
|
||||||
@ -107,10 +107,18 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) {
|
|||||||
component feeCheck = Num2Bits(248);
|
component feeCheck = Num2Bits(248);
|
||||||
feeCheck.in <== fee;
|
feeCheck.in <== fee;
|
||||||
|
|
||||||
component sameNullifiers = IsEqual();
|
// check that there are no same nullifiers among all inputs
|
||||||
sameNullifiers.in[0] <== inputNullifier[0];
|
component sameNullifiers[nIns * (nIns - 1) / 2];
|
||||||
sameNullifiers.in[1] <== inputNullifier[1];
|
var index = 0;
|
||||||
sameNullifiers.out === 0;
|
for (var i = 0; i < nIns - 1; i++) {
|
||||||
|
for (var j = i + 1; j < nIns; j++) {
|
||||||
|
sameNullifiers[index] = IsEqual();
|
||||||
|
sameNullifiers[index].in[0] <== inputNullifier[i];
|
||||||
|
sameNullifiers[index].in[1] <== inputNullifier[j];
|
||||||
|
sameNullifiers[index].out === 0;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// verify amount invariant
|
// verify amount invariant
|
||||||
sumIns + extAmount === sumOuts + fee;
|
sumIns + extAmount === sumOuts + fee;
|
||||||
@ -119,8 +127,9 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) {
|
|||||||
component treeUpdater = TreeUpdater(levels, zeroLeaf);
|
component treeUpdater = TreeUpdater(levels, zeroLeaf);
|
||||||
treeUpdater.oldRoot <== root;
|
treeUpdater.oldRoot <== root;
|
||||||
treeUpdater.newRoot <== newRoot;
|
treeUpdater.newRoot <== newRoot;
|
||||||
treeUpdater.leaf[0] <== outputCommitment[0];
|
for (var i = 0; i < nOuts; i++) {
|
||||||
treeUpdater.leaf[1] <== outputCommitment[1];
|
treeUpdater.leaf[i] <== outputCommitment[i];
|
||||||
|
}
|
||||||
treeUpdater.pathIndices <== outPathIndices;
|
treeUpdater.pathIndices <== outPathIndices;
|
||||||
for (var i = 0; i < levels - 1; i++) {
|
for (var i = 0; i < levels - 1; i++) {
|
||||||
treeUpdater.pathElements[i] <== outPathElements[i];
|
treeUpdater.pathElements[i] <== outPathElements[i];
|
||||||
|
@ -17,6 +17,7 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; // todo: maybe remov
|
|||||||
|
|
||||||
interface IVerifier {
|
interface IVerifier {
|
||||||
function verifyProof(bytes memory _proof, uint256[9] memory _input) external returns(bool);
|
function verifyProof(bytes memory _proof, uint256[9] memory _input) external returns(bool);
|
||||||
|
function verifyProof(bytes memory _proof, uint256[23] memory _input) external returns(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
contract TornadoPool is ReentrancyGuard {
|
contract TornadoPool is ReentrancyGuard {
|
||||||
@ -26,7 +27,8 @@ contract TornadoPool is ReentrancyGuard {
|
|||||||
mapping(bytes32 => bool) public nullifierHashes;
|
mapping(bytes32 => bool) public nullifierHashes;
|
||||||
bytes32 public currentRoot;
|
bytes32 public currentRoot;
|
||||||
uint public currentCommitmentIndex;
|
uint public currentCommitmentIndex;
|
||||||
IVerifier public verifier;
|
IVerifier public verifier2;
|
||||||
|
IVerifier public verifier16;
|
||||||
|
|
||||||
struct ExtData {
|
struct ExtData {
|
||||||
address payable recipient;
|
address payable recipient;
|
||||||
@ -42,10 +44,12 @@ contract TornadoPool is ReentrancyGuard {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
@dev The constructor
|
@dev The constructor
|
||||||
@param _verifier the address of SNARK verifier for this contract
|
@param _verifier2 the address of SNARK verifier for this contract
|
||||||
|
@param _verifier16 the address of SNARK verifier for this contract
|
||||||
*/
|
*/
|
||||||
constructor(IVerifier _verifier, bytes32 _currentRoot) public {
|
constructor(IVerifier _verifier2, IVerifier _verifier16, bytes32 _currentRoot) public {
|
||||||
verifier = _verifier;
|
verifier2 = _verifier2;
|
||||||
|
verifier16 = _verifier16;
|
||||||
currentRoot = _currentRoot;
|
currentRoot = _currentRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -66,7 +70,7 @@ contract TornadoPool is ReentrancyGuard {
|
|||||||
require(!isSpent(_inputNullifiers[0]), "Input 0 is already spent");
|
require(!isSpent(_inputNullifiers[0]), "Input 0 is already spent");
|
||||||
require(!isSpent(_inputNullifiers[1]), "Input 1 is already spent");
|
require(!isSpent(_inputNullifiers[1]), "Input 1 is already spent");
|
||||||
require(uint256(_extDataHash) == uint256(keccak256(abi.encode(_extData))) % FIELD_SIZE, "Incorrect external data hash");
|
require(uint256(_extDataHash) == uint256(keccak256(abi.encode(_extData))) % FIELD_SIZE, "Incorrect external data hash");
|
||||||
require(verifier.verifyProof(_proof, [
|
require(verifier2.verifyProof(_proof, [
|
||||||
uint256(_root),
|
uint256(_root),
|
||||||
uint256(_newRoot),
|
uint256(_newRoot),
|
||||||
uint256(_inputNullifiers[0]),
|
uint256(_inputNullifiers[0]),
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../artifacts/circuits/Verifier.sol
|
|
1
contracts/Verifier16.sol
Symbolic link
1
contracts/Verifier16.sol
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../artifacts/circuits/Verifier16.sol
|
1
contracts/Verifier2.sol
Symbolic link
1
contracts/Verifier2.sol
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../artifacts/circuits/Verifier2.sol
|
@ -7,11 +7,10 @@
|
|||||||
"test": "test"
|
"test": "test"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"circuit": "./scripts/buildCircuit.sh transaction2 && ./scripts/buildCircuit.sh transaction16",
|
"circuit": "./scripts/buildCircuit.sh 2 && ./scripts/buildCircuit.sh 16",
|
||||||
"compile": "npx hardhat compile",
|
"compile": "npx hardhat compile",
|
||||||
"build": "npm run circuit && npm run compile",
|
"build": "npm run circuit && npm run compile",
|
||||||
"migrate": "npx hardhat run scripts/deploy.js --network localhost",
|
"test": "npx hardhat test"
|
||||||
"start": "node ./src/index.js"
|
|
||||||
},
|
},
|
||||||
"keywords": [],
|
"keywords": [],
|
||||||
"author": "",
|
"author": "",
|
||||||
@ -32,7 +31,7 @@
|
|||||||
"ffjavascript": "^0.2.36",
|
"ffjavascript": "^0.2.36",
|
||||||
"fixed-merkle-tree": "^0.5.0",
|
"fixed-merkle-tree": "^0.5.0",
|
||||||
"hardhat": "^2.3.0",
|
"hardhat": "^2.3.0",
|
||||||
"snarkjs": "^0.4.5",
|
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#c103e3bf10e95e2e9bbf0f7952ed13812f8e39d3",
|
||||||
"tmp-promise": "^3.0.2"
|
"tmp-promise": "^3.0.2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,10 +8,11 @@ if [ ! -f artifacts/circuits/ptau$POWERS_OF_TAU ]; then
|
|||||||
npx snarkjs powersoftau prepare phase2 artifacts/circuits/tmp2_ptau$POWERS_OF_TAU artifacts/circuits/ptau$POWERS_OF_TAU
|
npx snarkjs powersoftau prepare phase2 artifacts/circuits/tmp2_ptau$POWERS_OF_TAU artifacts/circuits/ptau$POWERS_OF_TAU
|
||||||
rm artifacts/circuits/tmp_ptau$POWERS_OF_TAU artifacts/circuits/tmp2_ptau$POWERS_OF_TAU
|
rm artifacts/circuits/tmp_ptau$POWERS_OF_TAU artifacts/circuits/tmp2_ptau$POWERS_OF_TAU
|
||||||
fi
|
fi
|
||||||
npx circom -v -r artifacts/circuits/$1.r1cs -w artifacts/circuits/$1.wasm -s artifacts/circuits/$1.sym circuits/$1.circom
|
npx circom -v -r artifacts/circuits/transaction$1.r1cs -w artifacts/circuits/transaction$1.wasm -s artifacts/circuits/transaction$1.sym circuits/transaction$1.circom
|
||||||
npx snarkjs groth16 setup artifacts/circuits/$1.r1cs artifacts/circuits/ptau$POWERS_OF_TAU artifacts/circuits/tmp_$1.zkey
|
npx snarkjs groth16 setup artifacts/circuits/transaction$1.r1cs artifacts/circuits/ptau$POWERS_OF_TAU artifacts/circuits/tmp_transaction$1.zkey
|
||||||
npx snarkjs zkey contribute artifacts/circuits/tmp_$1.zkey artifacts/circuits/$1.zkey
|
npx snarkjs zkey contribute artifacts/circuits/tmp_transaction$1.zkey artifacts/circuits/transaction$1.zkey
|
||||||
npx snarkjs zkey export solidityverifier artifacts/circuits/$1.zkey artifacts/circuits/Verifier.sol
|
npx snarkjs zkey export solidityverifier artifacts/circuits/transaction$1.zkey artifacts/circuits/Verifier$1.sol
|
||||||
#zkutil setup -c artifacts/circuits/$1.r1cs -p artifacts/circuits/$1.params
|
sed -i.bak "s/contract Verifier/contract Verifier${1}/g" artifacts/circuits/Verifier$1.sol
|
||||||
#zkutil generate-verifier -p artifacts/circuits/$1.params -v artifacts/circuits/Verifier.sol
|
#zkutil setup -c artifacts/circuits/transaction$1.r1cs -p artifacts/circuits/transaction$1.params
|
||||||
npx snarkjs info -r artifacts/circuits/$1.r1cs
|
#zkutil generate-verifier -p artifacts/circuits/transaction$1.params -v artifacts/circuits/Verifier.sol
|
||||||
|
npx snarkjs info -r artifacts/circuits/transaction$1.r1cs
|
||||||
|
@ -14,16 +14,21 @@ const toFixedHex = (number, length = 32) =>
|
|||||||
).padStart(length * 2, '0')
|
).padStart(length * 2, '0')
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const Verifier = await ethers.getContractFactory('Verifier')
|
const Verifier2 = await ethers.getContractFactory('Verifier2')
|
||||||
const verifier = await Verifier.deploy()
|
const verifier2 = await Verifier2.deploy()
|
||||||
await verifier.deployed()
|
await verifier2.deployed()
|
||||||
console.log(`verifier: ${verifier.address}`)
|
console.log(`verifier2: ${verifier2.address}`)
|
||||||
|
|
||||||
|
const Verifier16 = await ethers.getContractFactory('Verifier16')
|
||||||
|
const verifier16 = await Verifier16.deploy()
|
||||||
|
await verifier16.deployed()
|
||||||
|
console.log(`verifier16: ${verifier16.address}`)
|
||||||
|
|
||||||
const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 })
|
const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 })
|
||||||
const root = await tree.root()
|
const root = await tree.root()
|
||||||
|
|
||||||
const Pool = await ethers.getContractFactory('TornadoPool')
|
const Pool = await ethers.getContractFactory('TornadoPool')
|
||||||
const tornado = await Pool.deploy(verifier.address, toFixedHex(root))
|
const tornado = await Pool.deploy(verifier2.address, verifier16.address, toFixedHex(root))
|
||||||
console.log("TornadoPool's address ", tornado.address)
|
console.log("TornadoPool's address ", tornado.address)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,15 +14,19 @@ describe('TornadoPool', () => {
|
|||||||
|
|
||||||
/* prettier-ignore */
|
/* prettier-ignore */
|
||||||
before(async function () {
|
before(async function () {
|
||||||
const Verifier = await ethers.getContractFactory('Verifier')
|
const Verifier2 = await ethers.getContractFactory('Verifier2')
|
||||||
const verifier = await Verifier.deploy()
|
const verifier2 = await Verifier2.deploy()
|
||||||
await verifier.deployed()
|
await verifier2.deployed()
|
||||||
|
|
||||||
|
const Verifier16 = await ethers.getContractFactory('Verifier16')
|
||||||
|
const verifier16 = await Verifier16.deploy()
|
||||||
|
await verifier16.deployed()
|
||||||
|
|
||||||
const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 })
|
const tree = new MerkleTree(MERKLE_TREE_HEIGHT, [], { hashFunction: poseidonHash2 })
|
||||||
const root = await tree.root()
|
const root = await tree.root()
|
||||||
|
|
||||||
const Pool = await ethers.getContractFactory('TornadoPool')
|
const Pool = await ethers.getContractFactory('TornadoPool')
|
||||||
tornadoPool = await Pool.deploy(verifier.address, toFixedHex(root))
|
tornadoPool = await Pool.deploy(verifier2.address, verifier16.address, toFixedHex(root))
|
||||||
|
|
||||||
snapshotId = await takeSnapshot()
|
snapshotId = await takeSnapshot()
|
||||||
})
|
})
|
||||||
|
27
yarn.lock
27
yarn.lock
@ -7423,10 +7423,20 @@ snapdragon@^0.8.1:
|
|||||||
source-map-resolve "^0.5.0"
|
source-map-resolve "^0.5.0"
|
||||||
use "^3.1.0"
|
use "^3.1.0"
|
||||||
|
|
||||||
snarkjs@^0.4.5:
|
"snarkjs@git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5":
|
||||||
|
version "0.1.20"
|
||||||
|
resolved "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
|
||||||
|
dependencies:
|
||||||
|
big-integer "^1.6.43"
|
||||||
|
chai "^4.2.0"
|
||||||
|
escape-string-regexp "^1.0.5"
|
||||||
|
eslint "^5.16.0"
|
||||||
|
keccak "^2.0.0"
|
||||||
|
yargs "^12.0.5"
|
||||||
|
|
||||||
|
"snarkjs@git+https://github.com/tornadocash/snarkjs.git#c103e3bf10e95e2e9bbf0f7952ed13812f8e39d3":
|
||||||
version "0.4.5"
|
version "0.4.5"
|
||||||
resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.4.5.tgz#c7246b0bdcdafd25c67c0ecc395556715b059a14"
|
resolved "git+https://github.com/tornadocash/snarkjs.git#c103e3bf10e95e2e9bbf0f7952ed13812f8e39d3"
|
||||||
integrity sha512-rgxbp3JMhGdPgkhCrssq+a4Bv2vm2QucWwK9QG5cdyRRpx8f5EOpyMPy7pi/U8VUyyyulAaDowKBf7x7chB7zg==
|
|
||||||
dependencies:
|
dependencies:
|
||||||
"@iden3/binfileutils" "0.0.8"
|
"@iden3/binfileutils" "0.0.8"
|
||||||
blake2b-wasm "https://github.com/jbaylina/blake2b-wasm.git"
|
blake2b-wasm "https://github.com/jbaylina/blake2b-wasm.git"
|
||||||
@ -7439,17 +7449,6 @@ snarkjs@^0.4.5:
|
|||||||
r1csfile "0.0.32"
|
r1csfile "0.0.32"
|
||||||
readline "^1.3.0"
|
readline "^1.3.0"
|
||||||
|
|
||||||
"snarkjs@git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5":
|
|
||||||
version "0.1.20"
|
|
||||||
resolved "git+https://github.com/tornadocash/snarkjs.git#869181cfaf7526fe8972073d31655493a04326d5"
|
|
||||||
dependencies:
|
|
||||||
big-integer "^1.6.43"
|
|
||||||
chai "^4.2.0"
|
|
||||||
escape-string-regexp "^1.0.5"
|
|
||||||
eslint "^5.16.0"
|
|
||||||
keccak "^2.0.0"
|
|
||||||
yargs "^12.0.5"
|
|
||||||
|
|
||||||
solc@0.7.3:
|
solc@0.7.3:
|
||||||
version "0.7.3"
|
version "0.7.3"
|
||||||
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
|
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"
|
||||||
|
Loading…
Reference in New Issue
Block a user