Skip to content

Commit

Permalink
feat: test withdraws with relayers and nullifier assertion
Browse files Browse the repository at this point in the history
  • Loading branch information
veigajoao committed Sep 13, 2022
1 parent bf73bbd commit 038bb03
Show file tree
Hide file tree
Showing 2 changed files with 181 additions and 27 deletions.
65 changes: 42 additions & 23 deletions packages/contracts/tests-rs/prepare_commitments.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const { utils } = require("ffjavascript");
const { stringifyBigInts } = utils;

const Logger = require("logplease");
const logger = Logger.create("snarkJS", {showTimestamp:false});
const logger = Logger.create("snarkJS", { showTimestamp: false });
Logger.setLogLevel("DEBUG");

async function buildCommitments() {
Expand Down Expand Up @@ -60,6 +60,22 @@ async function buildCommitments() {
});
}

async function generate_witness(input, name) {
const buffer = readFileSync("../../circuits/out/withdraw_js/withdraw.wasm");
const witnessCalculator = await wc(buffer);
const buff = await witnessCalculator.calculateWTNSBin(input, 0);
fs.writeFileSync("temp/" + name, buff, function (err) {
if (err) throw err;
});
}

async function generate_proof(number) {
const { proof, publicSignals } = await groth16.prove("../../circuits/out/withdraw_0001.zkey", `temp/witness${number}.wtns`, logger);
await bfj.write(`./temp/proof${number}.json`, stringifyBigInts(proof), { space: 1 });
await bfj.write(`./temp/public${number}.json`, stringifyBigInts(publicSignals), { space: 1 });
}


