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