Skip to content

Commit

Permalink
try to split ITreeVerifier
Browse files Browse the repository at this point in the history
  • Loading branch information
wzmuda committed Sep 9, 2024
1 parent 1534c98 commit cbe167d
Show file tree
Hide file tree
Showing 19 changed files with 395 additions and 128 deletions.
12 changes: 7 additions & 5 deletions src/WorldIDIdentityManagerImplV3.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
pragma solidity ^0.8.24;

import "./WorldIDIdentityManagerImplV2.sol";
import "./interfaces/ITreeVerifier4844.sol";
import {VerifierLookupTable4844} from "./data/VerifierLookupTable4844.sol";

/// @title WorldID Identity Manager Implementation Version 3
/// @author Worldcoin
Expand Down Expand Up @@ -48,7 +50,7 @@ contract WorldIDIdentityManagerImplV3 is WorldIDIdentityManagerImplV2 {
// memory safety error).

/// @notice The table of verifiers for verifying batch identity insertions following the EIP-4844 scheme.
VerifierLookupTable internal batchInsertion4844Verifiers;
VerifierLookupTable4844 internal batchInsertion4844Verifiers;

/// @notice Thrown when the WorldIDIdentityManagerImplV3 contract is initialized
event WorldIDIdentityManagerImplV3Initialized();
Expand All @@ -65,7 +67,7 @@ contract WorldIDIdentityManagerImplV3 is WorldIDIdentityManagerImplV2 {
///
///
/// @custom:reverts InvalidVerifierLUT if `_batchInsertion4844Verifiers` is set to the zero address
function initializeV3(VerifierLookupTable _batchInsertion4844Verifiers) public reinitializer(3) {
function initializeV3(VerifierLookupTable4844 _batchInsertion4844Verifiers) public reinitializer(3) {
if (address(_batchInsertion4844Verifiers) == address(0)) {
revert InvalidVerifierLUT();
}
Expand Down Expand Up @@ -101,7 +103,7 @@ contract WorldIDIdentityManagerImplV3 is WorldIDIdentityManagerImplV2 {
/// @param newTable The new verifier lookup table to be used for verifying identity
/// registrations.
/// @custom:reverts InvalidVerifierLUT if `newTable` is set to the zero address
function setRegisterIdentities4844VerifierLookupTable(VerifierLookupTable newTable)
function setRegisterIdentities4844VerifierLookupTable(VerifierLookupTable4844 newTable)
public
virtual
onlyProxy
Expand All @@ -112,7 +114,7 @@ contract WorldIDIdentityManagerImplV3 is WorldIDIdentityManagerImplV2 {
revert InvalidVerifierLUT();
}

VerifierLookupTable oldTable = batchInsertion4844Verifiers;
VerifierLookupTable4844 oldTable = batchInsertion4844Verifiers;
batchInsertion4844Verifiers = newTable;
emit DependencyUpdated(
Dependency.InsertionVerifierLookupTable, address(oldTable), address(newTable)
Expand Down Expand Up @@ -213,7 +215,7 @@ contract WorldIDIdentityManagerImplV3 is WorldIDIdentityManagerImplV2 {
}

// We need to look up the correct verifier before we can verify.
ITreeVerifier insertionVerifier =
ITreeVerifier4844 insertionVerifier =
batchInsertion4844Verifiers.getVerifierFor(params.batchSize);

// With that, we can properly try and verify.
Expand Down
177 changes: 177 additions & 0 deletions src/data/VerifierLookupTable4844.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {Ownable2Step} from "openzeppelin-contracts/access/Ownable2Step.sol";

import {ITreeVerifier4844} from "../interfaces/ITreeVerifier4844.sol";

/// @title Batch Lookup Table for EIP-4844 proofs.
/// @author Worldcoin
/// @notice A table that provides the correct tree verifier based on the provided batch size.
/// @dev It should be used to query the correct verifier before using that verifier for verifying a
/// tree modification proof.
contract VerifierLookupTable4844 is Ownable2Step {
////////////////////////////////////////////////////////////////////////////////
/// DATA ///
////////////////////////////////////////////////////////////////////////////////

/// The null address.
address internal constant nullAddress = address(0x0);

/// The null verifiers.
ITreeVerifier4844 internal constant nullVerifier = ITreeVerifier4844(nullAddress);

/// The lookup table for routing batches.
///
/// As we expect to only have a few batch sizes per contract, a mapping is used due to its
/// natively sparse storage.
mapping(uint256 => ITreeVerifier4844) internal verifier_lut;


////////////////////////////////////////////////////////////////////////////////
/// ERRORS ///
////////////////////////////////////////////////////////////////////////////////

/// @notice Raised if a batch size is requested that the lookup table doesn't know about.
error NoSuchVerifier();

/// @notice Raised if an attempt is made to add a verifier for a batch size that already exists.
error VerifierExists();

/// @notice Thrown when an attempt is made to renounce ownership.
error CannotRenounceOwnership();

////////////////////////////////////////////////////////////////////////////////
/// EVENTS ///
////////////////////////////////////////////////////////////////////////////////

/// @notice Emitted when a verifier is added to the lookup table.
///
/// @param batchSize The size of the batch that the verifier has been added for.
/// @param verifierAddress The address of the verifier that was associated with `batchSize`.
event VerifierAdded(uint256 indexed batchSize, address indexed verifierAddress);

/// @notice Emitted when a verifier is updated in the lookup table.
///
/// @param batchSize The size of the batch that the verifier has been updated for.
/// @param oldVerifierAddress The address of the old verifier for `batchSize`.
/// @param newVerifierAddress The address of the new verifier for `batchSize`.
event VerifierUpdated(
uint256 indexed batchSize,
address indexed oldVerifierAddress,
address indexed newVerifierAddress
);

/// @notice Emitted when a verifier is disabled in the lookup table.
///
/// @param batchSize The batch size that had its verifier disabled.
event VerifierDisabled(uint256 indexed batchSize);

////////////////////////////////////////////////////////////////////////////////
/// CONSTRUCTION ///
////////////////////////////////////////////////////////////////////////////////

/// @notice Constructs a new batch lookup table.
/// @dev It is initially constructed without any verifiers.
constructor() Ownable2Step() {}

////////////////////////////////////////////////////////////////////////////////
/// ACCESSORS ///
////////////////////////////////////////////////////////////////////////////////

/// @notice Obtains the verifier for the provided `batchSize`.
///
/// @param batchSize The batch size to get the associated verifier for.
///
/// @return verifier The tree verifier for the provided `batchSize`.
///
/// @custom:reverts NoSuchVerifier If there is no verifier associated with the `batchSize`.
function getVerifierFor(uint256 batchSize) public view returns (ITreeVerifier4844 verifier) {
// Check the preconditions for querying the verifier.
validateVerifier(batchSize);

// With the preconditions checked, we can return the verifier.
verifier = verifier_lut[batchSize];
}

/// @notice Adds a verifier for the provided `batchSize`.
///
/// @param batchSize The batch size to add the verifier for.
/// @param verifier The verifier for a batch of size `batchSize`.
///
/// @custom:reverts VerifierExists If `batchSize` already has an associated verifier.
/// @custom:reverts string If the caller is not the owner.
function addVerifier(uint256 batchSize, ITreeVerifier4844 verifier) public onlyOwner {
// Check that there is no entry for that batch size.
if (verifier_lut[batchSize] != nullVerifier) {
revert VerifierExists();
}

// Add the verifier.
updateVerifier(batchSize, verifier);
emit VerifierAdded(batchSize, address(verifier));
}

/// @notice Updates the verifier for the provided `batchSize`.
///
/// @param batchSize The batch size to add the verifier for.
/// @param verifier The verifier for a batch of size `batchSize`.
///
/// @return oldVerifier The old verifier instance associated with this batch size.
///
/// @custom:reverts string If the caller is not the owner.
function updateVerifier(uint256 batchSize, ITreeVerifier4844 verifier)
public
onlyOwner
returns (ITreeVerifier4844 oldVerifier)
{
oldVerifier = verifier_lut[batchSize];
verifier_lut[batchSize] = verifier;
emit VerifierUpdated(batchSize, address(oldVerifier), address(verifier));
}

/// @notice Disables the verifier for the provided batch size.
///
/// @param batchSize The batch size to disable the verifier for.
///
/// @return oldVerifier The old verifier associated with the batch size.
///
/// @custom:reverts string If the caller is not the owner.
function disableVerifier(uint256 batchSize)
public
onlyOwner
returns (ITreeVerifier4844 oldVerifier)
{
oldVerifier = updateVerifier(batchSize, ITreeVerifier4844(nullAddress));
emit VerifierDisabled(batchSize);
}

////////////////////////////////////////////////////////////////////////////////
/// INTERNAL FUNCTIONALITY ///
////////////////////////////////////////////////////////////////////////////////

/// @notice Checks if the entry for the provided `batchSize` is a valid verifier.
///
/// @param batchSize The batch size to check.
///
/// @custom:reverts NoSuchVerifier If `batchSize` does not have an associated verifier.
/// @custom:reverts BatchTooLarge If `batchSize` exceeds the maximum batch size.
function validateVerifier(uint256 batchSize) internal view {
if (verifier_lut[batchSize] == nullVerifier) {
revert NoSuchVerifier();
}
}

////////////////////////////////////////////////////////////////////////////////
/// OWNERSHIP MANAGEMENT ///
////////////////////////////////////////////////////////////////////////////////

/// @notice Ensures that ownership of the lookup table cannot be renounced.
/// @dev This function is intentionally not `virtual` as we do not want it to be possible to
/// renounce ownership for the lookup table.
/// @dev This function is marked as `onlyOwner` to maintain the access restriction from the base
/// contract.
function renounceOwnership() public view override onlyOwner {
revert CannotRenounceOwnership();
}
}
18 changes: 0 additions & 18 deletions src/interfaces/ITreeVerifier.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,4 @@ interface ITreeVerifier {
/// @param input the public input field elements in the scalar field Fr.
/// Elements must be reduced.
function verifyProof(uint256[8] calldata proof, uint256[1] calldata input) external;

/// Verify an uncompressed Groth16 proof.
/// @notice Reverts with InvalidProof if the proof is invalid or
/// with PublicInputNotInField the public input is not reduced.
/// @notice There is no return value. If the function does not revert, the
/// proof was successfully verified.
/// @param proof the points (A, B, C) in EIP-197 format matching the output
/// of compressProof.
/// @param commitments the Pedersen commitments from the proof.
/// @param commitmentPok the proof of knowledge for the Pedersen commitments.
/// @param input the public input field elements in the scalar field Fr.
/// Elements must be reduced.
function verifyProof(
uint256[8] calldata proof,
uint256[2] calldata commitments,
uint256[2] calldata commitmentPok,
uint256[6] calldata input
) external;
}
25 changes: 25 additions & 0 deletions src/interfaces/ITreeVerifier4844.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

/// @title Tree Verifier Interface
/// @author Worldcoin
/// @notice An interface representing a merkle tree verifier for EIP-4844 proofs.
interface ITreeVerifier4844 {
/// Verify an uncompressed Groth16 proof.
/// @notice Reverts with InvalidProof if the proof is invalid or
/// with PublicInputNotInField the public input is not reduced.
/// @notice There is no return value. If the function does not revert, the
/// proof was successfully verified.
/// @param proof the points (A, B, C) in EIP-197 format matching the output
/// of compressProof.
/// @param commitments the Pedersen commitments from the proof.
/// @param commitmentPok the proof of knowledge for the Pedersen commitments.
/// @param input the public input field elements in the scalar field Fr.
/// Elements must be reduced.
function verifyProof(
uint256[8] calldata proof,
uint256[2] calldata commitments,
uint256[2] calldata commitmentPok,
uint256[6] calldata input
) external;
}
10 changes: 0 additions & 10 deletions src/test/DeletionTreeVerifier16.sol
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,4 @@ contract Verifier is ITreeVerifier {
revert ProofInvalid();
}
}

/// Dummy implementation to satisfy ITreeVerifier interface.
function verifyProof(
uint256[8] calldata,
uint256[2] calldata,
uint256[2] calldata,
uint256[6] calldata
) public pure {
revert ProofInvalid();
}
}
10 changes: 0 additions & 10 deletions src/test/InsertionTreeVerifier16.sol
Original file line number Diff line number Diff line change
Expand Up @@ -564,14 +564,4 @@ contract Verifier is ITreeVerifier {
revert ProofInvalid();
}
}

/// Dummy implementation to satisfy ITreeVerifier interface.
function verifyProof(
uint256[8] calldata,
uint256[2] calldata,
uint256[2] calldata,
uint256[6] calldata
) public pure {
revert ProofInvalid();
}
}
8 changes: 2 additions & 6 deletions src/test/InsertionTreeVerifier164844.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {ITreeVerifier} from "src/interfaces/ITreeVerifier.sol";
import {ITreeVerifier4844} from "src/interfaces/ITreeVerifier4844.sol";

// SPDX-License-Identifier: MIT

Expand All @@ -10,7 +10,7 @@ pragma solidity ^0.8.0;
/// (256 bytes) and compressed (128 bytes) format. A view function is provided
/// to compress proofs.
/// @notice See <https://2π.com/23/bn254-compression> for further explanation.
contract Verifier is ITreeVerifier {
contract Verifier is ITreeVerifier4844 {

/// Some of the provided public input values are larger than the field modulus.
/// @dev Public input elements are not automatically reduced, as this is can be
Expand Down Expand Up @@ -716,8 +716,4 @@ contract Verifier is ITreeVerifier {
revert ProofInvalid();
}
}

function verifyProof(uint256[8] calldata, uint256[1] calldata) public pure {
revert ProofInvalid();
}
}
12 changes: 10 additions & 2 deletions src/test/identity-manager/WorldIDIdentityManagerDataQuery.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {SemaphoreTreeDepthValidator} from "../../utils/SemaphoreTreeDepthValidat
import {SimpleVerify} from "../mock/SimpleVerifier.sol";
import {TypeConverter as TC} from "../utils/TypeConverter.sol";
import {VerifierLookupTable} from "../../data/VerifierLookupTable.sol";
import {VerifierLookupTable4844} from "../../data/VerifierLookupTable4844.sol";

import {WorldIDIdentityManagerImplV2 as ManagerImpl} from "../../WorldIDIdentityManagerImplV2.sol";
import {WorldIDIdentityManagerImplV1 as ManagerImplV1} from "../../WorldIDIdentityManagerImplV1.sol";
Expand All @@ -24,6 +25,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
treeDepth,
newPreRoot,
defaultInsertVerifiers,
defaultInsertVerifiers4844,
defaultDeletionVerifiers,
defaultUpdateVerifiers,
semaphoreVerifier
Expand All @@ -50,12 +52,14 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
(
VerifierLookupTable insertVerifiers,
VerifierLookupTable deletionVerifiers,
VerifierLookupTable updateVerifiers
VerifierLookupTable updateVerifiers,
VerifierLookupTable4844 insertVerifiers4844
) = makeVerifierLookupTables(TC.makeDynArray([identities.length]));
makeNewIdentityManager(
treeDepth,
newPreRoot,
insertVerifiers,
insertVerifiers4844,
deletionVerifiers,
updateVerifiers,
semaphoreVerifier
Expand Down Expand Up @@ -91,12 +95,14 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
(
VerifierLookupTable insertVerifiers,
VerifierLookupTable deletionVerifiers,
VerifierLookupTable updateVerifiers
VerifierLookupTable updateVerifiers,
VerifierLookupTable4844 insertVerifiers4844
) = makeVerifierLookupTables(TC.makeDynArray([identities.length]));
makeNewIdentityManager(
treeDepth,
newPreRoot,
insertVerifiers,
insertVerifiers4844,
deletionVerifiers,
updateVerifiers,
semaphoreVerifier
Expand Down Expand Up @@ -150,6 +156,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
treeDepth,
actualRoot,
defaultInsertVerifiers,
defaultInsertVerifiers4844,
defaultDeletionVerifiers,
defaultUpdateVerifiers,
semaphoreVerifier
Expand Down Expand Up @@ -178,6 +185,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
actualTreeDepth,
insertionPreRoot,
defaultInsertVerifiers,
defaultInsertVerifiers4844,
defaultDeletionVerifiers,
defaultUpdateVerifiers,
semaphoreVerifier
Expand Down
Loading

0 comments on commit cbe167d

Please sign in to comment.