@ -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); |
|||
}); |
|||
}); |