transaaction circuit with custom input count

This commit is contained in:
poma 2021-06-15 14:25:06 +03:00
parent a19a226277
commit 960b6adb30
No known key found for this signature in database
GPG Key ID: BA20CB01FE165657
10 changed files with 69 additions and 47 deletions

View File

@ -14,7 +14,7 @@ commitment = hash(amount, blinding, pubKey)
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) {
signal input root;
signal input newRoot;
@ -107,10 +107,18 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) {
component feeCheck = Num2Bits(248);
feeCheck.in <== fee;
component sameNullifiers = IsEqual();
sameNullifiers.in[0] <== inputNullifier[0];
sameNullifiers.in[1] <== inputNullifier[1];
sameNullifiers.out === 0;
// check that there are no same nullifiers among all inputs
component sameNullifiers[nIns * (nIns - 1) / 2];
var index = 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
sumIns + extAmount === sumOuts + fee;
@ -119,8 +127,9 @@ template Transaction(levels, nIns, nOuts, zeroLeaf) {
component treeUpdater = TreeUpdater(levels, zeroLeaf);
treeUpdater.oldRoot <== root;
treeUpdater.newRoot <== newRoot;
treeUpdater.leaf[0] <== outputCommitment[0];
treeUpdater.leaf[1] <== outputCommitment[1];
for (var i = 0; i < nOuts; i++) {
treeUpdater.leaf[i] <== outputCommitment[i];
}
treeUpdater.pathIndices <== outPathIndices;
for (var i = 0; i < levels - 1; i++) {
treeUpdater.pathElements[i] <== outPathElements[i];

View File

@ -17,6 +17,7 @@ import "@openzeppelin/contracts/utils/ReentrancyGuard.sol"; // todo: maybe remov
interface IVerifier {
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 {
@ -26,7 +27,8 @@ contract TornadoPool is ReentrancyGuard {
mapping(bytes32 => bool) public nullifierHashes;
bytes32 public currentRoot;
uint public currentCommitmentIndex;
IVerifier public verifier;
IVerifier public verifier2;
IVerifier public verifier16;
struct ExtData {
address payable recipient;
@ -42,10 +44,12 @@ contract TornadoPool is ReentrancyGuard {
/**
@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 {
verifier = _verifier;
constructor(IVerifier _verifier2, IVerifier _verifier16, bytes32 _currentRoot) public {
verifier2 = _verifier2;
verifier16 = _verifier16;
currentRoot = _currentRoot;
}
@ -66,7 +70,7 @@ contract TornadoPool is ReentrancyGuard {
require(!isSpent(_inputNullifiers[0]), "Input 0 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(verifier.verifyProof(_proof, [
require(verifier2.verifyProof(_proof, [
uint256(_root),
uint256(_newRoot),
uint256(_inputNullifiers[0]),

View File

@ -1 +0,0 @@
../artifacts/circuits/Verifier.sol

1
contracts/Verifier16.sol Symbolic link
View File

@ -0,0 +1 @@
../artifacts/circuits/Verifier16.sol

1
contracts/Verifier2.sol Symbolic link
View File

@ -0,0 +1 @@
../artifacts/circuits/Verifier2.sol

View File

@ -7,11 +7,10 @@
"test": "test"
},
"scripts": {
"circuit": "./scripts/buildCircuit.sh transaction2 && ./scripts/buildCircuit.sh transaction16",
"circuit": "./scripts/buildCircuit.sh 2 && ./scripts/buildCircuit.sh 16",
"compile": "npx hardhat compile",
"build": "npm run circuit && npm run compile",
"migrate": "npx hardhat run scripts/deploy.js --network localhost",
"start": "node ./src/index.js"
"test": "npx hardhat test"
},
"keywords": [],
"author": "",
@ -32,7 +31,7 @@
"ffjavascript": "^0.2.36",
"fixed-merkle-tree": "^0.5.0",
"hardhat": "^2.3.0",
"snarkjs": "^0.4.5",
"snarkjs": "git+https://github.com/tornadocash/snarkjs.git#c103e3bf10e95e2e9bbf0f7952ed13812f8e39d3",
"tmp-promise": "^3.0.2"
}
}

View File

@ -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
rm artifacts/circuits/tmp_ptau$POWERS_OF_TAU artifacts/circuits/tmp2_ptau$POWERS_OF_TAU
fi
npx circom -v -r artifacts/circuits/$1.r1cs -w artifacts/circuits/$1.wasm -s artifacts/circuits/$1.sym circuits/$1.circom
npx snarkjs groth16 setup artifacts/circuits/$1.r1cs artifacts/circuits/ptau$POWERS_OF_TAU artifacts/circuits/tmp_$1.zkey
npx snarkjs zkey contribute artifacts/circuits/tmp_$1.zkey artifacts/circuits/$1.zkey
npx snarkjs zkey export solidityverifier artifacts/circuits/$1.zkey artifacts/circuits/Verifier.sol
#zkutil setup -c artifacts/circuits/$1.r1cs -p artifacts/circuits/$1.params
#zkutil generate-verifier -p artifacts/circuits/$1.params -v artifacts/circuits/Verifier.sol
npx snarkjs info -r artifacts/circuits/$1.r1cs
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/transaction$1.r1cs artifacts/circuits/ptau$POWERS_OF_TAU artifacts/circuits/tmp_transaction$1.zkey
npx snarkjs zkey contribute artifacts/circuits/tmp_transaction$1.zkey artifacts/circuits/transaction$1.zkey
npx snarkjs zkey export solidityverifier artifacts/circuits/transaction$1.zkey artifacts/circuits/Verifier$1.sol
sed -i.bak "s/contract Verifier/contract Verifier${1}/g" artifacts/circuits/Verifier$1.sol
#zkutil setup -c artifacts/circuits/transaction$1.r1cs -p artifacts/circuits/transaction$1.params
#zkutil generate-verifier -p artifacts/circuits/transaction$1.params -v artifacts/circuits/Verifier.sol
npx snarkjs info -r artifacts/circuits/transaction$1.r1cs

View File

@ -14,16 +14,21 @@ const toFixedHex = (number, length = 32) =>
).padStart(length * 2, '0')
async function main() {
const Verifier = await ethers.getContractFactory('Verifier')
const verifier = await Verifier.deploy()
await verifier.deployed()
console.log(`verifier: ${verifier.address}`)
const Verifier2 = await ethers.getContractFactory('Verifier2')
const verifier2 = await Verifier2.deploy()
await verifier2.deployed()
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 root = await tree.root()
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)
}

View File

@ -14,15 +14,19 @@ describe('TornadoPool', () => {
/* prettier-ignore */
before(async function () {
const Verifier = await ethers.getContractFactory('Verifier')
const verifier = await Verifier.deploy()
await verifier.deployed()
const Verifier2 = await ethers.getContractFactory('Verifier2')
const verifier2 = await Verifier2.deploy()
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 root = await tree.root()
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()
})

View File

@ -7423,10 +7423,20 @@ snapdragon@^0.8.1:
source-map-resolve "^0.5.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"
resolved "https://registry.yarnpkg.com/snarkjs/-/snarkjs-0.4.5.tgz#c7246b0bdcdafd25c67c0ecc395556715b059a14"
integrity sha512-rgxbp3JMhGdPgkhCrssq+a4Bv2vm2QucWwK9QG5cdyRRpx8f5EOpyMPy7pi/U8VUyyyulAaDowKBf7x7chB7zg==
resolved "git+https://github.com/tornadocash/snarkjs.git#c103e3bf10e95e2e9bbf0f7952ed13812f8e39d3"
dependencies:
"@iden3/binfileutils" "0.0.8"
blake2b-wasm "https://github.com/jbaylina/blake2b-wasm.git"
@ -7439,17 +7449,6 @@ snarkjs@^0.4.5:
r1csfile "0.0.32"
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:
version "0.7.3"
resolved "https://registry.yarnpkg.com/solc/-/solc-0.7.3.tgz#04646961bd867a744f63d2b4e3c0701ffdc7d78a"