From 8f40fc8e48ecfcd31d74b25826343e953dd670f2 Mon Sep 17 00:00:00 2001 From: "dcbuilder.eth" Date: Tue, 5 Sep 2023 18:44:18 +0100 Subject: [PATCH] add deletion circuit tests failing atm --- src/test/data/TestDeletionParams.json | 63 ++++ ...stParams.json => TestInsertionParams.json} | 0 .../WorldIDIdentityManagerCalculation.t.sol | 47 ++- .../WorldIDIdentityManagerDataQuery.t.sol | 4 +- ...rldIDIdentityManagerIdentityDeletion.t.sol | 151 ++++---- ...DIdentityManagerIdentityRegistration.t.sol | 71 ++-- ...WorldIDIdentityManagerIdentityUpdate.t.sol | 18 +- ...IDIdentityManagerOwnershipManagement.t.sol | 2 +- ...IdentityManagerSemaphoreVerification.t.sol | 8 +- .../WorldIDIdentityManagerTest.sol | 44 ++- .../WorldIDIdentityManagerUninit.t.sol | 15 +- src/test/mock/DeletionTreeVerifier.sol | 334 ++++++++++++++++++ ...Verifier.sol => InsertionTreeVerifier.sol} | 0 13 files changed, 624 insertions(+), 133 deletions(-) create mode 100644 src/test/data/TestDeletionParams.json rename src/test/data/{TestParams.json => TestInsertionParams.json} (100%) create mode 100644 src/test/mock/DeletionTreeVerifier.sol rename src/test/mock/{TreeVerifier.sol => InsertionTreeVerifier.sol} (100%) diff --git a/src/test/data/TestDeletionParams.json b/src/test/data/TestDeletionParams.json new file mode 100644 index 0000000..569e3a3 --- /dev/null +++ b/src/test/data/TestDeletionParams.json @@ -0,0 +1,63 @@ +{ + "inputHash": "0xfe7bd6158c7603ed86cef4dbe90a417fe7c16e94a730ae75ff0135837c6f4dd1", + "deletionIndices": [0, 2, 4], + "preRoot": "0x218676b10b4d8c25fce789f3b13f2b3e49497ce0b20f57bacd7dfda85c0b6ac2", + "postRoot": "0x7c453712267d1cca763c6da89bb632bd85bf9d8b48ef71bd0b7595f81357edb", + "identityCommitments": ["0x1", "0x3", "0x5"], + "merkleProofs": [ + [ + "0x2", + "0x20a3af0435914ccd84b806164531b0cd36e37d4efb93efab76913a93e1f30996", + "0x176cf35331147314efef56ab615fe64b748584a01d362fa17297672192d5ecd", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747", + "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2", + "0x1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636", + "0x2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a", + "0x14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0", + "0x190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c", + "0x22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92" + ], + [ + "0x4", + "0x65e2c6cc08a36c4a943286bc91c216054a1981eb4f7570f67394ef8937a21b8", + "0x176cf35331147314efef56ab615fe64b748584a01d362fa17297672192d5ecd", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747", + "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2", + "0x1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636", + "0x2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a", + "0x14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0", + "0x190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c", + "0x22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92" + ], + [ + "0x6", + "0x2098f5fb9e239eab3ceac3f27b81e481dc3124d55ffed523a839ee8446b64864", + "0x1ebadf14eecbfe79f7ac75d3b6c688b8630fb675fcf24ab20e2a08381998266f", + "0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238", + "0x7f9d837cb17b0d36320ffe93ba52345f1b728571a568265caac97559dbc952a", + "0x2b94cf5e8746b3f5c9631f4c5df32907a699c58c94b2ad4d7b5cec1639183f55", + "0x2dee93c5a666459646ea7d22cca9e1bcfed71e6951b953611d11dda32ea09d78", + "0x78295e5a22b84e982cf601eb639597b8b0515a88cb5ac7fa8a4aabe3c87349d", + "0x2fa5e5f18f6027a6501bec864564472a616b2e274a41211a444cbe3a99f3cc61", + "0xe884376d0d8fd21ecb780389e941f66e45e7acce3e228ab3e2156a614fcd747", + "0x1b7201da72494f1e28717ad1a52eb469f95892f957713533de6175e5da190af2", + "0x1f8d8822725e36385200c0b201249819a6e6e1e4650808b5bebc6bface7d7636", + "0x2c5d82f66c914bafb9701589ba8cfcfb6162b0a12acf88a8d0879a0471b5f85a", + "0x14c54148a0940bb820957f5adf3fa1134ef5c4aaa113f4646458f270e0bfbfd0", + "0x190d33b12f986f961e10c0ee44d8b9af11be25588cad89d416118e4bf4ebe80c", + "0x22f98aa9ce704152ac17354914ad73ed1167ae6596af510aa5b3649325e06c92" + ] + ] +} diff --git a/src/test/data/TestParams.json b/src/test/data/TestInsertionParams.json similarity index 100% rename from src/test/data/TestParams.json rename to src/test/data/TestInsertionParams.json diff --git a/src/test/identity-manager/WorldIDIdentityManagerCalculation.t.sol b/src/test/identity-manager/WorldIDIdentityManagerCalculation.t.sol index af11697..597e53e 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerCalculation.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerCalculation.t.sol @@ -18,9 +18,9 @@ contract WorldIDIdentityManagerCalculation is WorldIDIdentityManagerTest { // Setup bytes memory callData = abi.encodeCall( ManagerImplV1.calculateIdentityRegistrationInputHash, - (startIndex, preRoot, postRoot, identityCommitments) + (startIndex, insertionPreRoot, insertionPostRoot, identityCommitments) ); - bytes memory returnData = abi.encode(inputHash); + bytes memory returnData = abi.encode(insertionInputHash); // Test assertCallSucceedsOn(identityManagerAddress, callData, returnData); @@ -33,14 +33,39 @@ contract WorldIDIdentityManagerCalculation is WorldIDIdentityManagerTest { // Test managerImpl.calculateIdentityRegistrationInputHash( - startIndex, preRoot, postRoot, identityCommitments + startIndex, insertionPreRoot, insertionPostRoot, identityCommitments + ); + } + + /// @notice Tests whether it is possible to correctly calculate the `inputHash` to the merkle + /// tree verifier. + function testCalculateIdentityDeletionInputHashFromParametersOnKnownInput() public { + // Setup + bytes memory callData = abi.encodeCall( + ManagerImpl.calculateIdentityDeletionInputHash, + (deletionIndices, insertionPreRoot, insertionPostRoot) + ); + bytes memory returnData = abi.encode(deletionInputHash); + + // Test + assertCallSucceedsOn(identityManagerAddress, callData, returnData); + } + + /// @notice Checks that the input hash can only be calculated if behind the proxy. + function testCannotCalculateIdentityDeletionInputHashIfNotViaProxy() public { + // Setup + vm.expectRevert("Function must be called through delegatecall"); + + // Test + managerImpl.calculateIdentityDeletionInputHash( + deletionIndices, insertionPreRoot, insertionPostRoot ); } /// @notice Check whether it's possible to caculate the identity update input hash. function testCanCalculateIdentityUpdateInputHash( - uint256 preRoot, - uint256 postRoot, + uint256 insertionPreRoot, + uint256 insertionPostRoot, uint32 startIndex1, uint32 startIndex2, uint256 oldIdent1, @@ -63,8 +88,8 @@ contract WorldIDIdentityManagerCalculation is WorldIDIdentityManagerTest { bytes32 expectedResult = keccak256( abi.encodePacked( - preRoot, - postRoot, + insertionPreRoot, + insertionPostRoot, uint256(startIndex1), uint256(startIndex2), oldIdent1, @@ -75,7 +100,7 @@ contract WorldIDIdentityManagerCalculation is WorldIDIdentityManagerTest { ); bytes memory callData = abi.encodeCall( ManagerImplV1.calculateIdentityUpdateInputHash, - (preRoot, postRoot, leafIndices, oldIdents, newIdents) + (insertionPreRoot, insertionPostRoot, leafIndices, oldIdents, newIdents) ); bytes memory expectedReturn = abi.encode(expectedResult); @@ -86,8 +111,8 @@ contract WorldIDIdentityManagerCalculation is WorldIDIdentityManagerTest { /// @notice Ensures that the identity update hash can only be calculated when called via the /// proxy. function testCannotCalculateIdentityUpdateHashIfNotViaProxy( - uint256 preRoot, - uint256 postRoot, + uint256 insertionPreRoot, + uint256 insertionPostRoot, uint32[] memory leafIndices, uint256[] memory oldIdents, uint256[] memory newIdents @@ -97,7 +122,7 @@ contract WorldIDIdentityManagerCalculation is WorldIDIdentityManagerTest { // Test managerImpl.calculateIdentityUpdateInputHash( - preRoot, postRoot, leafIndices, oldIdents, newIdents + insertionPreRoot, insertionPostRoot, leafIndices, oldIdents, newIdents ); } } diff --git a/src/test/identity-manager/WorldIDIdentityManagerDataQuery.t.sol b/src/test/identity-manager/WorldIDIdentityManagerDataQuery.t.sol index d3d261d..2df1cb1 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerDataQuery.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerDataQuery.t.sol @@ -113,7 +113,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest { bytes memory queryCallData = abi.encodeCall(ManagerImplV1.queryRoot, (newPreRoot)); bytes memory returnData = abi.encode(ManagerImplV1.RootInfo(newPreRoot, uint128(originalTimestamp), false)); - vm.warp(originalTimestamp + 2 hours); // Force preRoot to expire + vm.warp(originalTimestamp + 2 hours); // Force insertionPreRoot to expire // Test assertCallSucceedsOn(identityManagerAddress, queryCallData, returnData); @@ -176,7 +176,7 @@ contract WorldIDIdentityManagerDataQuery is WorldIDIdentityManagerTest { vm.assume(SemaphoreTreeDepthValidator.validate(actualTreeDepth)); makeNewIdentityManager( actualTreeDepth, - preRoot, + insertionPreRoot, defaultInsertVerifiers, defaultDeletionVerifiers, defaultUpdateVerifiers, diff --git a/src/test/identity-manager/WorldIDIdentityManagerIdentityDeletion.t.sol b/src/test/identity-manager/WorldIDIdentityManagerIdentityDeletion.t.sol index 0faf21f..150fcdf 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerIdentityDeletion.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerIdentityDeletion.t.sol @@ -6,7 +6,7 @@ import {WorldIDIdentityManagerTest} from "./WorldIDIdentityManagerTest.sol"; import {ITreeVerifier} from "../../interfaces/ITreeVerifier.sol"; import {SimpleVerifier, SimpleVerify} from "../mock/SimpleVerifier.sol"; import {TypeConverter as TC} from "../utils/TypeConverter.sol"; -import {Verifier as TreeVerifier} from "../mock/TreeVerifier.sol"; +import {Verifier as TreeVerifier} from "../mock/DeletionTreeVerifier.sol"; import {VerifierLookupTable} from "../../data/VerifierLookupTable.sol"; import {WorldIDIdentityManager as IdentityManager} from "../../WorldIDIdentityManager.sol"; @@ -24,37 +24,49 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { /// Taken from WorldIDIdentityManagerImplV1.sol event TreeChanged( - uint256 indexed preRoot, ManagerImpl.TreeChange indexed kind, uint256 indexed postRoot + uint256 indexed deletionPreRoot, + ManagerImpl.TreeChange indexed kind, + uint256 indexed deletionPostRoot ); - // /// @notice Checks that the proof validates properly with the correct inputs. - // function testDeleteIdentitiesWithCorrectInputsFromKnown() public { - // // Setup - // ITreeVerifier actualVerifier = new TreeVerifier(); - // (VerifierLookupTable insertVerifiers, VerifierLookupTable deletionVerifiers, VerifierLookupTable updateVerifiers) = - // makeVerifierLookupTables(TC.makeDynArray([40])); - // deletionVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); - // makeNewIdentityManager( - // treeDepth, preRoot, insertVerifiers, deletionVerifiers, updateVerifiers, semaphoreVerifier - // ); - // bytes memory deleteCallData = abi.encodeCall( - // ManagerImpl.deleteIdentities, - // (proof, preRoot, deletionIndices, postRoot) - // ); - // bytes memory latestRootCallData = abi.encodeCall(ManagerImplV1.latestRoot, ()); - // bytes memory queryRootCallData = abi.encodeCall(ManagerImplV1.queryRoot, (postRoot)); - - // // Test - // assertCallSucceedsOn(identityManagerAddress, deleteCallData); - // assertCallSucceedsOn(identityManagerAddress, latestRootCallData, abi.encode(postRoot)); - // assertCallSucceedsOn( - // identityManagerAddress, - // queryRootCallData, - // abi.encode(ManagerImplV1.RootInfo(postRoot, 0, true)) - // ); - // } - - /// @notice Checks that the proof validates properly with correct inputs. + /// @notice Checks that the deletionProof validates properly with the correct inputs. + function testDeleteIdentitiesWithCorrectInputsFromKnown() public { + // Setup + ITreeVerifier actualVerifier = new TreeVerifier(); + ( + VerifierLookupTable insertVerifiers, + VerifierLookupTable deletionVerifiers, + VerifierLookupTable updateVerifiers + ) = makeVerifierLookupTables(TC.makeDynArray([40])); + deletionVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); + makeNewIdentityManager( + treeDepth, + deletionPreRoot, + insertVerifiers, + deletionVerifiers, + updateVerifiers, + semaphoreVerifier + ); + bytes memory deleteCallData = abi.encodeCall( + ManagerImpl.deleteIdentities, + (deletionProof, deletionPreRoot, deletionIndices, deletionPostRoot) + ); + bytes memory latestRootCallData = abi.encodeCall(ManagerImplV1.latestRoot, ()); + bytes memory queryRootCallData = abi.encodeCall(ManagerImplV1.queryRoot, (deletionPostRoot)); + + // Test + assertCallSucceedsOn(identityManagerAddress, deleteCallData); + assertCallSucceedsOn( + identityManagerAddress, latestRootCallData, abi.encode(deletionPostRoot) + ); + assertCallSucceedsOn( + identityManagerAddress, + queryRootCallData, + abi.encode(ManagerImplV1.RootInfo(deletionPostRoot, 0, true)) + ); + } + + /// @notice Checks that the deletionProof validates properly with correct inputs. function testDeleteIdentitiesWithCorrectInputs( uint128[8] memory prf, uint128 newPreRoot, @@ -183,7 +195,7 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { assertCallFailsOn(identityManagerAddress, callData, errorData); } - /// @notice Checks that it reverts if the provided proof is incorrect for the public inputs. + /// @notice Checks that it reverts if the provided deletionProof is incorrect for the public inputs. function testCannotDeleteIdentitiesWithIncorrectInputs( uint128[8] memory prf, uint128 newPreRoot, @@ -217,37 +229,37 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { // Test assertCallFailsOn(identityManagerAddress, callData, expectedError); } - // - // - // /// @notice Checks that it reverts if the provided post root is incorrect. - // function testCannotRegisterIdentitiesIfPostRootIncorrect(uint256 newPostRoot) public { - // // Setup - // vm.assume(newPostRoot != postRoot && newPostRoot < SNARK_SCALAR_FIELD); - // managerImpl = new ManagerImpl(); - // managerImplAddress = address(managerImpl); - // ITreeVerifier actualVerifier = new TreeVerifier(); - // (VerifierLookupTable insertVerifiers, VerifierLookupTable deletionVerifiers, VerifierLookupTable updateVerifiers) = - // makeVerifierLookupTables(TC.makeDynArray([70])); - // insertVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); - // - // bytes memory callData = abi.encodeCall( - // ManagerImplV1.initialize, - // (treeDepth, preRoot, insertVerifiers, deletionVerifiers, updateVerifiers, semaphoreVerifier) - // ); - // - // identityManager = new IdentityManager(managerImplAddress, callData); - // identityManagerAddress = address(identityManager); - // bytes memory registerCallData = abi.encodeCall( - // ManagerImplV1.registerIdentities, - // (proof, preRoot, startIndex, identityCommitments, newPostRoot) - // ); - // bytes memory expectedError = - // abi.encodeWithSelector(ManagerImplV1.ProofValidationFailure.selector); - // - // // Test - // assertCallFailsOn(identityManagerAddress, registerCallData, expectedError); - // } - // + + /// @notice Checks that it reverts if the provided post root is incorrect. + function testCannotDeleteIdentitiesIfPostRootIncorrect(uint256 newPostRoot) public { + // Setup + vm.assume(newPostRoot != deletionPostRoot && newPostRoot < SNARK_SCALAR_FIELD); + ITreeVerifier actualVerifier = new TreeVerifier(); + ( + VerifierLookupTable insertVerifiers, + VerifierLookupTable deletionVerifiers, + VerifierLookupTable updateVerifiers + ) = makeVerifierLookupTables(TC.makeDynArray([40])); + deletionVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); + makeNewIdentityManager( + treeDepth, + deletionPreRoot, + insertVerifiers, + deletionVerifiers, + updateVerifiers, + semaphoreVerifier + ); + + bytes memory deletionCallData = abi.encodeCall( + ManagerImpl.deleteIdentities, + (deletionProof, deletionPreRoot, deletionIndices, newPostRoot) + ); + bytes memory expectedError = + abi.encodeWithSelector(ManagerImplV1.ProofValidationFailure.selector); + + // Test + assertCallFailsOn(identityManagerAddress, deletionCallData, expectedError); + } /// @notice Tests that it reverts if an attempt is made to delete identities as an address /// that is not the identity operator address. @@ -255,7 +267,8 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { // Setup vm.assume(nonOperator != address(this) && nonOperator != address(0x0)); bytes memory callData = abi.encodeCall( - ManagerImpl.deleteIdentities, (proof, preRoot, deletionIndices, postRoot) + ManagerImpl.deleteIdentities, + (deletionProof, deletionPreRoot, deletionIndices, deletionPostRoot) ); bytes memory errorData = abi.encodeWithSelector(ManagerImplV1.Unauthorized.selector, nonOperator); @@ -284,7 +297,8 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { semaphoreVerifier ); bytes memory callData = abi.encodeCall( - ManagerImpl.deleteIdentities, (proof, actualRoot, deletionIndices, postRoot) + ManagerImpl.deleteIdentities, + (deletionProof, actualRoot, deletionIndices, deletionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.NotLatestRoot.selector, actualRoot, uint256(currentPreRoot) @@ -300,7 +314,8 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { // Setup uint256 newPreRoot = SNARK_SCALAR_FIELD + i; bytes memory callData = abi.encodeCall( - ManagerImpl.deleteIdentities, (proof, newPreRoot, deletionIndices, postRoot) + ManagerImpl.deleteIdentities, + (deletionProof, newPreRoot, deletionIndices, deletionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.UnreducedElement.selector, @@ -312,13 +327,13 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { assertCallFailsOn(identityManagerAddress, callData, expectedError); } - /// @notice Tests that it reverts if an attempt is made to delete identities with a postRoot + /// @notice Tests that it reverts if an attempt is made to delete identities with a deletionPostRoot /// that is not in reduced form. function testCannotDeleteIdentitiesWithUnreducedPostRoot(uint128 i) public { // Setup uint256 newPostRoot = SNARK_SCALAR_FIELD + i; bytes memory callData = abi.encodeCall( - ManagerImpl.deleteIdentities, (proof, initialRoot, deletionIndices, newPostRoot) + ManagerImpl.deleteIdentities, (deletionProof, initialRoot, deletionIndices, newPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.UnreducedElement.selector, @@ -338,6 +353,6 @@ contract WorldIDIdentityManagerIdentityDeletion is WorldIDIdentityManagerTest { vm.prank(expectedOwner); // Test - managerImpl.deleteIdentities(proof, initialRoot, deletionIndices, postRoot); + managerImpl.deleteIdentities(deletionProof, initialRoot, deletionIndices, deletionPostRoot); } } diff --git a/src/test/identity-manager/WorldIDIdentityManagerIdentityRegistration.t.sol b/src/test/identity-manager/WorldIDIdentityManagerIdentityRegistration.t.sol index a179d53..679d769 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerIdentityRegistration.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerIdentityRegistration.t.sol @@ -8,7 +8,7 @@ import {WorldIDIdentityManagerTest} from "./WorldIDIdentityManagerTest.sol"; import {ITreeVerifier} from "../../interfaces/ITreeVerifier.sol"; import {SimpleVerifier, SimpleVerify} from "../mock/SimpleVerifier.sol"; import {TypeConverter as TC} from "../utils/TypeConverter.sol"; -import {Verifier as TreeVerifier} from "../mock/TreeVerifier.sol"; +import {Verifier as TreeVerifier} from "../mock/InsertionTreeVerifier.sol"; import {VerifierLookupTable} from "../../data/VerifierLookupTable.sol"; import {WorldIDIdentityManager as IdentityManager} from "../../WorldIDIdentityManager.sol"; @@ -26,7 +26,9 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes /// Taken from WorldIDIdentityManagerImplV1.sol event TreeChanged( - uint256 indexed preRoot, ManagerImpl.TreeChange indexed kind, uint256 indexed postRoot + uint256 indexed insertionPreRoot, + ManagerImpl.TreeChange indexed kind, + uint256 indexed insertionPostRoot ); /// @notice Checks that the proof validates properly with the correct inputs. @@ -41,7 +43,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes insertVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); makeNewIdentityManager( treeDepth, - preRoot, + insertionPreRoot, insertVerifiers, deletionVerifiers, updateVerifiers, @@ -49,18 +51,21 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes ); bytes memory registerCallData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, preRoot, startIndex, identityCommitments, postRoot) + (insertionProof, insertionPreRoot, startIndex, identityCommitments, insertionPostRoot) ); bytes memory latestRootCallData = abi.encodeCall(ManagerImplV1.latestRoot, ()); - bytes memory queryRootCallData = abi.encodeCall(ManagerImplV1.queryRoot, (postRoot)); + bytes memory queryRootCallData = + abi.encodeCall(ManagerImplV1.queryRoot, (insertionPostRoot)); // Test assertCallSucceedsOn(identityManagerAddress, registerCallData); - assertCallSucceedsOn(identityManagerAddress, latestRootCallData, abi.encode(postRoot)); + assertCallSucceedsOn( + identityManagerAddress, latestRootCallData, abi.encode(insertionPostRoot) + ); assertCallSucceedsOn( identityManagerAddress, queryRootCallData, - abi.encode(ManagerImplV1.RootInfo(postRoot, 0, true)) + abi.encode(ManagerImplV1.RootInfo(insertionPostRoot, 0, true)) ); } @@ -253,7 +258,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes insertVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); makeNewIdentityManager( treeDepth, - preRoot, + insertionPreRoot, insertVerifiers, deletionVerifiers, updateVerifiers, @@ -261,7 +266,13 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes ); bytes memory registerCallData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, preRoot, newStartIndex, identityCommitments, postRoot) + ( + insertionProof, + insertionPreRoot, + newStartIndex, + identityCommitments, + insertionPostRoot + ) ); bytes memory expectedError = abi.encodeWithSelector(ManagerImplV1.ProofValidationFailure.selector); @@ -289,14 +300,15 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes insertVerifiers.addVerifier(identityCommitmentsSize, actualVerifier); makeNewIdentityManager( treeDepth, - preRoot, + insertionPreRoot, insertVerifiers, deletionVerifiers, updateVerifiers, semaphoreVerifier ); bytes memory registerCallData = abi.encodeCall( - ManagerImplV1.registerIdentities, (proof, preRoot, startIndex, identities, postRoot) + ManagerImplV1.registerIdentities, + (insertionProof, insertionPreRoot, startIndex, identities, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector(ManagerImplV1.ProofValidationFailure.selector); @@ -308,7 +320,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes /// @notice Checks that it reverts if the provided post root is incorrect. function testCannotRegisterIdentitiesIfPostRootIncorrect(uint256 newPostRoot) public { // Setup - vm.assume(newPostRoot != postRoot && newPostRoot < SNARK_SCALAR_FIELD); + vm.assume(newPostRoot != insertionPostRoot && newPostRoot < SNARK_SCALAR_FIELD); managerImpl = new ManagerImpl(); managerImplAddress = address(managerImpl); ITreeVerifier actualVerifier = new TreeVerifier(); @@ -321,7 +333,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes bytes memory callData = abi.encodeCall( ManagerImplV1.initialize, - (treeDepth, preRoot, insertVerifiers, updateVerifiers, semaphoreVerifier) + (treeDepth, insertionPreRoot, insertVerifiers, updateVerifiers, semaphoreVerifier) ); identityManager = new IdentityManager(managerImplAddress, callData); @@ -336,7 +348,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes bytes memory registerCallData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, preRoot, startIndex, identityCommitments, newPostRoot) + (insertionProof, insertionPreRoot, startIndex, identityCommitments, newPostRoot) ); bytes memory expectedError = abi.encodeWithSelector(ManagerImplV1.ProofValidationFailure.selector); @@ -352,7 +364,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes vm.assume(nonOperator != address(this) && nonOperator != address(0x0)); bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, preRoot, startIndex, identityCommitments, postRoot) + (insertionProof, insertionPreRoot, startIndex, identityCommitments, insertionPostRoot) ); bytes memory errorData = abi.encodeWithSelector(ManagerImplV1.Unauthorized.selector, nonOperator); @@ -383,7 +395,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes ); bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, actualRoot, startIndex, identityCommitments, postRoot) + (insertionProof, actualRoot, startIndex, identityCommitments, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.NotLatestRoot.selector, actualRoot, uint256(currentPreRoot) @@ -411,7 +423,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, initialRoot, startIndex, invalidCommitments, postRoot) + (insertionProof, initialRoot, startIndex, invalidCommitments, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.InvalidCommitment.selector, uint256(invalidPosition + 1) @@ -453,7 +465,13 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - ([uint256(2), 1, 3, 4, 5, 6, 7, 9], initialRoot, startIndex, identities, postRoot) + ( + [uint256(2), 1, 3, 4, 5, 6, 7, 9], + initialRoot, + startIndex, + identities, + insertionPostRoot + ) ); // Test @@ -469,7 +487,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes unreducedCommitments[position] = SNARK_SCALAR_FIELD + i; bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, initialRoot, startIndex, unreducedCommitments, postRoot) + (insertionProof, initialRoot, startIndex, unreducedCommitments, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.UnreducedElement.selector, @@ -488,7 +506,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes uint256 newPreRoot = SNARK_SCALAR_FIELD + i; bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, newPreRoot, startIndex, identityCommitments, postRoot) + (insertionProof, newPreRoot, startIndex, identityCommitments, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.UnreducedElement.selector, @@ -500,14 +518,14 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes assertCallFailsOn(identityManagerAddress, callData, expectedError); } - /// @notice Tests that it reverts if an attempt is made to register identities with a postRoot + /// @notice Tests that it reverts if an attempt is made to register identities with a insertionPostRoot /// that is not in reduced form. function testCannotRegisterIdentitiesWithUnreducedPostRoot(uint128 i) public { // Setup uint256 newPostRoot = SNARK_SCALAR_FIELD + i; bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, initialRoot, startIndex, identityCommitments, newPostRoot) + (insertionProof, initialRoot, startIndex, identityCommitments, newPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImplV1.UnreducedElement.selector, @@ -528,7 +546,12 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes bytes4 functionSelector = ManagerImplV1.registerIdentities.selector; // Have to encode with selector as otherwise it's typechecked. bytes memory callData = abi.encodeWithSelector( - functionSelector, proof, preRoot, i, identityCommitments, postRoot + functionSelector, + insertionProof, + insertionPreRoot, + i, + identityCommitments, + insertionPostRoot ); // Test @@ -544,7 +567,7 @@ contract WorldIDIdentityManagerIdentityRegistration is WorldIDIdentityManagerTes // Test managerImpl.registerIdentities( - proof, initialRoot, startIndex, identityCommitments, postRoot + insertionProof, initialRoot, startIndex, identityCommitments, insertionPostRoot ); } } diff --git a/src/test/identity-manager/WorldIDIdentityManagerIdentityUpdate.t.sol b/src/test/identity-manager/WorldIDIdentityManagerIdentityUpdate.t.sol index 66b78e7..0f03644 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerIdentityUpdate.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerIdentityUpdate.t.sol @@ -6,7 +6,7 @@ import {WorldIDIdentityManagerTest} from "./WorldIDIdentityManagerTest.sol"; import {ITreeVerifier} from "../../interfaces/ITreeVerifier.sol"; import {SimpleVerifier, SimpleVerify} from "../mock/SimpleVerifier.sol"; import {TypeConverter as TC} from "../utils/TypeConverter.sol"; -import {Verifier as TreeVerifier} from "../mock/TreeVerifier.sol"; +import {Verifier as TreeVerifier} from "../mock/InsertionTreeVerifier.sol"; import {VerifierLookupTable} from "../../data/VerifierLookupTable.sol"; import {WorldIDIdentityManager as IdentityManager} from "../../WorldIDIdentityManager.sol"; @@ -23,7 +23,9 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { /// Taken from WorldIDIdentityManagerImplV1.sol event TreeChanged( - uint256 indexed preRoot, ManagerImpl.TreeChange indexed kind, uint256 indexed postRoot + uint256 indexed insertionPreRoot, + ManagerImpl.TreeChange indexed kind, + uint256 indexed insertionPostRoot ); /// @notice Checks that the proof validates properly with correct inputs. @@ -283,7 +285,7 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { ) = prepareUpdateIdentitiesTestCase(identities, prf); bytes memory callData = abi.encodeCall( ManagerImpl.updateIdentities, - (actualProof, preRoot, leafIndices, oldIdents, newIdents, postRoot) + (actualProof, insertionPreRoot, leafIndices, oldIdents, newIdents, insertionPostRoot) ); bytes memory errorData = abi.encodeWithSelector(ManagerImpl.Unauthorized.selector, nonOperator); @@ -328,7 +330,7 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { ); bytes memory callData = abi.encodeCall( ManagerImpl.updateIdentities, - (actualProof, actualRoot, leafIndices, oldIdents, newIdents, postRoot) + (actualProof, actualRoot, leafIndices, oldIdents, newIdents, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImpl.NotLatestRoot.selector, actualRoot, uint256(currentPreRoot) @@ -392,7 +394,7 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { ) internal { bytes memory callData = abi.encodeCall( ManagerImpl.updateIdentities, - (actualProof, newPreRoot, leafIndices, oldIdents, newIdents, postRoot) + (actualProof, newPreRoot, leafIndices, oldIdents, newIdents, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImpl.UnreducedElement.selector, @@ -421,7 +423,7 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { ) = prepareUpdateIdentitiesTestCase(identities, prf); bytes memory callData = abi.encodeCall( ManagerImpl.updateIdentities, - (actualProof, newPreRoot, leafIndices, oldIdents, newIdents, postRoot) + (actualProof, newPreRoot, leafIndices, oldIdents, newIdents, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector( ManagerImpl.UnreducedElement.selector, @@ -433,7 +435,7 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { assertCallFailsOn(identityManagerAddress, callData, expectedError); } - /// @notice Tests that it reverts if an attempt is made to update identities with a postRoot + /// @notice Tests that it reverts if an attempt is made to update identities with a insertionPostRoot /// that is not in reduced form. function testCannotUpdateIdentitiesWithUnreducedPostRoot( uint128 i, @@ -480,7 +482,7 @@ contract WorldIDIdentityManagerIdentityUpdate is WorldIDIdentityManagerTest { // Test managerImpl.updateIdentities( - actualProof, initialRoot, leafIndices, oldIdents, newIdents, postRoot + actualProof, initialRoot, leafIndices, oldIdents, newIdents, insertionPostRoot ); } } diff --git a/src/test/identity-manager/WorldIDIdentityManagerOwnershipManagement.t.sol b/src/test/identity-manager/WorldIDIdentityManagerOwnershipManagement.t.sol index 1e77267..04e1557 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerOwnershipManagement.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerOwnershipManagement.t.sol @@ -11,7 +11,7 @@ import {Ownable2StepUpgradeable} from "contracts-upgradeable/access/Ownable2Step import {SemaphoreVerifier} from "semaphore/base/SemaphoreVerifier.sol"; import {SimpleVerifier, SimpleVerify} from "../mock/SimpleVerifier.sol"; import {UUPSUpgradeable} from "contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import {Verifier as TreeVerifier} from "../mock/TreeVerifier.sol"; +import {Verifier as TreeVerifier} from "../mock/InsertionTreeVerifier.sol"; import {WorldIDIdentityManagerImplMock} from "../mock/WorldIDIdentityManagerImplMock.sol"; import {WorldIDImpl} from "../../abstract/WorldIDImpl.sol"; diff --git a/src/test/identity-manager/WorldIDIdentityManagerSemaphoreVerification.t.sol b/src/test/identity-manager/WorldIDIdentityManagerSemaphoreVerification.t.sol index 1f3ef18..83977ea 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerSemaphoreVerification.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerSemaphoreVerification.t.sol @@ -31,7 +31,7 @@ contract WorldIDIdentityManagerSemaphoreValidation is WorldIDIdentityManagerTest vm.assume(prf[0] != 0); makeNewIdentityManager( actualTreeDepth, - preRoot, + insertionPreRoot, defaultInsertVerifiers, defaultDeletionVerifiers, defaultUpdateVerifiers, @@ -39,7 +39,7 @@ contract WorldIDIdentityManagerSemaphoreValidation is WorldIDIdentityManagerTest ); bytes memory verifyProofCallData = abi.encodeCall( ManagerImplV1.verifyProof, - (preRoot, nullifierHash, signalHash, externalNullifierHash, proof) + (insertionPreRoot, nullifierHash, signalHash, externalNullifierHash, insertionProof) ); // Test @@ -60,7 +60,7 @@ contract WorldIDIdentityManagerSemaphoreValidation is WorldIDIdentityManagerTest vm.assume(prf[0] % 2 == 0); makeNewIdentityManager( actualTreeDepth, - preRoot, + insertionPreRoot, defaultInsertVerifiers, defaultDeletionVerifiers, defaultUpdateVerifiers, @@ -68,7 +68,7 @@ contract WorldIDIdentityManagerSemaphoreValidation is WorldIDIdentityManagerTest ); bytes memory verifyProofCallData = abi.encodeCall( ManagerImplV1.verifyProof, - (preRoot, nullifierHash, signalHash, externalNullifierHash, prf) + (insertionPreRoot, nullifierHash, signalHash, externalNullifierHash, prf) ); vm.expectRevert("Semaphore__InvalidProof()"); diff --git a/src/test/identity-manager/WorldIDIdentityManagerTest.sol b/src/test/identity-manager/WorldIDIdentityManagerTest.sol index 865d5d3..cd77fc3 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerTest.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerTest.sol @@ -47,20 +47,36 @@ contract WorldIDIdentityManagerTest is WorldIDTest { uint256 internal slotCounter = 0; - // All hardcoded test data taken from `src/test/data/TestParams.json`. This will be dynamically + /////////////////////////////////////////////////////////////////// + /// INSERTION /// + /////////////////////////////////////////////////////////////////// + // All hardcoded test data taken from `src/test/data/TestInsertionParams.json`. This will be dynamically // generated at some point in the future. - bytes32 internal constant inputHash = + bytes32 internal constant insertionInputHash = 0x7d7f77c56064e1f8577de14bba99eff85599ab0e76d0caeadd1ad61674b8a9c3; uint32 internal constant startIndex = 0; - uint256 internal constant preRoot = + uint256 internal constant insertionPreRoot = 0x18f43331537ee2af2e3d758d50f72106467c6eea50371dd528d57eb2b856d238; - uint256 internal constant postRoot = + uint256 internal constant insertionPostRoot = 0x5c1e52b41a571293b30efacd2afdb7173b20cfaf1f646c4ac9f96eb75848270; + uint256[] identityCommitments; uint256 identityCommitmentsSize = 3; - uint256[8] proof; + uint256[8] insertionProof; - uint32[] deletionIndices = [0, 1, 2]; + /////////////////////////////////////////////////////////////////// + /// DELETION /// + /////////////////////////////////////////////////////////////////// + // All hardcoded test data taken from `src/test/data/TestDeletionParams.json`. This will be dynamically + // generated at some point in the future. + bytes32 internal constant deletionInputHash = + 0xfe7bd6158c7603ed86cef4dbe90a417fe7c16e94a730ae75ff0135837c6f4dd1; + uint256 internal constant deletionPreRoot = + 0x218676b10b4d8c25fce789f3b13f2b3e49497ce0b20f57bacd7dfda85c0b6ac2; + uint256 internal constant deletionPostRoot = + 0x7c453712267d1cca763c6da89bb632bd85bf9d8b48ef71bd0b7595f81357edb; + uint32[] deletionIndices = [0, 2, 4]; + uint256[8] deletionProof; // Needed for testing things. uint256 internal constant SNARK_SCALAR_FIELD = @@ -87,8 +103,8 @@ contract WorldIDIdentityManagerTest is WorldIDTest { identityCommitments[1] = 0x2; identityCommitments[2] = 0x3; - // Create the proof term. - proof = [ + // Create the insertion proof term. + insertionProof = [ 0x2a45bf326884bbf13c821a5e4f30690a391156cccf80a2922fb24250111dd7eb, 0x23a7376a159513e6d0e22d43fcdca9d0c8a5c54a73b59fce6962a41e71355894, 0x21b9fc7c2d1f76c2e1a972b00f18728a57a34d7e4ae040811bf1626132ff3658, @@ -98,6 +114,18 @@ contract WorldIDIdentityManagerTest is WorldIDTest { 0x23115ff1573808639f19724479b195b7894a45c9868242ad2a416767359c6c78, 0x23f3fa30273c7f38e360496e7f9790450096d4a9592e1fe6e0a996cb05b8fb28 ]; + + // Create the deletion proof term. + deletionProof = [ + 0x10145dce25fb4a9a1e4e305873c2a7ac91075da0db580fb1f6eeffa33ef52f5, + 0x192814271941d11d6185e154da26f194e07472704a0f94ec7bffc4fc1e3bbb40, + 0x3bfad23cb9da38fb86524c50c6dc69e3439ee56037ed559a7cf5851326d5922, + 0x2ea282b1ac2aa9faf003c7346d294cf77b78027db61a6165e5c461ac9fcc7e0c, + 0x2fdf35f34b7f3b97ce8bdf2a0641c25cb07cb67350ef9757b43a0b7778a73a5d, + 0xf2f797f11e59fe3d034777f97378f7d5f7702474b545e52c01db129f9555425, + 0x19f3b8fa4f138d70da5b0afea373f2eff69c58377f15c089062a463d3dfa6c65, + 0x2c53aeeaf305844fad88b917bf7fffbf5d57a384b6d959a957cf31fe8eb3779f + ]; } /// @notice This function runs before every single test. diff --git a/src/test/identity-manager/WorldIDIdentityManagerUninit.t.sol b/src/test/identity-manager/WorldIDIdentityManagerUninit.t.sol index d833efe..2eeda19 100644 --- a/src/test/identity-manager/WorldIDIdentityManagerUninit.t.sol +++ b/src/test/identity-manager/WorldIDIdentityManagerUninit.t.sol @@ -8,7 +8,7 @@ import {ITreeVerifier} from "../../interfaces/ITreeVerifier.sol"; import {CheckInitialized} from "../../utils/CheckInitialized.sol"; import {SemaphoreVerifier} from "semaphore/base/SemaphoreVerifier.sol"; import {TypeConverter as TC} from "../utils/TypeConverter.sol"; -import {Verifier as TreeVerifier} from "../mock/TreeVerifier.sol"; +import {Verifier as TreeVerifier} from "../mock/InsertionTreeVerifier.sol"; import {VerifierLookupTable} from "../../data/VerifierLookupTable.sol"; import {WorldIDIdentityManagerImplV2 as ManagerImpl} from "../../WorldIDIdentityManagerImplV2.sol"; @@ -27,7 +27,7 @@ contract WorldIDIdentityManagerUninit is WorldIDIdentityManagerTest { makeUninitIdentityManager(); bytes memory callData = abi.encodeCall( ManagerImplV1.registerIdentities, - (proof, preRoot, startIndex, identityCommitments, postRoot) + (insertionProof, insertionPreRoot, startIndex, identityCommitments, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector(CheckInitialized.ImplementationNotInitialized.selector); @@ -42,7 +42,8 @@ contract WorldIDIdentityManagerUninit is WorldIDIdentityManagerTest { // Setup makeUninitIdentityManager(); bytes memory callData = abi.encodeCall( - ManagerImpl.deleteIdentities, (proof, preRoot, deletionIndices, postRoot) + ManagerImpl.deleteIdentities, + (deletionProof, insertionPreRoot, deletionIndices, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector(CheckInitialized.ImplementationNotInitialized.selector); @@ -67,7 +68,7 @@ contract WorldIDIdentityManagerUninit is WorldIDIdentityManagerTest { ) = prepareUpdateIdentitiesTestCase(identities, prf); bytes memory callData = abi.encodeCall( ManagerImplV1.updateIdentities, - (actualProof, initialRoot, leafIndices, oldIdents, newIdents, postRoot) + (actualProof, initialRoot, leafIndices, oldIdents, newIdents, insertionPostRoot) ); bytes memory expectedError = abi.encodeWithSelector(CheckInitialized.ImplementationNotInitialized.selector); @@ -83,7 +84,7 @@ contract WorldIDIdentityManagerUninit is WorldIDIdentityManagerTest { makeUninitIdentityManager(); bytes memory callData = abi.encodeCall( ManagerImplV1.calculateIdentityRegistrationInputHash, - (startIndex, preRoot, postRoot, identityCommitments) + (startIndex, insertionPreRoot, insertionPostRoot, identityCommitments) ); bytes memory expectedError = abi.encodeWithSelector(CheckInitialized.ImplementationNotInitialized.selector); @@ -110,7 +111,7 @@ contract WorldIDIdentityManagerUninit is WorldIDIdentityManagerTest { function testShouldNotCallQueryRootWhileUninit() public { // Setup makeUninitIdentityManager(); - bytes memory callData = abi.encodeCall(ManagerImplV1.queryRoot, (preRoot)); + bytes memory callData = abi.encodeCall(ManagerImplV1.queryRoot, (insertionPreRoot)); bytes memory expectedError = abi.encodeWithSelector(CheckInitialized.ImplementationNotInitialized.selector); @@ -123,7 +124,7 @@ contract WorldIDIdentityManagerUninit is WorldIDIdentityManagerTest { function testShouldNotCallRequireValidRootWhileUninit() public { // Setup makeUninitIdentityManager(); - bytes memory callData = abi.encodeCall(ManagerImplV1.requireValidRoot, (preRoot)); + bytes memory callData = abi.encodeCall(ManagerImplV1.requireValidRoot, (insertionPreRoot)); bytes memory expectedError = abi.encodeWithSelector(CheckInitialized.ImplementationNotInitialized.selector); diff --git a/src/test/mock/DeletionTreeVerifier.sol b/src/test/mock/DeletionTreeVerifier.sol new file mode 100644 index 0000000..4ee087c --- /dev/null +++ b/src/test/mock/DeletionTreeVerifier.sol @@ -0,0 +1,334 @@ +// SPDX-License-Identifier: AML +// +// Copyright 2017 Christian Reitwiessner +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to +// deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +// IN THE SOFTWARE. + +// 2019 OKIMS + +pragma solidity ^0.8.21; + +// Worldcoin Modification Begin +import {ITreeVerifier} from "../../interfaces/ITreeVerifier.sol"; +// Worldcoin Modification End + +library Pairing { + uint256 constant PRIME_Q = + 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + struct G1Point { + uint256 X; + uint256 Y; + } + + // Encoding of field elements is: X[0] * z + X[1] + struct G2Point { + uint256[2] X; + uint256[2] Y; + } + + /* + * @return The negation of p, i.e. p.plus(p.negate()) should be zero. + */ + function negate(G1Point memory p) internal pure returns (G1Point memory) { + // The prime q in the base field F_q for G1 + if (p.X == 0 && p.Y == 0) { + return G1Point(0, 0); + } else { + return G1Point(p.X, PRIME_Q - (p.Y % PRIME_Q)); + } + } + + /* + * @return The sum of two points of G1 + */ + function plus(G1Point memory p1, G1Point memory p2) internal view returns (G1Point memory r) { + uint256[4] memory input; + input[0] = p1.X; + input[1] = p1.Y; + input[2] = p2.X; + input[3] = p2.Y; + bool success; + + // solium-disable-next-line security/no-inline-assembly + assembly { + success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success + case 0 { invalid() } + } + + require(success, "pairing-add-failed"); + } + + /* + * Same as plus but accepts raw input instead of struct + * @return The sum of two points of G1, one is represented as array + */ + function plus_raw(uint256[4] memory input, G1Point memory r) internal view { + bool success; + + // solium-disable-next-line security/no-inline-assembly + assembly { + success := staticcall(sub(gas(), 2000), 6, input, 0xc0, r, 0x60) + // Use "invalid" to make gas estimation work + switch success + case 0 { invalid() } + } + + require(success, "pairing-add-failed"); + } + + /* + * @return The product of a point on G1 and a scalar, i.e. + * p == p.scalar_mul(1) and p.plus(p) == p.scalar_mul(2) for all + * points p. + */ + function scalar_mul(G1Point memory p, uint256 s) internal view returns (G1Point memory r) { + uint256[3] memory input; + input[0] = p.X; + input[1] = p.Y; + input[2] = s; + bool success; + // solium-disable-next-line security/no-inline-assembly + assembly { + success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success + case 0 { invalid() } + } + require(success, "pairing-mul-failed"); + } + + /* + * Same as scalar_mul but accepts raw input instead of struct, + * Which avoid extra allocation. provided input can be allocated outside and re-used multiple times + */ + function scalar_mul_raw(uint256[3] memory input, G1Point memory r) internal view { + bool success; + + // solium-disable-next-line security/no-inline-assembly + assembly { + success := staticcall(sub(gas(), 2000), 7, input, 0x80, r, 0x60) + // Use "invalid" to make gas estimation work + switch success + case 0 { invalid() } + } + require(success, "pairing-mul-failed"); + } + + /* @return The result of computing the pairing check + * e(p1[0], p2[0]) * .... * e(p1[n], p2[n]) == 1 + * For example, + * pairing([P1(), P1().negate()], [P2(), P2()]) should return true. + */ + function pairing( + G1Point memory a1, + G2Point memory a2, + G1Point memory b1, + G2Point memory b2, + G1Point memory c1, + G2Point memory c2, + G1Point memory d1, + G2Point memory d2 + ) internal view returns (bool) { + G1Point[4] memory p1 = [a1, b1, c1, d1]; + G2Point[4] memory p2 = [a2, b2, c2, d2]; + uint256 inputSize = 24; + uint256[] memory input = new uint256[](inputSize); + + for (uint256 i = 0; i < 4; i++) { + uint256 j = i * 6; + input[j + 0] = p1[i].X; + input[j + 1] = p1[i].Y; + input[j + 2] = p2[i].X[0]; + input[j + 3] = p2[i].X[1]; + input[j + 4] = p2[i].Y[0]; + input[j + 5] = p2[i].Y[1]; + } + + uint256[1] memory out; + bool success; + + // solium-disable-next-line security/no-inline-assembly + assembly { + success := + staticcall(sub(gas(), 2000), 8, add(input, 0x20), mul(inputSize, 0x20), out, 0x20) + // Use "invalid" to make gas estimation work + switch success + case 0 { invalid() } + } + + require(success, "pairing-opcode-failed"); + + return out[0] != 0; + } +} + +// Worldcoin Modification Begin +contract Verifier is ITreeVerifier { + // Worldcoin Modification End + using Pairing for *; + + uint256 constant SNARK_SCALAR_FIELD = + 21888242871839275222246405745257275088548364400416034343698204186575808495617; + uint256 constant PRIME_Q = + 21888242871839275222246405745257275088696311157297823662689037894645226208583; + + struct VerifyingKey { + Pairing.G1Point alfa1; + Pairing.G2Point beta2; + Pairing.G2Point gamma2; + Pairing.G2Point delta2; + } + // []G1Point IC (K in gnark) appears directly in verifyProof + + struct Proof { + Pairing.G1Point A; + Pairing.G2Point B; + Pairing.G1Point C; + } + + function verifyingKey() internal pure returns (VerifyingKey memory vk) { + vk.alfa1 = Pairing.G1Point( + uint256(52310580967459383704021522385189254499304474471547535811310615398576769951), + uint256(7291249744446722037162513203943006986339795116141384316533111547561641167822) + ); + vk.beta2 = Pairing.G2Point( + [ + uint256(8774379755363320550669844180112264022627426381980458747522921543861904032921), + uint256(17050651176309917467812173085994634667615850293804401137194981963221191345214) + ], + [ + uint256(9532649927932127528504849154920868233868762393828686925532075937157486281555), + uint256(20563090312175461275499757844669675815825471730038416221147314992656674798692) + ] + ); + vk.gamma2 = Pairing.G2Point( + [ + uint256(10223309812847353065265790704275368236646318307022189099083441109364521213510), + uint256(5479048347683019968734080992524690982834639863860330169657505457862645969740) + ], + [ + uint256(8943216645050495424919694812228077480981816275684868517846763236752223349833), + uint256(20902185363846403723699635306655644636499525938556936384747313777463028032705) + ] + ); + vk.delta2 = Pairing.G2Point( + [ + uint256(12325231795587563109820874988033304510461460742341796001540677194285279812747), + uint256(17350151067619102762774183339085304742366477476204397745251535350585554521998) + ], + [ + uint256(17262195326165479167814590336065562959354006927671232024563285122330580203859), + uint256(1222091031474366491842744700014113530726241346759454954111938176521073904056) + ] + ); + } + + // accumulate scalarMul(mul_input) into q + // that is computes sets q = (mul_input[0:2] * mul_input[3]) + q + function accumulate( + uint256[3] memory mul_input, + Pairing.G1Point memory p, + uint256[4] memory buffer, + Pairing.G1Point memory q + ) internal view { + // computes p = mul_input[0:2] * mul_input[3] + Pairing.scalar_mul_raw(mul_input, p); + + // point addition inputs + buffer[0] = q.X; + buffer[1] = q.Y; + buffer[2] = p.X; + buffer[3] = p.Y; + + // q = p + q + Pairing.plus_raw(buffer, q); + } + + /* + * @returns Whether the proof is valid given the hardcoded verifying key + * above and the public inputs + */ + function verifyProof( + uint256[2] memory a, + uint256[2][2] memory b, + uint256[2] memory c, + uint256[1] calldata input + ) public view returns (bool r) { + Proof memory proof; + proof.A = Pairing.G1Point(a[0], a[1]); + proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]); + proof.C = Pairing.G1Point(c[0], c[1]); + + // Make sure that proof.A, B, and C are each less than the prime q + require(proof.A.X < PRIME_Q, "verifier-aX-gte-prime-q"); + require(proof.A.Y < PRIME_Q, "verifier-aY-gte-prime-q"); + + require(proof.B.X[0] < PRIME_Q, "verifier-bX0-gte-prime-q"); + require(proof.B.Y[0] < PRIME_Q, "verifier-bY0-gte-prime-q"); + + require(proof.B.X[1] < PRIME_Q, "verifier-bX1-gte-prime-q"); + require(proof.B.Y[1] < PRIME_Q, "verifier-bY1-gte-prime-q"); + + require(proof.C.X < PRIME_Q, "verifier-cX-gte-prime-q"); + require(proof.C.Y < PRIME_Q, "verifier-cY-gte-prime-q"); + + // Make sure that every input is less than the snark scalar field + for (uint256 i = 0; i < input.length; i++) { + require(input[i] < SNARK_SCALAR_FIELD, "verifier-gte-snark-scalar-field"); + } + + VerifyingKey memory vk = verifyingKey(); + + // Compute the linear combination vk_x + Pairing.G1Point memory vk_x = Pairing.G1Point(0, 0); + + // Buffer reused for addition p1 + p2 to avoid memory allocations + // [0:2] -> p1.X, p1.Y ; [2:4] -> p2.X, p2.Y + uint256[4] memory add_input; + + // Buffer reused for multiplication p1 * s + // [0:2] -> p1.X, p1.Y ; [3] -> s + uint256[3] memory mul_input; + + // temporary point to avoid extra allocations in accumulate + Pairing.G1Point memory q = Pairing.G1Point(0, 0); + + vk_x.X = + uint256(15192898137962050825752556154192558668690494364746507462245302757774844453066); // vk.K[0].X + vk_x.Y = + uint256(17224823573622770939180121865028927654857290127034369071352333165806833510555); // vk.K[0].Y + mul_input[0] = + uint256(10255897644603320765835520092115638625648096021879181094405107761224658229409); // vk.K[1].X + mul_input[1] = + uint256(20207387871300138546929839074164215373130154272732599264420957757415128753368); // vk.K[1].Y + mul_input[2] = input[0]; + accumulate(mul_input, q, add_input, vk_x); // vk_x += vk.K[1] * input[0] + + return Pairing.pairing( + Pairing.negate(proof.A), + proof.B, + vk.alfa1, + vk.beta2, + vk_x, + vk.gamma2, + proof.C, + vk.delta2 + ); + } +} diff --git a/src/test/mock/TreeVerifier.sol b/src/test/mock/InsertionTreeVerifier.sol similarity index 100% rename from src/test/mock/TreeVerifier.sol rename to src/test/mock/InsertionTreeVerifier.sol