You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

159 lines
4.3 KiB

const fs = require("fs");
const bigInt = require("big-integer");
const { groth } = require('snarkjs');
const { Fr } = require('ffjavascript').bn128;
const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils;
const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
const circomlib = require("circomlib");
const smt = require("circomlib").smt;
const Web3 = require("web3");
// const buildBn128 = require("wasmsnark").buildBn128;
const coinCode = "0"; // refearing to ETH
const ethAmount = '1';
const amount = Web3.utils.toWei(ethAmount, 'ether');
exports.randBigInt = () => {
return Fr.random();
};
exports.calcCommitment = (key, secret) => {
const poseidon = circomlib.poseidon.createHash(6, 8, 57);
const nullifier = poseidon([key, secret]).toString();
const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
return commitment;
};
exports.calcDepositWitness = async (wasm, nLevels, key, secret, commitments) => {
const poseidon = circomlib.poseidon.createHash(6, 8, 57);
const nullifier = poseidon([key, secret]).toString();
const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
console.log("Commitment", commitment.toString());
// rebuild the tree
let tree = await smt.newMemEmptyTrie();
await tree.insert(0, 0);
for (let i=0; i <commitments.length; i++) {
await tree.insert(i+1, commitments[i]);
}
let res = await tree.insert(key, commitment);
// new root
let siblings = res.siblings;
console.log(res);
// while (siblings.length < nLevels) {
// siblings.push("0");
// };
// calculate witness
const input = unstringifyBigInts({
"coinCode": coinCode,
"amount": amount,
"secret": secret,
"oldKey": res.isOld0 ? 0 : res.oldKey,
"oldValue": res.isOld0 ? 0 : res.oldValue,
"isOld0": res.isOld0 ? 1 : 0,
"siblings": siblings,
"rootOld": res.oldRoot,
"rootNew": res.newRoot,
"commitment": commitment,
"key": key
});
console.log("input", input);
// const options = {};
// const wc = await WitnessCalculatorBuilder(wasm, options);
const wc = await WitnessCalculatorBuilder(wasm);
const witness = await wc.calculateWitness(input, {sanityCheck: true});
const wBuff = Buffer.allocUnsafe(witness.length*32);
for (let i=0; i <witness.length; i++) {
for (let j=0; j <8; j++) {
const bi = witness[i];
const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
// wBuff.writeUInt32LE(v, i*32 + j*4, 4)
wBuff.writeUInt32LE(v, i*32 + j*4)
}
}
// const witness = unstringifyBigInts(stringifyBigInts(w));
// return wBuff;
return {
witness: wBuff,
publicInputs: {
commitment:commitment,
root:res.newRoot
}
};
}
exports.calcWithdrawWitness = async (wasm, nLevels, key, secret, commitments, addr) => {
const poseidon = circomlib.poseidon.createHash(6, 8, 57);
const nullifier = poseidon([key, secret]).toString();
const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
// rebuild the tree
let tree = await smt.newMemEmptyTrie();
await tree.insert(0, 0);
for (let i=0; i <commitments.length; i++) {
await tree.insert(i+1, commitments[i]);
}
// await tree.insert(commitment, 0);
// root
const root = tree.root;
const res = await tree.find(key);
if (!res.found) {
console.error("leaf expect to exist but not exists, key:", key);
}
let siblings = res.siblings;
while (siblings.length < nLevels) {
siblings.push("0");
};
// calculate witness
const input = unstringifyBigInts({
"coinCode": coinCode,
"amount": amount,
"secret": secret,
"nullifier": nullifier,
"siblings": siblings,
"root": root,
"address": addr,
"key": key
});
console.log("input", input);
// const options = {};
// const wc = await WitnessCalculatorBuilder(wasm, options);
const wc = await WitnessCalculatorBuilder(wasm);
const witness = await wc.calculateWitness(input, {sanityCheck: true});
const wBuff = Buffer.allocUnsafe(witness.length*32);
for (let i=0; i <witness.length; i++) {
for (let j=0; j <8; j++) {
const bi = witness[i];
const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
// wBuff.writeUInt32LE(v, i*32 + j*4, 4)
wBuff.writeUInt32LE(v, i*32 + j*4)
}
}
// const witness = unstringifyBigInts(stringifyBigInts(w));
return {
witness: wBuff,
publicInputs: {
address:addr,
nullifier:nullifier
}
};
}