Skip to content

Commit

Permalink
WIP: try to split ITreeVerifier
Browse files Browse the repository at this point in the history
Compilation fails:

Error:
Compiler run failed:
Error: Compiler error (/solidity/libsolidity/codegen/LValue.cpp:55):Stack too deep. Try compiling with `--via-ir` (cli) or the equivalent `viaIR: true` (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.
CompilerError: Stack too deep. Try compiling with `--via-ir` (cli) or the equivalent `viaIR: true` (standard JSON) while enabling the optimizer. Otherwise, try removing local variables.
   --> src/test/identity-manager/WorldIDIdentityManagerIdentityRegistration.t.sol:167:40:
    |
167 |             (actualProof, newPostRoot, newStartIndex, secondIdents, secondPostRoot)
    |                                        ^^^^^^^^^^^^^

make: *** [test] Error 1
  • Loading branch information
wzmuda committed Sep 6, 2024
1 parent f8bb6d0 commit 440e522
Show file tree
Hide file tree
Showing 19 changed files with 424 additions and 118 deletions.
8 changes: 5 additions & 3 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/ITreeVerifierPedersen.sol";
import {VerifierLookupTablePedersen} from "./data/VerifierLookupTablePedersen.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;
VerifierLookupTablePedersen 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(VerifierLookupTablePedersen _batchInsertion4844Verifiers) public reinitializer(3) {
if (address(_batchInsertion4844Verifiers) == address(0)) {
revert InvalidVerifierLUT();
}
Expand Down Expand Up @@ -144,7 +146,7 @@ contract WorldIDIdentityManagerImplV3 is WorldIDIdentityManagerImplV2 {
}

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

bytes32 kzgCommitmentHash = blobhash(0);
Expand Down
177 changes: 177 additions & 0 deletions src/data/VerifierLookupTablePedersen.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 {ITreeVerifierPedersen} from "../interfaces/ITreeVerifierPedersen.sol";

/// @title Batch Lookup Table for proofs with Pedersen commitments.
/// @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 VerifierLookupTablePedersen is Ownable2Step {
////////////////////////////////////////////////////////////////////////////////
/// DATA ///
////////////////////////////////////////////////////////////////////////////////

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

/// The null verifiers.
ITreeVerifierPedersen internal constant nullVerifier = ITreeVerifierPedersen(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 => ITreeVerifierPedersen) 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 (ITreeVerifierPedersen 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, ITreeVerifierPedersen 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, ITreeVerifierPedersen verifier)
public
onlyOwner
returns (ITreeVerifierPedersen 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 (ITreeVerifierPedersen oldVerifier)
{
oldVerifier = updateVerifier(batchSize, ITreeVerifierPedersen(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/ITreeVerifierPedersen.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 proofs for which Pedersen commitments exist.
interface ITreeVerifierPedersen {
/// 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 {ITreeVerifierPedersen} from "src/interfaces/ITreeVerifierPedersen.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 ITreeVerifierPedersen {

/// 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 {VerifierLookupTablePedersen} from "../../data/VerifierLookupTablePedersen.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,
defaultInsertVerifiersPedersen,
defaultDeletionVerifiers,
defaultUpdateVerifiers,
semaphoreVerifier
Expand All @@ -50,12 +52,14 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
(
VerifierLookupTable insertVerifiers,
VerifierLookupTable deletionVerifiers,
VerifierLookupTable updateVerifiers
VerifierLookupTable updateVerifiers,
VerifierLookupTablePedersen insertVerifiersPedersen
) = makeVerifierLookupTables(TC.makeDynArray([identities.length]));
makeNewIdentityManager(
treeDepth,
newPreRoot,
insertVerifiers,
insertVerifiersPedersen,
deletionVerifiers,
updateVerifiers,
semaphoreVerifier
Expand Down Expand Up @@ -91,12 +95,14 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
(
VerifierLookupTable insertVerifiers,
VerifierLookupTable deletionVerifiers,
VerifierLookupTable updateVerifiers
VerifierLookupTable updateVerifiers,
VerifierLookupTablePedersen insertVerifiersPedersen
) = makeVerifierLookupTables(TC.makeDynArray([identities.length]));
makeNewIdentityManager(
treeDepth,
newPreRoot,
insertVerifiers,
insertVerifiersPedersen,
deletionVerifiers,
updateVerifiers,
semaphoreVerifier
Expand Down Expand Up @@ -150,6 +156,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
treeDepth,
actualRoot,
defaultInsertVerifiers,
defaultInsertVerifiersPedersen,
defaultDeletionVerifiers,
defaultUpdateVerifiers,
semaphoreVerifier
Expand Down Expand Up @@ -178,6 +185,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest {
actualTreeDepth,
insertionPreRoot,
defaultInsertVerifiers,
defaultInsertVerifiersPedersen,
defaultDeletionVerifiers,
defaultUpdateVerifiers,
semaphoreVerifier
Expand Down
Loading

0 comments on commit 440e522

Please sign in to comment.