miksi-core/src/miksi.ts
src/miksi.tsRaw
1const fs = require("fs");
2const bigInt = require("big-integer");
3const { groth } = require('snarkjs');
4const { Fr } = require('ffjavascript').bn128;
5const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils;
6const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
7const circomlib = require("circomlib");
8const smt = require("circomlib").smt;
9const Web3 = require("web3");
10// const buildBn128 = require("wasmsnark").buildBn128;
11
12
13const nLevels = 5;
14const coinCode = "0"; // refearing to ETH
15const ethAmount = '1';
16const amount = Web3.utils.toWei(ethAmount, 'ether');
17
18exports.randBigInt = () => {
19 return Fr.random();
20};
21
22exports.calcCommitment = (secret, nullifier) => {
23 const poseidon = circomlib.poseidon.createHash(6, 8, 57);
24 const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
25 return commitment;
26};
27
28exports.calcDepositWitness = async (wasm, secret, nullifier, commitments, key) => {
29 const poseidon = circomlib.poseidon.createHash(6, 8, 57);
30 const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
31
32 // rebuild the tree
33 let tree = await smt.newMemEmptyTrie();
34 await tree.insert(0, 0);
35 for (let i=0; i<commitments.length; i++) {
36 await tree.insert(i+1, commitments[i]);
37 }
38
39 // old root
40 const rootOld = tree.root;
41 const resOld = await tree.find(commitment);
42 let oldKey = "0";
43 let oldValue = "0";
44 if (!resOld.found) {
45 oldKey = resOld.notFoundKey.toString();
46 oldValue = resOld.notFoundValue.toString();
47 }
48 console.log("oldKey", oldKey);
49 console.log("oldValue", oldValue);
50 // if (resOld.found) {
51 // console.error("leaf expect to not exist but exists");
52 // }
53 let siblingsOld = resOld.siblings;
54 while (siblingsOld.length < nLevels) {
55 siblingsOld.push("0");
56 };
57
58 await tree.insert(key, commitment);
59
60 // new root
61 const rootNew = tree.root;
62 const resNew = await tree.find(key);
63 if (!resNew.found) {
64 console.error("leaf with the new commitment expect to exist but not exists");
65 }
66 let siblingsNew = resNew.siblings;
67 while (siblingsNew.length < nLevels) {
68 siblingsNew.push("0");
69 };
70
71 // calculate witness
72 const input = unstringifyBigInts({
73 "coinCode": coinCode,
74 "amount": amount,
75 "secret": secret,
76 "nullifier": nullifier,
77 "oldKey": oldKey,
78 "oldValue": oldValue,
79 "siblingsOld": siblingsOld,
80 "siblingsNew": siblingsNew,
81 "rootOld": rootOld,
82 "rootNew": rootNew,
83 "commitment": commitment,
84 "key": key
85 });
86 console.log("input", input);
87 // const options = {};
88 // const wc = await WitnessCalculatorBuilder(wasm, options);
89
90 const wc = await WitnessCalculatorBuilder(wasm);
91
92 const witness = await wc.calculateWitness(input, {sanityCheck: true});
93
94 const wBuff = Buffer.allocUnsafe(witness.length*32);
95
96 for (let i=0; i<witness.length; i++) {
97 for (let j=0; j<8; j++) {
98 const bi = witness[i];
99 const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
100 // wBuff.writeUInt32LE(v, i*32 + j*4, 4)
101 wBuff.writeUInt32LE(v, i*32 + j*4)
102 }
103 }
104
105
106 // const witness = unstringifyBigInts(stringifyBigInts(w));
107 // return wBuff;
108 return {
109 witness: wBuff,
110 publicInputs: {
111 commitment:commitment,
112 root:rootNew
113 }
114 };
115}
116
117exports.calcWithdrawWitness = async (wasm, secret, nullifier, commitments, addr, key) => {
118 const poseidon = circomlib.poseidon.createHash(6, 8, 57);
119 const commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
120
121 // rebuild the tree
122 let tree = await smt.newMemEmptyTrie();
123 await tree.insert(0, 0);
124 for (let i=0; i<commitments.length; i++) {
125 await tree.insert(i+1, commitments[i]);
126 }
127 // await tree.insert(commitment, 0);
128
129 // root
130 const root = tree.root;
131 const res = await tree.find(key);
132 if (!res.found) {
133 console.error("leaf expect to exist but not exists, key:", key);
134 }
135 let siblings = res.siblings;
136 while (siblings.length < nLevels) {
137 siblings.push("0");
138 };
139
140 // calculate witness
141 const input = unstringifyBigInts({
142 "coinCode": coinCode,
143 "amount": amount,
144 "secret": secret,
145 "nullifier": nullifier,
146 "siblings": siblings,
147 "root": root,
148 "address": addr,
149 "key": key
150 });
151 console.log("input", input);
152 // const options = {};
153 // const wc = await WitnessCalculatorBuilder(wasm, options);
154
155 const wc = await WitnessCalculatorBuilder(wasm);
156
157 const witness = await wc.calculateWitness(input, {sanityCheck: true});
158
159 const wBuff = Buffer.allocUnsafe(witness.length*32);
160
161 for (let i=0; i<witness.length; i++) {
162 for (let j=0; j<8; j++) {
163 const bi = witness[i];
164 const v = bigInt(bi).shiftRight(j*32).and(0xFFFFFFFF).toJSNumber();
165 // wBuff.writeUInt32LE(v, i*32 + j*4, 4)
166 wBuff.writeUInt32LE(v, i*32 + j*4)
167 }
168 }
169
170
171 // const witness = unstringifyBigInts(stringifyBigInts(w));
172 return {
173 witness: wBuff,
174 publicInputs: {
175 address:addr,
176 nullifier:nullifier
177 }
178 };
179}