mirror of
https://github.com/kilyig/ZheroTag.git
synced 2026-01-10 05:47:58 -05:00
simple move test
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -12,3 +12,8 @@ artifacts
|
||||
# circom extras
|
||||
*.r1cs
|
||||
*.sym
|
||||
*_cpp
|
||||
*_js
|
||||
*.wasm
|
||||
*.zkey
|
||||
ptau
|
||||
@@ -1,4 +1,5 @@
|
||||
include "../node_modules/circomlib/circuits/poseidon.circom";
|
||||
include "./set_operations.circom";
|
||||
|
||||
template Move() {
|
||||
signal input xOld;
|
||||
@@ -11,12 +12,19 @@ template Move() {
|
||||
signal input saltNew;
|
||||
signal output posHashNew;
|
||||
|
||||
// verify the old hash
|
||||
component oldHashChecker = Poseidon(3);
|
||||
oldHashChecker.inputs[0] <== xOld;
|
||||
oldHashChecker.inputs[1] <== yOld;
|
||||
oldHashChecker.inputs[2] <== saltOld;
|
||||
posHashOld === oldHashChecker.out;
|
||||
|
||||
// chess kings can only move to one of their Moore neighbors
|
||||
component possibleSquares = VisibleSquares();
|
||||
|
||||
|
||||
|
||||
// produce the hash for the new position
|
||||
component newHashGenerator = Poseidon(3);
|
||||
newHashGenerator.inputs[0] <== xNew;
|
||||
newHashGenerator.inputs[1] <== yNew;
|
||||
|
||||
9
circuits/move.json
Normal file
9
circuits/move.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"xOld": "0",
|
||||
"yOld": "0",
|
||||
"saltOld": "12345",
|
||||
"posHashOld": "2321794270632629049109131152230501273451975640760836008986566812209223148844",
|
||||
"xNew": "0",
|
||||
"yNew": "1",
|
||||
"saltNew": "12345"
|
||||
}
|
||||
1
circuits/move.vkey.json
Normal file
1
circuits/move.vkey.json
Normal file
@@ -0,0 +1 @@
|
||||
{"protocol":"groth16","curve":"bn128","nPublic":2,"vk_alpha_1":["20491192805390485299153009773594534940189261866228447918068658471970481763042","9383485363053290200918347156157836566562967994039712273449902621266178545958","1"],"vk_beta_2":[["6375614351688725206403948262868962793625744043794305715222011528459656738731","4252822878758300859123897981450591353533073413197771768651442665752259397132"],["10505242626370262277552901082094356697409835680220590971873171140371331206856","21847035105528745403288232691147584728191162732299865338377159692350059136679"],["1","0"]],"vk_gamma_2":[["10857046999023057135944570762232829481370756359578518086990519993285655852781","11559732032986387107991004021392285783925812861821192530917403151452391805634"],["8495653923123431417604973247489272438418190587263600148770280649306958101930","4082367875863433681332203403145435568316851327593401208105741076214120093531"],["1","0"]],"vk_delta_2":[["11377128597735879021622360903045069097412621576574291907159414133493915260453","8716571390944861277971267551725025206258009161176855904806311635057491901677"],["2861081928609901668097431581878231610252099555665736351017075153886697877772","13554251175355426001797871842533481691442937219832974449306312132444599263879"],["1","0"]],"vk_alphabeta_12":[[["2029413683389138792403550203267699914886160938906632433982220835551125967885","21072700047562757817161031222997517981543347628379360635925549008442030252106"],["5940354580057074848093997050200682056184807770593307860589430076672439820312","12156638873931618554171829126792193045421052652279363021382169897324752428276"],["7898200236362823042373859371574133993780991612861777490112507062703164551277","7074218545237549455313236346927434013100842096812539264420499035217050630853"]],[["7077479683546002997211712695946002074877511277312570035766170199895071832130","10093483419865920389913245021038182291233451549023025229112148274109565435465"],["4595479056700221319381530156280926371456704509942304414423590385166031118820","19831328484489333784475432780421641293929726139240675179672856274388269393268"],["11934129596455521040620786944827826205713621633706285934057045369193958244500","8037395052364110730298837004334506829870972346962140206007064471173334027475"]]],"IC":[["10949745416203741753861666003392260431354756070229883865289399583857266626873","4752309395416276455687127811956182629017861296766033750094835229557888182163","1"],["6681688297283077922224793909077601140641366659527375085275419804338075561691","13496422065519917963443266301163620335101452437762361899898963868378832044582","1"],["15023341891295437508357259311319910621355185477288801447736711177077669711379","7552267576198300157303859398700949767122932653089581929751811660821602384802","1"]]}
|
||||
0
circuits/psi1.json
Normal file
0
circuits/psi1.json
Normal file
0
circuits/psi2.json
Normal file
0
circuits/psi2.json
Normal file
0
circuits/psi3.json
Normal file
0
circuits/psi3.json
Normal file
@@ -3,7 +3,28 @@ import "@nomicfoundation/hardhat-toolbox";
|
||||
import "hardhat-circom";
|
||||
|
||||
const config: HardhatUserConfig = {
|
||||
solidity: "0.8.18",
|
||||
solidity: {
|
||||
compilers: [
|
||||
{
|
||||
version: "0.6.11"
|
||||
},
|
||||
{
|
||||
version: "0.8.17"
|
||||
}],
|
||||
},
|
||||
circom: {
|
||||
// (optional) Base path for input files, defaults to `./circuits/`
|
||||
inputBasePath: "./circuits",
|
||||
// (required) The final ptau file, relative to inputBasePath, from a Phase 1 ceremony
|
||||
ptau: "./ptau/powersOfTau28_hez_final_15.ptau",
|
||||
// (required) Each object in this array refers to a separate circuit
|
||||
circuits: [
|
||||
{ name: "move" },
|
||||
// { name: "psi1" },
|
||||
// { name: "psi2" },
|
||||
// { name: "psi3" }
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default config;
|
||||
|
||||
@@ -12,6 +12,14 @@ async function main() {
|
||||
console.log(
|
||||
`ZheroTag deployed to ${zheroTag.address} at time ${unlockTime}`
|
||||
);
|
||||
|
||||
// deploy the move verifier
|
||||
const MoveVerifier = await ethers.getContractFactory("contracts/MoveVerifier.sol:Verifier");
|
||||
const moveVerifier = await MoveVerifier.deploy();
|
||||
await moveVerifier.deployed();
|
||||
console.log(
|
||||
`MoveVerifier.sol deployed to ${moveVerifier.address}. Time: ${Date.now()}`
|
||||
);
|
||||
}
|
||||
|
||||
// We recommend this pattern to be able to use async/await everywhere
|
||||
|
||||
124
test/Lock.ts
124
test/Lock.ts
@@ -1,124 +0,0 @@
|
||||
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
||||
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
|
||||
import { expect } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
describe("Lock", function () {
|
||||
// We define a fixture to reuse the same setup in every test.
|
||||
// We use loadFixture to run this setup once, snapshot that state,
|
||||
// and reset Hardhat Network to that snapshot in every test.
|
||||
async function deployOneYearLockFixture() {
|
||||
const ONE_YEAR_IN_SECS = 365 * 24 * 60 * 60;
|
||||
const ONE_GWEI = 1_000_000_000;
|
||||
|
||||
const lockedAmount = ONE_GWEI;
|
||||
const unlockTime = (await time.latest()) + ONE_YEAR_IN_SECS;
|
||||
|
||||
// Contracts are deployed using the first signer/account by default
|
||||
const [owner, otherAccount] = await ethers.getSigners();
|
||||
|
||||
const Lock = await ethers.getContractFactory("Lock");
|
||||
const lock = await Lock.deploy(unlockTime, { value: lockedAmount });
|
||||
|
||||
return { lock, unlockTime, lockedAmount, owner, otherAccount };
|
||||
}
|
||||
|
||||
describe("Deployment", function () {
|
||||
it("Should set the right unlockTime", async function () {
|
||||
const { lock, unlockTime } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
expect(await lock.unlockTime()).to.equal(unlockTime);
|
||||
});
|
||||
|
||||
it("Should set the right owner", async function () {
|
||||
const { lock, owner } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
expect(await lock.owner()).to.equal(owner.address);
|
||||
});
|
||||
|
||||
it("Should receive and store the funds to lock", async function () {
|
||||
const { lock, lockedAmount } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
expect(await ethers.provider.getBalance(lock.address)).to.equal(
|
||||
lockedAmount
|
||||
);
|
||||
});
|
||||
|
||||
it("Should fail if the unlockTime is not in the future", async function () {
|
||||
// We don't use the fixture here because we want a different deployment
|
||||
const latestTime = await time.latest();
|
||||
const Lock = await ethers.getContractFactory("Lock");
|
||||
await expect(Lock.deploy(latestTime, { value: 1 })).to.be.revertedWith(
|
||||
"Unlock time should be in the future"
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Withdrawals", function () {
|
||||
describe("Validations", function () {
|
||||
it("Should revert with the right error if called too soon", async function () {
|
||||
const { lock } = await loadFixture(deployOneYearLockFixture);
|
||||
|
||||
await expect(lock.withdraw()).to.be.revertedWith(
|
||||
"You can't withdraw yet"
|
||||
);
|
||||
});
|
||||
|
||||
it("Should revert with the right error if called from another account", async function () {
|
||||
const { lock, unlockTime, otherAccount } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
// We can increase the time in Hardhat Network
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
// We use lock.connect() to send a transaction from another account
|
||||
await expect(lock.connect(otherAccount).withdraw()).to.be.revertedWith(
|
||||
"You aren't the owner"
|
||||
);
|
||||
});
|
||||
|
||||
it("Shouldn't fail if the unlockTime has arrived and the owner calls it", async function () {
|
||||
const { lock, unlockTime } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
// Transactions are sent using the first signer by default
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
await expect(lock.withdraw()).not.to.be.reverted;
|
||||
});
|
||||
});
|
||||
|
||||
describe("Events", function () {
|
||||
it("Should emit an event on withdrawals", async function () {
|
||||
const { lock, unlockTime, lockedAmount } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
await expect(lock.withdraw())
|
||||
.to.emit(lock, "Withdrawal")
|
||||
.withArgs(lockedAmount, anyValue); // We accept any value as `when` arg
|
||||
});
|
||||
});
|
||||
|
||||
describe("Transfers", function () {
|
||||
it("Should transfer the funds to the owner", async function () {
|
||||
const { lock, unlockTime, lockedAmount, owner } = await loadFixture(
|
||||
deployOneYearLockFixture
|
||||
);
|
||||
|
||||
await time.increaseTo(unlockTime);
|
||||
|
||||
await expect(lock.withdraw()).to.changeEtherBalances(
|
||||
[owner, lock],
|
||||
[lockedAmount, -lockedAmount]
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
76
test/ZheroTagLocal.ts
Normal file
76
test/ZheroTagLocal.ts
Normal file
@@ -0,0 +1,76 @@
|
||||
import { time, loadFixture } from "@nomicfoundation/hardhat-network-helpers";
|
||||
import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
|
||||
import { expect } from "chai";
|
||||
import { ethers } from "hardhat";
|
||||
import { int } from "hardhat/internal/core/params/argumentTypes";
|
||||
import { BigNumber } from "ethers";
|
||||
import { groth16 } from "snarkjs";
|
||||
import fs from "fs";
|
||||
|
||||
const MOVE_WASM_FILE_PATH = "circuits/move.wasm";
|
||||
const MOVE_ZKEY_FILE_PATH = "circuits/move.zkey";
|
||||
const MOVE_VKEY_FILE_PATH = "circuits/move.vkey.json";
|
||||
|
||||
import { generateProof } from "./utils/snark-utils";
|
||||
|
||||
// x: 0 y: 0 salt: 12345
|
||||
// 2321794270632629049109131152230501273451975640760836008986566812209223148844
|
||||
// x: 5 y: 5 salt: 12345
|
||||
// 9435539296313397007849595282098379346206722261888911142952399734225356376203
|
||||
|
||||
|
||||
describe("ZheroTagLocal", function () {
|
||||
// We define a fixture to reuse the same setup in every test.
|
||||
// We use loadFixture to run this setup once, snapshot that state,
|
||||
// and reset Hardhat Network to that snapshot in every test.
|
||||
async function fixture() {
|
||||
console.log("Running the fixture");
|
||||
}
|
||||
|
||||
describe("Move", function () {
|
||||
it("Basic move", async function () {
|
||||
const circuitInputs = {
|
||||
xOld: 0,
|
||||
yOld: 0,
|
||||
saltOld: 12345,
|
||||
posHashOld: BigInt("2321794270632629049109131152230501273451975640760836008986566812209223148844"),
|
||||
xNew: 0,
|
||||
yNew: 0,
|
||||
saltNew: 12345
|
||||
}
|
||||
const [proof, publicSignals] = await generateProof(
|
||||
circuitInputs,
|
||||
MOVE_WASM_FILE_PATH,
|
||||
MOVE_ZKEY_FILE_PATH
|
||||
);
|
||||
|
||||
console.log(proof);
|
||||
console.log(publicSignals);
|
||||
|
||||
const vKey = JSON.parse(fs.readFileSync(MOVE_VKEY_FILE_PATH, 'utf-8'));
|
||||
const res = await groth16.verify(vKey, publicSignals, proof);
|
||||
|
||||
if (res === true) {
|
||||
console.log("Verification OK");
|
||||
} else {
|
||||
console.log("Invalid proof");
|
||||
}
|
||||
});
|
||||
|
||||
it("Should set the right owner", async function () {
|
||||
|
||||
//expect(await lock.owner()).to.equal(owner.address);
|
||||
});
|
||||
|
||||
it("Should receive and store the funds to lock", async function () {
|
||||
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
// sources: https://betterprogramming.pub/zero-knowledge-proofs-using-snarkjs-and-circom-fac6c4d63202
|
||||
// ^^^^ for groth16.verify
|
||||
15
test/utils/snark-utils.ts
Normal file
15
test/utils/snark-utils.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { groth16 } from "snarkjs";
|
||||
import { ethers } from "hardhat";
|
||||
|
||||
export async function generateProof(circuitInputs: any, filePathWASM: any, filePathZKEY: any) {
|
||||
//const file_wasm = fs.readFileSync(filePathWASM);
|
||||
//const file_zkey = fs.readFileSync(filePathZKEY);
|
||||
|
||||
const { proof, publicSignals } = await groth16.fullProve(
|
||||
circuitInputs,
|
||||
filePathWASM,
|
||||
filePathZKEY
|
||||
);
|
||||
|
||||
return [proof, publicSignals];
|
||||
}
|
||||
Reference in New Issue
Block a user