semaphore V2 tutorial
semaphore V2では木構造が変化したり、開発環境がHardHat ベースになったりと大幅なアプデがされている
今回は以下のtutorialを参考に木構造(回路)の理解を深める
木構造
左がv1のイメージ図、右がv2
https://scrapbox.io/files/626348406db8a5001dc5f5f1.pnghttps://scrapbox.io/files/6263481020335a001d726855.png
より詳細な木構造が見えるようになった。
signal treeはsignal Hashのsquareに置き換わってる
onChain処理
code:circuit.sol
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@appliedzkp/semaphore-contracts/interfaces/IVerifier.sol";
import "@appliedzkp/semaphore-contracts/base/SemaphoreCore.sol";
contract Greeters is SemaphoreCore {
// A new greeting is published every time a user's proof is validated.
event NewGreeting(bytes32 greeting);
// Greeters are identified by a Merkle root.
// The offchain Merkle tree contains the greeters' identity commitments.
uint256 public greeters;
// The external verifier used to verify Semaphore proofs.
IVerifier public verifier;
constructor(uint256 _greeters, address _verifier) {
greeters = _greeters;
verifier = IVerifier(_verifier); //Iverifierはinterfaceとして定義されている
}
// Only users who create valid proofs can greet.
// The external nullifier is in this example the root of the Merkle tree.
function greet(
bytes32 _greeting,
uint256 _nullifierHash,
) external {
//6個の引数は最初のinputの数に一致しているので、この関数に入力するだけで良さげ
_verifyProof(_greeting, greeters, _nullifierHash, greeters, _proof, verifier);
// Prevent double-greeting (nullifierHash = hash(root + identityNullifier)).
// Every user can greet once.
_saveNullifierHash(_nullifierHash);
emit NewGreeting(_greeting);
}
}
offChain処理
初期入力の一つであるidentityCommitmentsはJSONとして渡されることを想定している。これはユーザーが入力するやつ
code:identityCommitments.json
[
"9426253249246138013650573474062059446203468399013007463704855436559640562175",
"6200634377081441056179822649025268043304989981899916286941956069781421654881",
"19706772421195815860043593475869058320994241404138740034486179990871964981523"
]
この中身を変更し、yarn hardhat test すると Error: The leaf does not exists となる
最初の実行時に覚えてるのかな?と思ったけど、ここのパラメータは決めうち
code:deploy.js
const { IncrementalMerkleTree } = require("@zk-kit/incremental-merkle-tree")
const { poseidon } = require("circomlibjs")
const identityCommitments = require("../static/identityCommitments.json")
const { task, types } = require("hardhat/config")
task("deploy", "Deploy a Greeters contract")
.addOptionalParam("logs", "Print the logs", true, types.boolean)
.setAction(async ({ logs }, { ethers }) => {
const VerifierContract = await ethers.getContractFactory("Verifier")
const verifier = await VerifierContract.deploy()
await verifier.deployed()
logs && console.log(Verifier contract has been deployed to: ${verifier.address})
const GreetersContract = await ethers.getContractFactory("Greeters")
const tree = new IncrementalMerkleTree(poseidon, 20, BigInt(0), 2)
//拡張for文でidentityCommitmentを木に格納していく
for (const identityCommitment of identityCommitments) {
tree.insert(identityCommitment)
}
const greeters = await GreetersContract.deploy(tree.root, verifier.address)
await greeters.deployed()
logs && console.log(Greeters contract has been deployed to: ${greeters.address})
return greeters
})
inputになる型は今回はBigIntになっているが、ユーザーが何をinputするかによる。