arnaucube
arnaucube/miksi-corePublic Self-hosted repository
miksi-core/test/contracts/miksi.test.ts
test/contracts/miksi.test.tsRaw
  1const Verifier = artifacts.require("../../contracts/Verifier");
  2const Miksi = artifacts.require("../../contracts/Miksi.sol");
  3
  4const chai = require("chai");
  5const expect = chai.expect;
  6const truffleAssert = require('truffle-assertions');
  7
  8const fs = require("fs");
  9const { groth } = require('snarkjs');
 10const { stringifyBigInts, unstringifyBigInts } = require('ffjavascript').utils;
 11const WitnessCalculatorBuilder = require("circom_runtime").WitnessCalculatorBuilder;
 12const circomlib = require("circomlib");
 13const smt = require("circomlib").smt;
 14
 15contract("miksi", (accounts) => {
 16
 17
 18  const {
 19    0: owner,
 20    1: addr1, // used for the deposit
 21    2: addr2, // used for the withdraw
 22    3: addr3,
 23  } = accounts;
 24
 25  let insVerifier;
 26  let insMiksi;
 27
 28    const nLevels = 5;
 29    const secret = "1234567890";
 30
 31    const coinCode = "0"; // refearing to ETH
 32    const ethAmount = '1';
 33    const amount = web3.utils.toWei(ethAmount, 'ether');
 34    const nullifier = "567891234";
 35    let tree;
 36    let commitment;
 37    let proof;
 38    let publicSignals;
 39
 40  before(async () => {
 41
 42    insVerifier = await Verifier.new();
 43    insMiksi = await Miksi.new(insVerifier.address);
 44  });
 45
 46  before(async() => {
 47    let balance_wei = await web3.eth.getBalance(addr1);
 48    // console.log("Balance at " + addr1, web3.utils.fromWei(balance_wei, 'ether'));
 49    expect(balance_wei).to.be.equal('100000000000000000000');
 50
 51    const poseidon = circomlib.poseidon.createHash(6, 8, 57);
 52    commitment = poseidon([coinCode, amount, secret, nullifier]).toString();
 53
 54    // deposit
 55    // add commitment into SMT
 56    tree = await smt.newMemEmptyTrie();
 57    await tree.insert(commitment, 0);
 58    await tree.insert(1, 0);
 59    await tree.insert(2, 0);
 60    expect(tree.root.toString()).to.be.equal('9712258649847843172766744803572924784812438285433990419902675958769413333474');
 61  });
 62
 63  it("Make the deposit", async () => {
 64    // console.log("root", tree.root);
 65    // console.log("Deposit of " + ethAmount + " ETH from " + addr1 + ".\nCommitment "+commitment+", root: "+ tree.root);
 66    await insMiksi.deposit(commitment, tree.root.toString(), {from: addr1, value: amount});
 67
 68    balance_wei = await web3.eth.getBalance(addr1);
 69    // console.log("Balance at " + addr1, web3.utils.fromWei(balance_wei, 'ether'));
 70    expect(balance_wei).to.be.equal('98998318640000000000');
 71  });
 72
 73  it("Get the commitments data", async () => {
 74    // getCommitments data
 75    let res = await insMiksi.getCommitments();
 76    expect(res[0][0].toString()).to.be.equal('189025084074544266465422070282645213792582195466360448472858620722286781863');
 77    expect(res[1].toString()).to.be.equal('9712258649847843172766744803572924784812438285433990419902675958769413333474');
 78  });
 79
 80  it("Calculate witness and generate the zkProof", async () => {
 81    const resC = await tree.find(commitment);
 82    assert(resC.found);
 83    let siblings = resC.siblings;
 84    while (siblings.length < nLevels) {
 85        siblings.push("0");
 86    };
 87    // console.log("siblings", siblings);
 88
 89    // calculate witness
 90    const wasm = await fs.promises.readFile("./build/withdraw.wasm");
 91    const input = unstringifyBigInts({
 92      "coinCode": coinCode,
 93      "amount": amount,
 94      "secret": secret,
 95      "nullifier": nullifier,
 96      "siblings": siblings,
 97      "root": tree.root,
 98      "address": addr2
 99    });
100    const options = {};
101    // console.log("Calculate witness");
102    const wc = await WitnessCalculatorBuilder(wasm, options);
103    const w = await wc.calculateWitness(input);
104    const witness = unstringifyBigInts(stringifyBigInts(w));
105
106    // generate zkproof of commitment using snarkjs (as is a test)
107    const provingKey = unstringifyBigInts(JSON.parse(fs.readFileSync("./build/proving_key.json", "utf8")));
108
109    // console.log("Generate zkSNARK proof");
110    const res = groth.genProof(provingKey, witness);
111    proof = res.proof;
112    publicSignals = res.publicSignals;
113  });
114
115  it("Try to use the zkProof with another address and get revert", async () => {
116    // console.log("Try to reuse the zkproof and expect revert");
117    await truffleAssert.fails(
118      insMiksi.withdraw(
119        addr1,
120        nullifier,
121        [proof.pi_a[0].toString(), proof.pi_a[1].toString()],
122        [
123          [proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString()],
124          [proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString()]
125        ],
126        [proof.pi_c[0].toString(), proof.pi_c[1].toString()]
127      ),
128      truffleAssert.ErrorType.REVERT,
129      "zkProof withdraw could not be verified"
130    );
131  });
132
133  it("Withdraw 1 ETH with the zkProof", async () => {
134    // withdraw
135    // console.log("Withdraw of " + ethAmount + " ETH to " + addr2);
136    let resW = await insMiksi.withdraw(
137      addr2,
138      nullifier,
139      [proof.pi_a[0].toString(), proof.pi_a[1].toString()],
140      [
141        [proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString()],
142        [proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString()]
143      ],
144      [proof.pi_c[0].toString(), proof.pi_c[1].toString()]
145    );
146    // console.log("resW", resW);
147
148    balance_wei = await web3.eth.getBalance(addr2);
149    // console.log("Balance at " + addr2, web3.utils.fromWei(balance_wei, 'ether'));
150    expect(balance_wei).to.be.equal('101000000000000000000');
151  });
152
153  it("Try to reuse the zkProof and get revert", async () => {
154    // console.log("Try to reuse the zkproof and expect revert");
155    await truffleAssert.fails(
156      insMiksi.withdraw(
157        addr2,
158        nullifier,
159        [proof.pi_a[0].toString(), proof.pi_a[1].toString()],
160        [
161          [proof.pi_b[0][1].toString(), proof.pi_b[0][0].toString()],
162          [proof.pi_b[1][1].toString(), proof.pi_b[1][0].toString()]
163        ],
164        [proof.pi_c[0].toString(), proof.pi_c[1].toString()]
165      ),
166      truffleAssert.ErrorType.REVERT,
167      "nullifier already used"
168    );
169    balance_wei = await web3.eth.getBalance(addr2);
170    expect(balance_wei).to.be.equal('101000000000000000000');
171  });
172});