@ -0,0 +1,84 @@ |
|||||
|
/* |
||||
|
|
||||
|
# deposit.circom |
||||
|
|
||||
|
+----------+ +----------+ |
||||
|
PUB_nullifier+------>+ | | | |
||||
|
| | | SMT | |
||||
|
PUB_coinCode+------->+ | | Poseidon +<------+PUB_rootOld |
||||
|
| Poseidon +-+----------->+ Verifier | |
||||
|
PUB_amount+--------->+ | | | Non | |
||||
|
| | | | Existance+<------+PRI_siblings |
||||
|
PRI_secret+--------->+ | | | | + |
||||
|
+----------+ | +----------+ | |
||||
|
| | |
||||
|
| | |
||||
|
| +----------+ | |
||||
|
| | | | |
||||
|
| | | | |
||||
|
+----+ | | SMT +<---------+ |
||||
|
PUB_commitment+----> == +<--------+----------->+ Poseidon | |
||||
|
+----+ | Verifier | |
||||
|
| +<------+PUB_rootNew |
||||
|
| | |
||||
|
+----------+ |
||||
|
|
||||
|
|
||||
|
*/ |
||||
|
|
||||
|
include "../node_modules/circomlib/circuits/comparators.circom"; |
||||
|
include "../node_modules/circomlib/circuits/poseidon.circom"; |
||||
|
include "../node_modules/circomlib/circuits/smt/smtverifier.circom"; |
||||
|
|
||||
|
template Deposit(nLevels) { |
||||
|
signal input coinCode; |
||||
|
signal input amount; |
||||
|
signal private input secret; |
||||
|
signal input nullifier; |
||||
|
signal private input siblingsOld[nLevels]; |
||||
|
signal private input siblingsNew[nLevels]; |
||||
|
signal input rootOld; |
||||
|
signal input rootNew; |
||||
|
signal input commitment; |
||||
|
|
||||
|
component hash = Poseidon(4, 6, 8, 57); |
||||
|
hash.inputs[0] <== coinCode; |
||||
|
hash.inputs[1] <== amount; |
||||
|
hash.inputs[2] <== secret; |
||||
|
hash.inputs[3] <== nullifier; |
||||
|
|
||||
|
component comCheck = IsEqual(); |
||||
|
comCheck.in[0] <== hash.out; |
||||
|
comCheck.in[1] <== commitment; |
||||
|
comCheck.out === 1; |
||||
|
|
||||
|
// TODO instead of 2 siblings input, get siblingsOld from siblingsNew[len-1] |
||||
|
|
||||
|
component smtOld = SMTVerifier(nLevels); |
||||
|
smtOld.enabled <== 1; |
||||
|
smtOld.fnc <== 1; |
||||
|
smtOld.root <== rootOld; |
||||
|
for (var i=0; i<nLevels; i++) { |
||||
|
smtOld.siblings[i] <== siblingsOld[i]; |
||||
|
} |
||||
|
smtOld.oldKey <== 1; |
||||
|
smtOld.oldValue <== 0; |
||||
|
smtOld.isOld0 <== 0; |
||||
|
smtOld.key <== hash.out; |
||||
|
smtOld.value <== 0; |
||||
|
|
||||
|
component smtNew = SMTVerifier(nLevels); |
||||
|
smtNew.enabled <== 1; |
||||
|
smtNew.fnc <== 0; |
||||
|
smtNew.root <== rootNew; |
||||
|
for (var i=0; i<nLevels; i++) { |
||||
|
smtNew.siblings[i] <== siblingsNew[i]; |
||||
|
} |
||||
|
smtNew.oldKey <== 0; |
||||
|
smtNew.oldValue <== 0; |
||||
|
smtNew.isOld0 <== 0; |
||||
|
smtNew.key <== hash.out; |
||||
|
smtNew.value <== 0; |
||||
|
} |
||||
|
|
||||
|
component main = Deposit(5); |
@ -0,0 +1,72 @@ |
|||||
|
const path = require("path"); |
||||
|
const tester = require("circom").tester; |
||||
|
const chai = require("chai"); |
||||
|
const assert = chai.assert; |
||||
|
const circomlib = require("circomlib"); |
||||
|
const smt = require("circomlib").smt; |
||||
|
|
||||
|
export {}; |
||||
|
|
||||
|
describe("deposit test", function () { |
||||
|
this.timeout(200000); |
||||
|
|
||||
|
|
||||
|
it("Test Deposit", async () => { |
||||
|
const circuit = await tester( |
||||
|
path.join(__dirname, "../../circuits", "deposit.circom"), |
||||
|
{reduceConstraints: false} |
||||
|
); |
||||
|
|
||||
|
const nLevels = 5; |
||||
|
const secret = "1234567890"; |
||||
|
|
||||
|
const coinCode = "0"; |
||||
|
const amount = '1000000000000000000'; |
||||
|
const nullifier = "567891234"; |
||||
|
|
||||
|
const poseidon = circomlib.poseidon.createHash(6, 8, 57); |
||||
|
const commitment = poseidon([coinCode, amount, secret, nullifier]).toString(); |
||||
|
|
||||
|
// add commitment into SMT
|
||||
|
let tree = await smt.newMemEmptyTrie(); |
||||
|
await tree.insert(1, 0); |
||||
|
await tree.insert(2, 0); |
||||
|
|
||||
|
let rootOld = tree.root; |
||||
|
let res = await tree.find(commitment); |
||||
|
// console.log(res);
|
||||
|
assert(!res.found); |
||||
|
let siblingsOld = res.siblings; |
||||
|
while (siblingsOld.length < nLevels) { |
||||
|
siblingsOld.push("0"); |
||||
|
}; |
||||
|
console.log("siblingsOld", siblingsOld); |
||||
|
|
||||
|
await tree.insert(commitment, 0); |
||||
|
let rootNew = tree.root; |
||||
|
|
||||
|
res = await tree.find(commitment); |
||||
|
// console.log(res);
|
||||
|
assert(res.found); |
||||
|
let siblingsNew = res.siblings; |
||||
|
while (siblingsNew.length < nLevels) { |
||||
|
siblingsNew.push("0"); |
||||
|
}; |
||||
|
console.log("siblingsNew", siblingsNew); |
||||
|
console.log("rootOld", rootOld); |
||||
|
console.log("rootNew", rootNew); |
||||
|
|
||||
|
const witness = await circuit.calculateWitness({ |
||||
|
"coinCode": coinCode, |
||||
|
"amount": amount, |
||||
|
"secret": secret, |
||||
|
"nullifier": nullifier, |
||||
|
"siblingsOld": siblingsOld, |
||||
|
"siblingsNew": siblingsNew, |
||||
|
"rootOld": rootOld, |
||||
|
"rootNew": rootNew, |
||||
|
"commitment": commitment |
||||
|
}); |
||||
|
await circuit.checkConstraints(witness); |
||||
|
}); |
||||
|
}); |