// set accounts that will be used
const accounts = [
"user.test.near",
Expand Down Expand Up @@ -135,17 +151,10 @@ async function buildCommitments() {
const path4 = commitmentTree.proof(commitmentLeaves[3]);
const pathWL4 = whitelistTree.proof(accountsHashes[3]);

const nullifierHashes = [
mimc.single_hash(commitment1.nullifier),
mimc.single_hash(commitment2.nullifier),
mimc.single_hash(commitment3.nullifier),
mimc.single_hash(commitment4.nullifier),
];

// commitment 1 will be withdrawn by user 4
let commitment1Input = {
root: path1.pathRoot,
nullifierHash: nullifierHashes[0],
nullifierHash: mimc.single_hash(commitment1.nullifier),
recipient: accountsHashes[3], // not taking part in any computations
relayer: "0", // not taking part in any computations
fee: "0", // not taking part in any computations
Expand All @@ -163,24 +172,34 @@ async function buildCommitments() {
whitelistPathIndices: pathWL1.pathIndices
};

console.log(commitment1Input);
// commitment 1 will be withdrawn by user 4
let commitment2Input = {
root: path2.pathRoot,
nullifierHash: mimc.single_hash(commitment2.nullifier),
recipient: accountsHashes[3], // not taking part in any computations
relayer: accountsHashes[0], // not taking part in any computations
fee: "1000", // not taking part in any computations
refund: "0", // not taking part in any computations
nullifier: commitment2.nullifier,
secret: commitment2.secret,
pathElements: path2.pathElements,
pathIndices: path2.pathIndices,

// generate witness
async function generate_witness(input, name) {
const buffer = readFileSync("../../circuits/out/withdraw_js/withdraw.wasm");
const witnessCalculator = await wc(buffer);
const buff = await witnessCalculator.calculateWTNSBin(input, 0);
fs.writeFileSync("temp/" + name, buff, function (err) {
if (err) throw err;
});
}
// reference to current whitelist Merkle Tree
whitelistRoot: pathWL2.pathRoot,
// reference to original depositor to enforce whitelist
originDepositor: accountsHashes[1],
whitelistPathElements: pathWL2.pathElements,
whitelistPathIndices: pathWL2.pathIndices
};

// generate witness
await generate_witness(commitment1Input, "witness1.wtns");
await generate_witness(commitment2Input, "witness2.wtns");

const { proof, publicSignals } = await groth16.prove("../../circuits/out/withdraw_0001.zkey", "temp/witness1.wtns", logger);

await bfj.write("./temp/proof1.json", stringifyBigInts(proof), { space: 1 });
await bfj.write("./temp/public1.json", stringifyBigInts(publicSignals), { space: 1 });
// generate proofs
await generate_proof(1);
await generate_proof(2);

process.exit()
}
Expand Down
143 changes: 139 additions & 4 deletions packages/contracts/tests-rs/src/tests_core/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,13 +150,58 @@ mod tests {
Err(_) => (),
}

// assert correct proof
// make correct deposits
user
.call(&worker, contract.id(), "deposit")
.args_json(json!({
"secrets_hash": commitment1["secret_hash"]
}))?
.deposit(DEPOSIT_VALUE)
.gas(300000000000000)
.transact()
.await?;

user2
.call(&worker, contract.id(), "deposit")
.args_json(json!({
"secrets_hash": commitment2["secret_hash"]
}))?
.deposit(DEPOSIT_VALUE)
.gas(300000000000000)
.transact()
.await?;

user3
.call(&worker, contract.id(), "deposit")
.args_json(json!({
"secrets_hash": commitment3["secret_hash"]
}))?
.deposit(DEPOSIT_VALUE)
.gas(300000000000000)
.transact()
.await?;

user4
.call(&worker, contract.id(), "deposit")
.args_json(json!({
"secrets_hash": commitment4["secret_hash"]
}))?
.deposit(DEPOSIT_VALUE)
.gas(300000000000000)
.transact()
.await?;

// assert correct proofs

// user 1 deposits -> user 1 withdraws to user4
let receiver_account = user4.id();

let proof1 = get_json("proof1.json").unwrap();
let public1 = get_json("public1.json").unwrap();

let result = user
let initial_balance = user4.view_account(&worker).await?.balance;

user
.call(&worker, contract.id(), "withdraw")
.args_json(json!({
"root": public1[0],
Expand Down Expand Up @@ -185,9 +230,99 @@ mod tests {
.transact()
.await?;

println!("{:?}", result);
panic!("WWW");
let final_balance = user4.view_account(&worker).await?.balance;

assert_eq!(initial_balance + DEPOSIT_VALUE, final_balance);

// assert proof cannot be used again
let should_panic = user
.call(&worker, contract.id(), "withdraw")
.args_json(json!({
"root": public1[0],
"nullifier_hash": public1[1],
"recipient": receiver_account,
"relayer": null,
"fee": public1[4],
"refund": public1[5],
"whitelist_root": public1[6],
"proof": {
"a": {
"x": proof1["pi_a"][0],
"y": proof1["pi_a"][1]
},
"b": {
"x": proof1["pi_b"][0],
"y": proof1["pi_b"][1]
},
"c": {
"x": proof1["pi_c"][0],
"y": proof1["pi_c"][1]
}
},
}))?
.gas(300000000000000)
.transact()
.await;

match should_panic {
Ok(_) => panic!("should panic"),
Err(_) => (),
}

// user 2 deposits -> user1 withdraws as relayer to user4 withdraws
let receiver_account = user4.id();

let proof2 = get_json("proof2.json").unwrap();
let public2 = get_json("public2.json").unwrap();

let initial_balance1 = user.view_account(&worker).await?.balance;
let initial_balance4 = user4.view_account(&worker).await?.balance;

user2
.call(&worker, contract.id(), "withdraw")
.args_json(json!({
"root": public2[0],
"nullifier_hash": public2[1],
"recipient": receiver_account,
"relayer": user.id(),
"fee": public2[4],
"refund": public2[5],
"whitelist_root": public2[6],
"proof": {
"a": {
"x": proof2["pi_a"][0],
"y": proof2["pi_a"][1]
},
"b": {
"x": proof2["pi_b"][0],
"y": proof2["pi_b"][1]
},
"c": {
"x": proof2["pi_c"][0],
"y": proof2["pi_c"][1]
}
},
}))?
.gas(300000000000000)
.transact()
.await?;

let final_balance1 = user.view_account(&worker).await?.balance;
let final_balance4 = user4.view_account(&worker).await?.balance;

println!("initial1: {}", initial_balance1);
println!("final1: {}", final_balance1);
println!("initial2: {}", initial_balance4);
println!("final2: {}", final_balance4);

assert_eq!(
initial_balance1 + public2[4].as_str().unwrap().parse::<u128>().unwrap(),
final_balance1
);
assert_eq!(
initial_balance4 + DEPOSIT_VALUE - public2[4].as_str().unwrap().parse::<u128>().unwrap(),
final_balance4
);

// 2. attempt to withdraw with wrong proofs - assert fail

Expand Down

0 comments on commit 038bb03

Please sign in to comment.