Merge pull request #633 from social-tw/revert-629-refactor/remove-epkhelper-contract

Revert 629 refactor/remove epkhelper contract
This commit is contained in:
Ya-wen, Jeng
2025-01-22 16:44:02 +08:00
committed by GitHub
14 changed files with 316 additions and 291 deletions

View File

@@ -1,16 +1,21 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.0;
import { Unirep } from "@unirep/contracts/Unirep.sol";
import { EpochKeyVerifierHelper } from "@unirep/contracts/verifierHelpers/EpochKeyVerifierHelper.sol";
import { EpochKeyLiteVerifierHelper } from "@unirep/contracts/verifierHelpers/EpochKeyLiteVerifierHelper.sol";
import { BaseVerifierHelper } from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import { VerifierHelperManager } from "./verifierHelpers/VerifierHelperManager.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { DailyClaimVHelper } from "./verifierHelpers/DailyClaimVHelper.sol";
import {Unirep} from "@unirep/contracts/Unirep.sol";
import {ReputationVerifierHelper} from "@unirep/contracts/verifierHelpers/ReputationVerifierHelper.sol";
import {EpochKeyLiteVerifierHelper} from "@unirep/contracts/verifierHelpers/EpochKeyLiteVerifierHelper.sol";
import {BaseVerifierHelper} from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import {VerifierHelperManager} from "./verifierHelpers/VerifierHelperManager.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {DailyClaimVHelper} from "./verifierHelpers/DailyClaimVHelper.sol";
// Uncomment this line to use console.log
// import "hardhat/console.sol";
interface IVerifier {
function verifyProof(uint256[] calldata publicSignals, uint256[8] calldata proof) external view returns (bool);
function verifyProof(
uint256[] calldata publicSignals,
uint256[8] calldata proof
) external view returns (bool);
}
contract UnirepApp is Ownable {
@@ -27,7 +32,7 @@ contract UnirepApp is Ownable {
Unirep public unirep;
IVerifier internal dataVerifier;
ReputationVerifierHelper internal repHelper;
EpochKeyVerifierHelper internal epkHelper;
EpochKeyLiteVerifierHelper internal epkLiteHelper;
VerifierHelperManager internal verifierHelperManager;
@@ -47,21 +52,42 @@ contract UnirepApp is Ownable {
// Nagative Reputation field index in Unirep protocol
uint256 public immutable negRepFieldIndex = 1;
event Post(uint256 indexed epochKey, uint256 indexed postId, uint256 indexed epoch, string content);
event Post(
uint256 indexed epochKey,
uint256 indexed postId,
uint256 indexed epoch,
string content
);
event Comment(
uint256 indexed epochKey, uint256 indexed postId, uint256 indexed commentId, uint256 epoch, string content
uint256 indexed epochKey,
uint256 indexed postId,
uint256 indexed commentId,
uint256 epoch,
string content
);
event UpdatedComment(
uint256 indexed epochKey, uint256 indexed postId, uint256 indexed commentId, uint256 epoch, string newContent
uint256 indexed epochKey,
uint256 indexed postId,
uint256 indexed commentId,
uint256 epoch,
string newContent
);
event ClaimPosRep(uint256 indexed epochKey, uint256 epoch);
event ClaimPosRep(
uint256 indexed epochKey,
uint256 epoch
);
event ClaimNegRep(uint256 indexed epochKey, uint256 epoch);
event ClaimNegRep(
uint256 indexed epochKey,
uint256 epoch
);
event DailyEpochEnded(uint48 indexed epoch);
event DailyEpochEnded(
uint48 indexed epoch
);
uint160 immutable attesterId;
@@ -79,7 +105,7 @@ contract UnirepApp is Ownable {
constructor(
Unirep _unirep,
ReputationVerifierHelper _repHelper,
EpochKeyVerifierHelper _epkHelper,
EpochKeyLiteVerifierHelper _epkLiteHelper,
IVerifier _dataVerifier,
VerifierHelperManager _verifierHelperManager,
@@ -88,8 +114,8 @@ contract UnirepApp is Ownable {
// set unirep address
unirep = _unirep;
// set reputation verifier helper address
repHelper = _repHelper;
// set epoch key verifier helper address
epkHelper = _epkHelper;
// set epoch key lite verifier helper address
epkLiteHelper = _epkLiteHelper;
@@ -100,25 +126,18 @@ contract UnirepApp is Ownable {
// set verifierHelper manager
verifierHelperManager = _verifierHelperManager;
dailyEpochData =
DailyEpochData({startTimestamp: uint48(block.timestamp), currentEpoch: 0, epochLength: 24 * 60 * 60});
dailyEpochData = DailyEpochData({
startTimestamp: uint48(block.timestamp),
currentEpoch: 0,
epochLength: 24*60*60
});
// sign up as an attester
attesterId = uint160(msg.sender);
unirep.attesterSignUp(_epochLength);
}
/// @dev Decode and verify the reputation proofs
/// @return proofSignals proof signals or fails
function decodeAndVerify(uint256[] calldata publicSignals, uint256[8] calldata proof)
internal
view
returns (ReputationVerifierHelper.ReputationSignals memory proofSignals)
{
return repHelper.verifyAndCheckCaller(publicSignals, proof);
}
/**
/**
* Sign up users in this app
* @param publicSignals: public signals
* @param proof: UserSignUpProof
@@ -144,10 +163,14 @@ contract UnirepApp is Ownable {
/**
* Post a content in this app
* @param publicSignals: public signals
* @param proof: reputationProof from the user
* @param proof: epockKeyProof from the user
* @param content: content of this post
*/
function post(uint256[] calldata publicSignals, uint256[8] calldata proof, string memory content) public {
*/
function post(
uint256[] memory publicSignals,
uint256[8] memory proof,
string memory content
) public {
// check if proof is used before
bytes32 nullifier = keccak256(abi.encodePacked(publicSignals, proof));
if (proofNullifier[nullifier]) {
@@ -156,7 +179,8 @@ contract UnirepApp is Ownable {
proofNullifier[nullifier] = true;
ReputationVerifierHelper.ReputationSignals memory signals = decodeAndVerify(publicSignals, proof);
EpochKeyVerifierHelper.EpochKeySignals memory signals = epkHelper
.decodeEpochKeySignals(publicSignals);
// check the epoch != current epoch (ppl can only post in current aepoch)
uint48 epoch = unirep.attesterCurrentEpoch(signals.attesterId);
@@ -164,8 +188,12 @@ contract UnirepApp is Ownable {
revert InvalidEpoch();
}
// should check lastly
epkHelper.verifyAndCheckCaller(publicSignals, proof);
emit Post(signals.epochKey, latestPostId, signals.epoch, content);
latestPostId++;
}
/**
@@ -176,8 +204,8 @@ contract UnirepApp is Ownable {
* @param content: comment content
*/
function leaveComment(
uint256[] calldata publicSignals,
uint256[8] calldata proof,
uint256[] memory publicSignals,
uint256[8] memory proof,
uint256 postId,
string memory content
) public {
@@ -188,19 +216,29 @@ contract UnirepApp is Ownable {
}
proofNullifier[nullifier] = true;
ReputationVerifierHelper.ReputationSignals memory signals = decodeAndVerify(publicSignals, proof);
EpochKeyVerifierHelper.EpochKeySignals memory signals = epkHelper
.decodeEpochKeySignals(publicSignals);
// check the epoch != current epoch (ppl can only leave comment in current epoch)
// check the epoch != current epoch (ppl can only post in current aepoch)
uint48 epoch = unirep.attesterCurrentEpoch(signals.attesterId);
if (signals.epoch != epoch) {
revert InvalidEpoch();
}
// check if the proof is valid
epkHelper.verifyAndCheckCaller(publicSignals, proof);
uint256 commentId = postCommentIndex[postId];
epochKeyCommentMap[postId][commentId] = signals.epochKey;
postCommentIndex[postId] = commentId + 1;
emit Comment(signals.epochKey, postId, commentId, signals.epoch, content);
emit Comment(
signals.epochKey,
postId,
commentId,
signals.epoch,
content
);
}
/**
@@ -226,8 +264,10 @@ contract UnirepApp is Ownable {
proofNullifier[nullifier] = true;
EpochKeyLiteVerifierHelper.EpochKeySignals memory signals =
epkLiteHelper.decodeEpochKeyLiteSignals(publicSignals);
EpochKeyLiteVerifierHelper.EpochKeySignals
memory signals = epkLiteHelper.decodeEpochKeyLiteSignals(
publicSignals
);
// check the epoch != current epoch (ppl can only post in current aepoch)
uint48 epoch = unirep.attesterCurrentEpoch(signals.attesterId);
@@ -246,20 +286,29 @@ contract UnirepApp is Ownable {
epkLiteHelper.verifyAndCheckCaller(publicSignals, proof);
emit UpdatedComment(signals.epochKey, postId, commentId, signals.epoch, newContent);
emit UpdatedComment(
signals.epochKey,
postId,
commentId,
signals.epoch,
newContent
);
}
/// @param publicSignals The public signals of the snark proof
/// @param proof The proof data of the snark proof
/// @param identifier sha256(verifier_contract_name)
/// @return signals The EpochKeySignals from BaseVerifierHelper
function verifyWithIdentifier(uint256[] calldata publicSignals, uint256[8] calldata proof, bytes32 identifier)
public
view
returns (BaseVerifierHelper.EpochKeySignals memory)
{
BaseVerifierHelper.EpochKeySignals memory signal =
verifierHelperManager.verifyProof(publicSignals, proof, identifier);
function verifyWithIdentifier(
uint256[] calldata publicSignals,
uint256[8] calldata proof,
bytes32 identifier
) public view returns (BaseVerifierHelper.EpochKeySignals memory) {
BaseVerifierHelper.EpochKeySignals memory signal = verifierHelperManager.verifyProof(
publicSignals,
proof,
identifier
);
return signal;
}
@@ -278,11 +327,19 @@ contract UnirepApp is Ownable {
}
}
function submitAttestation(uint256 epochKey, uint48 targetEpoch, uint256 fieldIndex, uint256 val) public {
function submitAttestation(
uint256 epochKey,
uint48 targetEpoch,
uint256 fieldIndex,
uint256 val
) public {
unirep.attest(epochKey, targetEpoch, fieldIndex, val);
}
function verifyDataProof(uint256[] calldata publicSignals, uint256[8] calldata proof) public view returns (bool) {
function verifyDataProof(
uint256[] calldata publicSignals,
uint256[8] calldata proof
) public view returns (bool) {
return dataVerifier.verifyProof(publicSignals, proof);
}
@@ -297,7 +354,7 @@ contract UnirepApp is Ownable {
uint256[8] calldata proof,
bytes32 identifier,
uint256 change
) public onlyOwner {
) public onlyOwner() {
// check if proof is used before
bytes32 nullifier = keccak256(abi.encodePacked(publicSignals, proof));
if (proofNullifier[nullifier]) {
@@ -306,8 +363,11 @@ contract UnirepApp is Ownable {
proofNullifier[nullifier] = true;
BaseVerifierHelper.EpochKeySignals memory signals =
verifierHelperManager.verifyProof(publicSignals, proof, identifier);
BaseVerifierHelper.EpochKeySignals memory signals = verifierHelperManager.verifyProof(
publicSignals,
proof,
identifier
);
// check the epoch != current epoch (ppl can only claim in current epoch)
uint48 epoch = unirep.attesterCurrentEpoch(signals.attesterId);
@@ -331,10 +391,11 @@ contract UnirepApp is Ownable {
* @param publicSignals: public signals
* @param proof: daily claim proof
*/
function claimDailyLoginRep(uint256[] calldata publicSignals, uint256[8] calldata proof, bytes32 identifier)
public
onlyOwner
{
function claimDailyLoginRep(
uint256[] calldata publicSignals,
uint256[8] calldata proof,
bytes32 identifier
) public onlyOwner() {
_updateDailyEpochIfNeeded();
DailyClaimVHelper dailyClaimVHelpers = DailyClaimVHelper(verifierHelperManager.registeredVHelpers(identifier));
@@ -363,7 +424,11 @@ contract UnirepApp is Ownable {
revert NonNegativeReputation();
}
verifierHelperManager.verifyProof(publicSignals, proof, identifier);
verifierHelperManager.verifyProof(
publicSignals,
proof,
identifier
);
// attesting on Unirep contract:
unirep.attest(
@@ -373,7 +438,10 @@ contract UnirepApp is Ownable {
1
);
emit ClaimPosRep(signals.epochKey, epoch);
emit ClaimPosRep(
signals.epochKey,
epoch
);
}
/**
@@ -387,7 +455,7 @@ contract UnirepApp is Ownable {
uint256[8] calldata proof,
bytes32 identifier,
uint256 change
) public onlyOwner {
) public onlyOwner() {
// check if proof is used before
bytes32 nullifier = keccak256(abi.encodePacked(publicSignals, proof));
if (proofNullifier[nullifier]) {
@@ -396,8 +464,11 @@ contract UnirepApp is Ownable {
proofNullifier[nullifier] = true;
BaseVerifierHelper.EpochKeySignals memory signals =
verifierHelperManager.verifyProof(publicSignals, proof, identifier);
BaseVerifierHelper.EpochKeySignals memory signals = verifierHelperManager.verifyProof(
publicSignals,
proof,
identifier
);
// check the epoch != current epoch (ppl can only claim in current epoch)
uint48 epoch = unirep.attesterCurrentEpoch(signals.attesterId);
@@ -408,7 +479,12 @@ contract UnirepApp is Ownable {
// attesting on Unirep contract:
// 1. punishing poster (5)
// 2. punishing reporter (1)
unirep.attest(signals.epochKey, epoch, negRepFieldIndex, change);
unirep.attest(
signals.epochKey,
epoch,
negRepFieldIndex,
change
);
emit ClaimNegRep(signals.epochKey, epoch);
}

View File

@@ -1,25 +1,24 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {Unirep} from "@unirep/contracts/Unirep.sol";
import {IVerifier} from "@unirep/contracts/interfaces/IVerifier.sol";
import {BaseVerifierHelper} from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import { Unirep } from "@unirep/contracts/Unirep.sol";
import { IVerifier } from "@unirep/contracts/interfaces/IVerifier.sol";
import { BaseVerifierHelper } from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
/// @title IVerifierHelper
/// @dev Interface for VerifierHelpers in Unirep Social-TW
interface IVerifierHelper {
/// @param publicSignals The public signals of the snark proof
/// @return signals The EpochKeySignals
function decodeSignals(uint256[] calldata publicSignals)
external
pure
returns (BaseVerifierHelper.EpochKeySignals memory);
function decodeSignals(
uint256[] calldata publicSignals
) external pure returns (BaseVerifierHelper.EpochKeySignals memory);
/// @param publicSignals The public signals of the snark proof
/// @param proof The proof data of the snark proof
/// @return signals The EpochKeySignals
function verifyAndCheck(uint256[] calldata publicSignals, uint256[8] calldata proof)
external
view
returns (BaseVerifierHelper.EpochKeySignals memory);
function verifyAndCheck(
uint256[] calldata publicSignals,
uint256[8] calldata proof
) external view returns (BaseVerifierHelper.EpochKeySignals memory);
}

View File

@@ -1,13 +1,16 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {BaseVerifierHelper} from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import {Unirep} from "@unirep/contracts/Unirep.sol";
import {IVerifier} from "@unirep/contracts/interfaces/IVerifier.sol";
import {IVerifierHelper} from "../interfaces/IVerifierHelper.sol";
import { BaseVerifierHelper } from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import { Unirep } from "@unirep/contracts/Unirep.sol";
import { IVerifier } from "@unirep/contracts/interfaces/IVerifier.sol";
import { IVerifierHelper } from "../interfaces/IVerifierHelper.sol";
contract DailyClaimVHelper is BaseVerifierHelper, IVerifierHelper {
constructor(Unirep _unirep, IVerifier _verifier) BaseVerifierHelper(_unirep, _verifier) {}
constructor(
Unirep _unirep,
IVerifier _verifier
) BaseVerifierHelper(_unirep, _verifier) {}
struct DailyClaimSignals {
uint256 epochKey;
@@ -28,12 +31,19 @@ contract DailyClaimVHelper is BaseVerifierHelper, IVerifierHelper {
/// @param publicSignals The public signals of the snark proof
/// @return signals The EpochKeySignals
function decodeSignals(uint256[] calldata publicSignals) public pure returns (EpochKeySignals memory) {
function decodeSignals(
uint256[] calldata publicSignals
) public pure returns (EpochKeySignals memory) {
EpochKeySignals memory signals;
(signals.nonce, signals.epoch, signals.attesterId, signals.revealNonce, signals.chainId) =
super.decodeEpochKeyControl(publicSignals[1]);
(
signals.nonce,
signals.epoch,
signals.attesterId,
signals.revealNonce,
signals.chainId
) = super.decodeEpochKeyControl(publicSignals[1]);
signals.epochKey = publicSignals[0];
if (signals.epochKey >= SNARK_SCALAR_FIELD) revert InvalidEpochKey();
return signals;
@@ -42,15 +52,22 @@ contract DailyClaimVHelper is BaseVerifierHelper, IVerifierHelper {
/// @dev https://developer.unirep.io/docs/contracts-api/verifiers/reputation-verifier-helper#decodereputationsignals
/// @param publicSignals The public signals of the snark proof
/// @return signals The ReputationSignals
function decodeDailyClaimSignals(uint256[] calldata publicSignals) public pure returns (DailyClaimSignals memory) {
function decodeDailyClaimSignals(
uint256[] calldata publicSignals
) public pure returns (DailyClaimSignals memory) {
DailyClaimSignals memory signals;
signals.epochKey = publicSignals[0];
signals.dailyEpoch = uint48(publicSignals[3]);
signals.dailyNullifier = publicSignals[4];
// now decode the control values
(signals.nonce, signals.epoch, signals.attesterId, signals.revealNonce, signals.chainId) =
super.decodeEpochKeyControl(publicSignals[1]);
(
signals.nonce,
signals.epoch,
signals.attesterId,
signals.revealNonce,
signals.chainId
) = super.decodeEpochKeyControl(publicSignals[1]);
(
signals.minRep,
@@ -66,15 +83,14 @@ contract DailyClaimVHelper is BaseVerifierHelper, IVerifierHelper {
return signals;
}
/// @param publicSignals The public signals of the snark proof
/// @param proof The proof data of the snark proof
/// @return signals The EpochKeySignals
function verifyAndCheck(uint256[] calldata publicSignals, uint256[8] calldata proof)
public
view
returns (EpochKeySignals memory)
{
function verifyAndCheck(
uint256[] calldata publicSignals,
uint256[8] calldata proof
) public view returns (EpochKeySignals memory) {
EpochKeySignals memory signals = decodeSignals(publicSignals);
if (!verifier.verifyProof(publicSignals, proof)) revert InvalidProof();
@@ -90,7 +106,9 @@ contract DailyClaimVHelper is BaseVerifierHelper, IVerifierHelper {
/// @return proveMaxRep Whether to prove maximum rep information in the control field
/// @return proveZeroRep Whether to prove zero rep information in the control field
/// @return proveGraffiti Whether to prove graffiti information in the control field
function decodeReputationControl(uint256 control)
function decodeReputationControl(
uint256 control
)
public
pure
returns (
@@ -123,4 +141,4 @@ contract DailyClaimVHelper is BaseVerifierHelper, IVerifierHelper {
proveGraffiti = bool(shiftAndParse(control, accBits, oneBit) != 0);
accBits += oneBit;
}
}
}

View File

@@ -1,39 +1,48 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {BaseVerifierHelper} from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import {Unirep} from "@unirep/contracts/Unirep.sol";
import {IVerifier} from "@unirep/contracts/interfaces/IVerifier.sol";
import {IVerifierHelper} from "../interfaces/IVerifierHelper.sol";
import { BaseVerifierHelper } from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import { Unirep } from "@unirep/contracts/Unirep.sol";
import { IVerifier } from "@unirep/contracts/interfaces/IVerifier.sol";
import { IVerifierHelper } from "../interfaces/IVerifierHelper.sol";
contract ReportNonNullifierVHelper is BaseVerifierHelper, IVerifierHelper {
constructor(Unirep _unirep, IVerifier _verifier) BaseVerifierHelper(_unirep, _verifier) {}
constructor(
Unirep _unirep,
IVerifier _verifier
) BaseVerifierHelper(_unirep, _verifier) {}
/// @param publicSignals The public signals of the snark proof
/// @return signals The EpochKeySignals
function decodeSignals(uint256[] calldata publicSignals) public pure returns (EpochKeySignals memory) {
function decodeSignals(
uint256[] calldata publicSignals
) public pure returns (EpochKeySignals memory) {
EpochKeySignals memory signals;
(signals.nonce, signals.epoch, signals.attesterId, signals.revealNonce, signals.chainId) =
super.decodeEpochKeyControl(publicSignals[0]);
(
signals.nonce,
signals.epoch,
signals.attesterId,
signals.revealNonce,
signals.chainId
) = super.decodeEpochKeyControl(publicSignals[0]);
signals.epochKey = publicSignals[1];
if (signals.epochKey >= SNARK_SCALAR_FIELD) revert InvalidEpochKey();
return signals;
}
/// @param publicSignals The public signals of the snark proof
/// @param proof The proof data of the snark proof
/// @return signals The EpochKeySignals
function verifyAndCheck(uint256[] calldata publicSignals, uint256[8] calldata proof)
public
view
returns (EpochKeySignals memory)
{
function verifyAndCheck(
uint256[] calldata publicSignals,
uint256[8] calldata proof
) public view returns (EpochKeySignals memory) {
EpochKeySignals memory signals = decodeSignals(publicSignals);
if (!verifier.verifyProof(publicSignals, proof)) revert InvalidProof();
return signals;
}
}
}

View File

@@ -1,40 +1,49 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {BaseVerifierHelper} from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import {Unirep} from "@unirep/contracts/Unirep.sol";
import {IVerifier} from "@unirep/contracts/interfaces/IVerifier.sol";
import {IVerifierHelper} from "../interfaces/IVerifierHelper.sol";
import { BaseVerifierHelper } from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import { Unirep } from "@unirep/contracts/Unirep.sol";
import { IVerifier } from "@unirep/contracts/interfaces/IVerifier.sol";
import { IVerifierHelper } from "../interfaces/IVerifierHelper.sol";
contract ReportNullifierVHelper is BaseVerifierHelper, IVerifierHelper {
constructor(Unirep _unirep, IVerifier _verifier) BaseVerifierHelper(_unirep, _verifier) {}
constructor(
Unirep _unirep,
IVerifier _verifier
) BaseVerifierHelper(_unirep, _verifier) {}
/// @param publicSignals The public signals of the snark proof
/// @return signals The EpochKeySignals
function decodeSignals(uint256[] calldata publicSignals) public pure returns (EpochKeySignals memory) {
function decodeSignals(
uint256[] calldata publicSignals
) public pure returns (EpochKeySignals memory) {
EpochKeySignals memory signals;
(signals.nonce, signals.epoch, signals.attesterId, signals.revealNonce, signals.chainId) =
super.decodeEpochKeyControl(publicSignals[0]);
(
signals.nonce,
signals.epoch,
signals.attesterId,
signals.revealNonce,
signals.chainId
) = super.decodeEpochKeyControl(publicSignals[0]);
signals.epochKey = publicSignals[1];
if (signals.epochKey >= SNARK_SCALAR_FIELD) revert InvalidEpochKey();
return signals;
}
/// @param publicSignals The public signals of the snark proof
/// @param proof The proof data of the snark proof
/// @return signals The EpochKeySignals
function verifyAndCheck(uint256[] calldata publicSignals, uint256[8] calldata proof)
public
view
returns (EpochKeySignals memory)
{
function verifyAndCheck(
uint256[] calldata publicSignals,
uint256[8] calldata proof
) public view returns (EpochKeySignals memory) {
EpochKeySignals memory signals = decodeSignals(publicSignals);
if (!verifier.verifyProof(publicSignals, proof)) revert InvalidProof();
return signals;
}
}
}

View File

@@ -1,19 +1,21 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import {IVerifierHelper} from "../interfaces/IVerifierHelper.sol";
import {BaseVerifierHelper} from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import { IVerifierHelper } from "../interfaces/IVerifierHelper.sol";
import { BaseVerifierHelper } from "@unirep/contracts/verifierHelpers/BaseVerifierHelper.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
contract VerifierHelperManager is Ownable {
mapping(bytes32 => address) public registeredVHelpers; // see verifierRegister
error IdentifierNotRegistered(bytes32);
/// @dev register VerifierHelper Contract in Unirep Social-TW
/// @param identifier sha256(verifier_contract_name)
/// @param addr the address where the verifier is deployed
function verifierRegister(bytes32 identifier, address addr) public onlyOwner {
/// @param addr the address where the verifier is deployed
function verifierRegister(
bytes32 identifier,
address addr
) public onlyOwner() {
registeredVHelpers[identifier] = addr;
}
@@ -22,17 +24,16 @@ contract VerifierHelperManager is Ownable {
/// @param proof The proof data of the snark proof
/// @param identifier sha256(verifier_contract_name)
/// @return signals The EpochKeySignals from BaseVerifierHelper
function verifyProof(uint256[] calldata publicSignals, uint256[8] calldata proof, bytes32 identifier)
public
view
returns (BaseVerifierHelper.EpochKeySignals memory)
{
function verifyProof(
uint256[] calldata publicSignals,
uint256[8] calldata proof,
bytes32 identifier
) public view returns (BaseVerifierHelper.EpochKeySignals memory) {
address vHelperAddr = registeredVHelpers[identifier];
if (vHelperAddr == address(0)) {
revert IdentifierNotRegistered(identifier);
}
BaseVerifierHelper.EpochKeySignals memory signal =
IVerifierHelper(vHelperAddr).verifyAndCheck(publicSignals, proof);
return signal;
BaseVerifierHelper.EpochKeySignals memory signal = IVerifierHelper(vHelperAddr).verifyAndCheck(publicSignals, proof);
return signal;
}
}
}

View File

@@ -21,12 +21,11 @@ const VHelperManager = VerifierHelperManager // alias for verifier helper manage
export async function deployApp(deployer: ethers.Signer, epochLength: number) {
const unirep = await deployUnirep(deployer)
const repHelper = await deployVerifierHelper(
const epkHelper = await deployVerifierHelper(
unirep.address,
deployer,
Circuit.reputation
Circuit.epochKey
)
const epkLiteHelper = await deployVerifierHelper(
unirep.address,
deployer,
@@ -112,7 +111,7 @@ export async function deployApp(deployer: ethers.Signer, epochLength: number) {
const app = await AppF.deploy(
unirep.address,
repHelper.address,
epkHelper.address,
epkLiteHelper.address,
dataProofVerifier.address,
vHelperManager.address,

View File

@@ -1,9 +1,9 @@
// @ts-ignore
import { ethers } from 'hardhat'
import { DailyClaimProof } from '@unirep-app/circuits'
import { ReputationProof } from '@unirep/circuits'
import { genEpochKey } from '@unirep/utils'
import { expect } from 'chai'
import { ethers } from 'hardhat'
import { deployApp } from '../scripts/utils/deployUnirepSocialTw'
import { Unirep, UnirepApp } from '../typechain-types'
import { IdentityObject } from './types'

View File

@@ -1,15 +1,16 @@
//@ts-ignore
import { CircuitConfig } from '@unirep/circuits'
import { expect } from 'chai'
import { ethers } from 'hardhat'
import { expect } from 'chai'
import { CircuitConfig } from '@unirep/circuits'
import { describe } from 'node:test'
import { deployApp } from '../scripts/utils/deployUnirepSocialTw'
import { Unirep, UnirepApp } from '../typechain-types'
import {
createMultipleUserIdentity,
genEpochKeyLiteProof,
genReputationProof,
genEpochKeyProof,
genUserState,
randomData,
} from './utils'
const { STATE_TREE_DEPTH } = CircuitConfig.default
@@ -67,8 +68,9 @@ describe('Comment Test', function () {
// user 1 post something
const content = 'something interesting'
const userState = await genUserState(users[0].id, app)
const repProof = await userState.genProveReputationProof({})
await app.post(repProof.publicSignals, repProof.proof, content)
const { publicSignals: epochKeySig1, proof: epochKeyProof1 } =
await userState.genEpochKeyProof()
await app.post(epochKeySig1, epochKeyProof1, content)
chainId = await unirep.chainid()
})
@@ -77,18 +79,17 @@ describe('Comment Test', function () {
it('should revert leaving comment with invalid epoch', async function () {
const userState = await genUserState(users[1].id, app)
const id = users[1].id
const attesterId = userState.sync.attesterId
const epoch = await userState.sync.loadCurrentEpoch()
// generating a proof with wrong epoch
const wrongEpoch = 44444
const attesterId = userState.sync.attesterId
const epoch = await userState.sync.loadCurrentEpoch()
const tree = await userState.sync.genStateTree(epoch, attesterId)
const leafIndex = await userState.latestStateTreeLeafIndex(
epoch,
attesterId
)
const data = await userState.getProvableData()
const repProof = await genReputationProof({
const data = randomData()
const { publicSignals, proof } = await genEpochKeyProof({
id,
tree,
leafIndex,
@@ -98,60 +99,48 @@ describe('Comment Test', function () {
attesterId,
data,
})
const postId = 0
await expect(
app.leaveComment(
repProof.publicSignals,
repProof.proof,
postId,
'Invalid Epoch'
)
app.leaveComment(publicSignals, proof, postId, 'Invalid Epoch')
).to.be.revertedWithCustomError(app, 'InvalidEpoch')
userState.stop()
})
it('should revert leaving comment with invalid reputation proof', async function () {
it('should revert leaving comment with invalid epoch key proof', async function () {
const userState = await genUserState(users[1].id, app)
const repProof = await userState.genProveReputationProof({})
const { publicSignals, proof } = await userState.genEpochKeyProof({
nonce: 0,
})
const content = 'This is so interesting!'
repProof.proof[0] = BigInt(0)
proof[0] = BigInt(0)
await expect(
app.leaveComment(
repProof.publicSignals,
repProof.proof,
BigInt(0),
content
)
app.leaveComment(publicSignals, proof, BigInt(0), content)
).to.be.reverted
userState.stop()
})
it('should comment with valid reputation proof and signals', async function () {
it('should comment with valid epoch key proof and signals', async function () {
const userState = await genUserState(users[1].id, app)
const repProof = await userState.genProveReputationProof({})
const { publicSignals, proof } = await userState.genEpochKeyProof({
nonce: 0,
})
const content = 'This is so interesting!'
const postId = 0
const commentId = 0
const epoch = await userState.sync.loadCurrentEpoch()
// record the used proof here
inputPublicSig = repProof.publicSignals
inputProof = repProof.proof
inputPublicSig = publicSignals
inputProof = proof
await expect(
app.leaveComment(
repProof.publicSignals,
repProof.proof,
postId,
content
)
app.leaveComment(publicSignals, proof, postId, content)
)
.to.emit(app, 'Comment')
.withArgs(
repProof.publicSignals[0], // epochKey
publicSignals[0], // epochKey
postId,
commentId,
epoch,

View File

@@ -1,21 +1,22 @@
//@ts-ignore
import { ethers } from 'hardhat'
import { DataProof } from '@unirep-app/circuits'
import { defaultProver as prover } from '@unirep-app/circuits/provers/defaultProver'
import { Circuit, CircuitConfig } from '@unirep/circuits'
import { deployVerifierHelper } from '@unirep/contracts/deploy'
import { stringifyBigInts } from '@unirep/utils'
import { expect } from 'chai'
import { ethers } from 'hardhat'
import { describe } from 'node:test'
import { deployApp } from '../scripts/utils/deployUnirepSocialTw'
import { IdentityObject } from './types'
import {
createRandomUserIdentity,
genReputationProof,
genEpochKeyProof,
genUserState,
randomData,
} from './utils'
const { FIELD_COUNT } = CircuitConfig.default
const { FIELD_COUNT, STATE_TREE_DEPTH } = CircuitConfig.default
describe('Unirep App', function () {
let unirep: any
@@ -114,15 +115,16 @@ describe('Unirep App', function () {
describe('user post', function () {
it('should fail to post with invalid proof', async function () {
const userState = await genUserState(user.id, app)
const repProof = await userState.genProveReputationProof({})
const { publicSignals, proof } = await userState.genEpochKeyProof()
// generate a fake proof
repProof.proof[0] = BigInt(0)
const concoctProof = [...proof]
const len = concoctProof[0].toString().length
concoctProof[0] = BigInt(2)
const content = 'Invalid Proof'
await expect(
app.post(repProof.publicSignals, repProof.proof, content)
).to.be.reverted // revert in epkHelper.verifyAndCheck()
await expect(app.post(publicSignals, concoctProof, content)).to.be
.reverted // revert in epkHelper.verifyAndCheck()
userState.stop()
})
@@ -130,13 +132,14 @@ describe('Unirep App', function () {
it('should post with valid proof', async function () {
const content = 'Valid Proof'
const userState = await genUserState(user.id, app)
const repProof = await userState.genProveReputationProof({})
const { publicSignals, proof } = await userState.genEpochKeyProof()
await expect(
app.post(repProof.publicSignals, repProof.proof, content)
)
inputPublicSig = publicSignals
inputProof = proof
await expect(app.post(publicSignals, proof, content))
.to.emit(app, 'Post')
.withArgs(repProof.publicSignals[0], 0, 0, content)
.withArgs(publicSignals[0], 0, 0, content)
userState.stop()
})
@@ -144,16 +147,14 @@ describe('Unirep App', function () {
it('should post and have the correct postId', async function () {
const content = 'Valid Proof'
const userState = await genUserState(user.id, app)
const repProof = await userState.genProveReputationProof({})
const { publicSignals, proof } = await userState.genEpochKeyProof()
inputPublicSig = repProof.publicSignals
inputProof = repProof.proof
inputPublicSig = publicSignals
inputProof = proof
await expect(
app.post(repProof.publicSignals, repProof.proof, content)
)
await expect(app.post(publicSignals, proof, content))
.to.emit(app, 'Post')
.withArgs(repProof.publicSignals[0], 1, 0, content)
.withArgs(publicSignals[0], 1, 0, content)
userState.stop()
})
@@ -177,10 +178,8 @@ describe('Unirep App', function () {
epoch,
attesterId
)
const data = await userState.getProvableData()
const repProof = await genReputationProof({
const data = randomData()
const { publicSignals, proof } = await genEpochKeyProof({
id,
tree,
leafIndex,
@@ -190,13 +189,8 @@ describe('Unirep App', function () {
attesterId,
data,
})
await expect(
app.post(
repProof.publicSignals,
repProof.proof,
'Invalid Epoch'
)
app.post(publicSignals, proof, 'Invalid Epoch')
).to.be.revertedWithCustomError(app, 'InvalidEpoch')
userState.stop()

View File

@@ -1,7 +1,7 @@
//@ts-ignore
import { genEpochKey } from '@unirep/utils'
import { expect } from 'chai'
import { ethers } from 'hardhat'
import { expect } from 'chai'
import { genEpochKey } from '@unirep/utils'
import { describe } from 'node:test'
import { deployApp } from '../scripts/utils/deployUnirepSocialTw'
import { Unirep, UnirepApp } from '../typechain-types'
@@ -15,7 +15,7 @@ import {
genReportNullifierCircuitInput,
} from './utils'
describe('Verifier Helper Test', function () {
describe('Verifier Helper Manager Test', function () {
let unirep: Unirep
let app: UnirepApp
let reportNonNullifierVHelper: any

View File

@@ -1,7 +1,7 @@
//@ts-ignore
import { genEpochKey } from '@unirep/utils'
import { expect } from 'chai'
import { ethers } from 'hardhat'
import { expect } from 'chai'
import { genEpochKey } from '@unirep/utils'
import { describe } from 'node:test'
import { deployApp } from '../scripts/utils/deployUnirepSocialTw'
import { Unirep, UnirepApp } from '../typechain-types'
@@ -15,7 +15,7 @@ import {
genReportNullifierCircuitInput,
} from './utils'
describe('Verifier Test', function () {
describe('Verifier Helper Manager Test', function () {
let unirep: Unirep
let app: UnirepApp
let reportNonNullifierVerifier

View File

@@ -163,75 +163,6 @@ export async function genEpochKeyLiteProof(config: {
return { publicSignals, proof }
}
export async function genReputationProof(config: {
id: Identity
tree: IncrementalMerkleTree
leafIndex: number
data?: bigint[]
graffiti?: any
revealNonce?: number
attesterId: number | bigint
epoch: number
nonce: number
minRep?: number
maxRep?: number
proveZeroRep?: boolean
sigData?: bigint
chainId: number
}) {
const {
id,
tree,
leafIndex,
data,
graffiti,
revealNonce,
attesterId,
epoch,
nonce,
minRep,
maxRep,
proveZeroRep,
sigData,
chainId,
} = Object.assign(config)
const _proof = tree.createProof(leafIndex)
const circuitInputs = {
identity_secret: id.secret,
state_tree_indices: _proof.pathIndices,
state_tree_elements: _proof.siblings,
data,
prove_graffiti: graffiti ? 1 : 0,
graffiti: BigInt(graffiti ?? 0),
reveal_nonce: revealNonce ?? 0,
attester_id: attesterId,
epoch,
nonce,
min_rep: minRep ?? 0,
max_rep: maxRep ?? 0,
prove_min_rep: !!(minRep ?? 0) ? 1 : 0,
prove_max_rep: !!(maxRep ?? 0) ? 1 : 0,
prove_zero_rep: proveZeroRep ?? 0,
sig_data: sigData ?? 0,
chain_id: chainId,
}
const r = await prover.genProofAndPublicSignals(
Circuit.reputation,
circuitInputs
)
const { publicSignals, proof } = new ReputationProof(
r.publicSignals,
r.proof,
prover
)
return { publicSignals, proof }
}
export const randomData = () => [
...Array(SUM_FIELD_COUNT)
.fill(0)

View File

@@ -80,7 +80,7 @@ describe('CheckReputation', function () {
revealNonce: 0,
})
const { publicSignals, proof } = await genProofAndVerify(
const { isValid, publicSignals, proof } = await genProofAndVerify(
Circuit.reputation,
circuitInputs
)