From 22ba4ff130aa13435d8e5cc33240cbc2c85036fd Mon Sep 17 00:00:00 2001 From: r4bbit <445106+0x-r4bbit@users.noreply.github.com> Date: Tue, 15 Jul 2025 15:18:21 +0200 Subject: [PATCH] refactor(RLN): remove verifier and exit function --- .gas-report | 58 ++++++++--------------- .gas-snapshot | 16 +++---- script/RLN.s.sol | 5 +- src/rln/RLN.sol | 45 +----------------- test/RLN.t.sol | 117 ++--------------------------------------------- 5 files changed, 31 insertions(+), 210 deletions(-) diff --git a/.gas-report b/.gas-report index 35f6ce5..5648f9f 100644 --- a/.gas-report +++ b/.gas-report @@ -4,13 +4,13 @@ +=================================================================================================================================================+ | Deployment Cost | Deployment Size | | | | | |-------------------------------------------------------------------------------------------+-----------------+-------+--------+--------+---------| -| 295493 | 1374 | | | | | +| 272694 | 1374 | | | | | |-------------------------------------------------------------------------------------------+-----------------+-------+--------+--------+---------| | | | | | | | |-------------------------------------------------------------------------------------------+-----------------+-------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-------------------------------------------------------------------------------------------+-----------------+-------+--------+--------+---------| -| fallback | 5145 | 64591 | 33119 | 193478 | 3571 | +| fallback | 5145 | 65050 | 33119 | 193478 | 3522 | ╰-------------------------------------------------------------------------------------------+-----------------+-------+--------+--------+---------╯ ╭-----------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -24,7 +24,7 @@ |-----------------------------------------------------+-----------------+---------+---------+---------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |-----------------------------------------------------+-----------------+---------+---------+---------+---------| -| run | 4666141 | 4666141 | 4666141 | 4666141 | 186 | +| run | 4666141 | 4666141 | 4666141 | 4666141 | 182 | ╰-----------------------------------------------------+-----------------+---------+---------+---------+---------╯ ╭-----------------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -80,7 +80,7 @@ |---------------------------------------------------------+-----------------+------+--------+------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |---------------------------------------------------------+-----------------+------+--------+------+---------| -| activeNetworkConfig | 455 | 2090 | 455 | 4455 | 548 | +| activeNetworkConfig | 455 | 2084 | 455 | 4455 | 540 | ╰---------------------------------------------------------+-----------------+------+--------+------+---------╯ ╭---------------------------------------------------------------------+-----------------+---------+---------+---------+---------╮ @@ -114,11 +114,11 @@ |------------------------------+-----------------+--------+--------+--------+---------| | OPERATOR_ROLE | 262 | 262 | 262 | 262 | 2 | |------------------------------+-----------------+--------+--------+--------+---------| -| SLASHER_ROLE | 262 | 262 | 262 | 262 | 34 | +| SLASHER_ROLE | 262 | 262 | 262 | 262 | 30 | |------------------------------+-----------------+--------+--------+--------+---------| | accountSlashAmount | 2611 | 2611 | 2611 | 2611 | 2 | |------------------------------+-----------------+--------+--------+--------+---------| -| addRewardDistributor | 29975 | 63560 | 70903 | 70903 | 304 | +| addRewardDistributor | 29975 | 63592 | 70903 | 70903 | 296 | |------------------------------+-----------------+--------+--------+--------+---------| | allowance | 573 | 573 | 573 | 573 | 8 | |------------------------------+-----------------+--------+--------+--------+---------| @@ -130,11 +130,11 @@ |------------------------------+-----------------+--------+--------+--------+---------| | getRewardDistributors | 5132 | 7710 | 9644 | 9644 | 21 | |------------------------------+-----------------+--------+--------+--------+---------| -| grantRole | 29490 | 29490 | 29490 | 29490 | 39 | +| grantRole | 29490 | 29490 | 29490 | 29490 | 35 | |------------------------------+-----------------+--------+--------+--------+---------| | hasRole | 2754 | 2754 | 2754 | 2754 | 4 | |------------------------------+-----------------+--------+--------+--------+---------| -| initialize | 116796 | 116796 | 116796 | 116796 | 186 | +| initialize | 116796 | 116796 | 116796 | 116796 | 182 | |------------------------------+-----------------+--------+--------+--------+---------| | mint | 4869 | 50370 | 51342 | 51342 | 551 | |------------------------------+-----------------+--------+--------+--------+---------| @@ -396,7 +396,7 @@ +===============================================================================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------------------------------------------------------------------+-----------------+-------+--------+-------+---------| -| 1204853 | 6015 | | | | | +| 1204853 | 6207 | | | | | |------------------------------------------------------------------------------------------+-----------------+-------+--------+-------+---------| | | | | | | | |------------------------------------------------------------------------------------------+-----------------+-------+--------+-------+---------| @@ -436,55 +436,33 @@ +=====================================================================================+ | Deployment Cost | Deployment Size | | | | | |------------------------------+-----------------+--------+--------+--------+---------| -| 1982512 | 9143 | | | | | +| 1751905 | 8068 | | | | | |------------------------------+-----------------+--------+--------+--------+---------| | | | | | | | |------------------------------+-----------------+--------+--------+--------+---------| | Function Name | Min | Avg | Median | Max | # Calls | |------------------------------+-----------------+--------+--------+--------+---------| -| DEFAULT_ADMIN_ROLE | 262 | 262 | 262 | 262 | 10 | +| DEFAULT_ADMIN_ROLE | 262 | 262 | 262 | 262 | 6 | |------------------------------+-----------------+--------+--------+--------+---------| -| REGISTER_ROLE | 262 | 262 | 262 | 262 | 10 | +| REGISTER_ROLE | 262 | 262 | 262 | 262 | 6 | |------------------------------+-----------------+--------+--------+--------+---------| | SET_SIZE | 2339 | 2339 | 2339 | 2339 | 1 | |------------------------------+-----------------+--------+--------+--------+---------| -| SLASHER_ROLE | 262 | 262 | 262 | 262 | 10 | +| SLASHER_ROLE | 262 | 262 | 262 | 262 | 6 | |------------------------------+-----------------+--------+--------+--------+---------| -| exit | 7068 | 16233 | 18694 | 22939 | 3 | -|------------------------------+-----------------+--------+--------+--------+---------| -| hasRole | 2707 | 2707 | 2707 | 2707 | 30 | +| hasRole | 2707 | 2707 | 2707 | 2707 | 18 | |------------------------------+-----------------+--------+--------+--------+---------| | identityCommitmentIndex | 2340 | 2340 | 2340 | 2340 | 5 | |------------------------------+-----------------+--------+--------+--------+---------| -| initialize | 165036 | 165036 | 165036 | 165036 | 11 | +| initialize | 142752 | 142752 | 142752 | 142752 | 7 | |------------------------------+-----------------+--------+--------+--------+---------| -| members | 4669 | 4669 | 4669 | 4669 | 6 | +| members | 4669 | 4669 | 4669 | 4669 | 5 | |------------------------------+-----------------+--------+--------+--------+---------| -| register | 6997 | 45345 | 53001 | 55801 | 11 | +| register | 6997 | 42474 | 53001 | 55801 | 8 | |------------------------------+-----------------+--------+--------+--------+---------| -| slash | 7111 | 54764 | 18737 | 138444 | 3 | -|------------------------------+-----------------+--------+--------+--------+---------| -| verifier | 2359 | 2359 | 2359 | 2359 | 1 | +| slash | 7032 | 66881 | 66881 | 126731 | 2 | ╰------------------------------+-----------------+--------+--------+--------+---------╯ -╭--------------------------------------+-----------------+-------+--------+-------+---------╮ -| test/RLN.t.sol:MockVerifier Contract | | | | | | -+===========================================================================================+ -| Deployment Cost | Deployment Size | | | | | -|--------------------------------------+-----------------+-------+--------+-------+---------| -| 204321 | 642 | | | | | -|--------------------------------------+-----------------+-------+--------+-------+---------| -| | | | | | | -|--------------------------------------+-----------------+-------+--------+-------+---------| -| Function Name | Min | Avg | Median | Max | # Calls | -|--------------------------------------+-----------------+-------+--------+-------+---------| -| changeResult | 21649 | 21649 | 21649 | 21649 | 2 | -|--------------------------------------+-----------------+-------+--------+-------+---------| -| result | 2298 | 2298 | 2298 | 2298 | 3 | -|--------------------------------------+-----------------+-------+--------+-------+---------| -| verifyProof | 4790 | 4790 | 4790 | 4790 | 4 | -╰--------------------------------------+-----------------+-------+--------+-------+---------╯ - ╭-------------------------------------------------------------------+-----------------+-------+--------+-------+---------╮ | test/mocks/KarmaDistributorMock.sol:KarmaDistributorMock Contract | | | | | | +========================================================================================================================+ diff --git a/.gas-snapshot b/.gas-snapshot index d7df711..b7ae3f9 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -112,16 +112,12 @@ OverflowTest:testTotalSupply() (gas: 359391) OverflowTest:testTransfersNotAllowed() (gas: 61925) OverflowTest:test_RevertWhen_MintingCausesOverflow() (gas: 129592) OverflowTest:test_RevertWhen_SettingRewardCausesOverflow() (gas: 127920) -RLNTest:test_exit_fails_when_invalid_proof() (gas: 195432) -RLNTest:test_exit_fails_when_not_registered() (gas: 64843) -RLNTest:test_exit_succeeds() (gas: 187485) -RLNTest:test_initial_state() (gas: 60571) -RLNTest:test_register_fails_when_duplicate_identity_commitment() (gas: 131752) -RLNTest:test_register_fails_when_index_exceeds_set_size() (gas: 2569410) -RLNTest:test_register_succeeds() (gas: 272680) -RLNTest:test_slash_fails_when_invalid_proof() (gas: 195506) -RLNTest:test_slash_fails_when_not_registered() (gas: 64886) -RLNTest:test_slash_succeeds() (gas: 438591) +RLNTest:test_initial_state() (gas: 45654) +RLNTest:test_register_fails_when_duplicate_identity_commitment() (gas: 131740) +RLNTest:test_register_fails_when_index_exceeds_set_size() (gas: 2313519) +RLNTest:test_register_succeeds() (gas: 272683) +RLNTest:test_slash_fails_when_not_registered() (gas: 46080) +RLNTest:test_slash_succeeds() (gas: 408157) RemoveRewardDistributorTest:testAddKarmaDistributorOnlyAdmin() (gas: 438248) RemoveRewardDistributorTest:testBalanceOf() (gas: 456715) RemoveRewardDistributorTest:testBalanceOfWithNoSystemTotalKarma() (gas: 83783) diff --git a/script/RLN.s.sol b/script/RLN.s.sol index a285354..476dc2f 100644 --- a/script/RLN.s.sol +++ b/script/RLN.s.sol @@ -6,11 +6,9 @@ import { DeploymentConfig } from "./DeploymentConfig.s.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; -import { Groth16Verifier } from "../src/rln/Verifier.sol"; import { RLN } from "../src/rln/RLN.sol"; contract DeployRLNScript is BaseScript { - error InvalidDepth(); error InvalidAddress(); @@ -28,10 +26,9 @@ contract DeployRLNScript is BaseScript { } vm.startBroadcast(deployer); - address verifier = (address)(new Groth16Verifier()); // Deploy Karma logic contract bytes memory initializeData = - abi.encodeCall(RLN.initialize, (deployer, deployer, deployer, depth, verifier, karmaAddress)); + abi.encodeCall(RLN.initialize, (deployer, deployer, deployer, depth, karmaAddress)); address impl = address(new RLN()); // Create upgradeable proxy address proxy = address(new ERC1967Proxy(impl, initializeData)); diff --git a/src/rln/RLN.sol b/src/rln/RLN.sol index c712943..9869bcd 100644 --- a/src/rln/RLN.sol +++ b/src/rln/RLN.sol @@ -6,7 +6,6 @@ import { Karma } from "../Karma.sol"; import { AccessControlUpgradeable } from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; import { Initializable } from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; -import { IVerifier } from "./IVerifier.sol"; /// @title Rate-Limiting Nullifier registry contract /// @dev This contract allows you to register RLN commitment and withdraw/slash. @@ -14,7 +13,6 @@ contract RLN is Initializable, UUPSUpgradeable, AccessControlUpgradeable { bytes32 public constant SLASHER_ROLE = keccak256("SLASHER_ROLE"); bytes32 public constant REGISTER_ROLE = keccak256("REGISTER_ROLE"); - error RLN__InvalidProof(); error RLN__MemberNotFound(); error RLN__IdCommitmentAlreadyRegistered(); error RLN__SetIsFull(); @@ -40,18 +38,11 @@ contract RLN is Initializable, UUPSUpgradeable, AccessControlUpgradeable { /// @dev Karma Token used for registering. Karma public karma; - /// @dev Groth16 verifier. - IVerifier public verifier; - /// @dev Emmited when a new member registered. /// @param identityCommitment: `identityCommitment`; /// @param index: idCommitmentIndex value. event MemberRegistered(uint256 identityCommitment, uint256 index); - /// @dev Emmited when a member was withdrawn. - /// @param index: index of `identityCommitment`; - event MemberExited(uint256 index); - /// @dev Emmited when a member was slashed. /// @param index: index of `identityCommitment`; /// @param slasher: address of slasher (msg.sender). @@ -67,13 +58,11 @@ contract RLN is Initializable, UUPSUpgradeable, AccessControlUpgradeable { /// @param _register: address of the register; /// @param depth: depth of the merkle tree; /// @param _token: address of the ERC20 contract; - /// @param _verifier: address of the Groth16 Verifier. function initialize( address _owner, address _slasher, address _register, uint256 depth, - address _verifier, address _token ) public @@ -87,7 +76,6 @@ contract RLN is Initializable, UUPSUpgradeable, AccessControlUpgradeable { SET_SIZE = 1 << depth; karma = Karma(_token); - verifier = IVerifier(_verifier); } /** @@ -122,47 +110,16 @@ contract RLN is Initializable, UUPSUpgradeable, AccessControlUpgradeable { } } - /// @dev Request for exit. - /// @param identityCommitment: `identityCommitment`; - /// @param proof: snarkjs's format generated proof (without public inputs) packed consequently. - function exit(uint256 identityCommitment, uint256[8] calldata proof) external onlyRole(REGISTER_ROLE) { - User memory member = members[identityCommitment]; - if (member.userAddress == address(0)) { - revert RLN__MemberNotFound(); - } - if (!_verifyProof(identityCommitment, proof)) { - revert RLN__InvalidProof(); - } - - delete members[identityCommitment]; - emit MemberExited(member.index); - } - /// @dev Slashes identity with identityCommitment. /// @param identityCommitment: `identityCommitment`; - /// @param proof: snarkjs's format generated proof (without public inputs) packed consequently. - function slash(uint256 identityCommitment, uint256[8] calldata proof) external onlyRole(SLASHER_ROLE) { + function slash(uint256 identityCommitment) external onlyRole(SLASHER_ROLE) { User memory member = members[identityCommitment]; if (member.userAddress == address(0)) { revert RLN__MemberNotFound(); } - if (!_verifyProof(identityCommitment, proof)) { - revert RLN__InvalidProof(); - } - karma.slash(member.userAddress); delete members[identityCommitment]; emit MemberSlashed(member.index, msg.sender); } - - /// @dev Groth16 proof verification - function _verifyProof(uint256 identityCommitment, uint256[8] calldata proof) internal view returns (bool) { - return verifier.verifyProof( - [proof[0], proof[1]], - [[proof[2], proof[3]], [proof[4], proof[5]]], - [proof[6], proof[7]], - [identityCommitment, uint256(0)] - ); - } } diff --git a/test/RLN.t.sol b/test/RLN.t.sol index a48bdd6..2c6d308 100644 --- a/test/RLN.t.sol +++ b/test/RLN.t.sol @@ -4,44 +4,14 @@ pragma solidity ^0.8.26; import { Test } from "forge-std/Test.sol"; import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; import { RLN } from "../src/rln/RLN.sol"; -import { IVerifier } from "../src/rln/IVerifier.sol"; import { Karma } from "../src/Karma.sol"; import { KarmaDistributorMock } from "./mocks/KarmaDistributorMock.sol"; import { DeployKarmaScript } from "../script/DeployKarma.s.sol"; -import { DeployRLNScript } from "../script/RLN.s.sol"; import { DeploymentConfig } from "../script/DeploymentConfig.s.sol"; -/// @dev A mock verifier that allows toggling proof validity. -contract MockVerifier is IVerifier { - bool public result; - - constructor() { - result = true; - } - - function verifyProof( - uint256[2] memory, - uint256[2][2] memory, - uint256[2] memory, - uint256[2] memory - ) - external - view - override - returns (bool) - { - return result; - } - - function changeResult(bool _result) external { - result = _result; - } -} - contract RLNTest is Test { RLN public rln; - MockVerifier public verifier; uint256 private constant DEPTH = 2; // for most tests uint256 private constant SMALL_DEPTH = 1; // for “full” test @@ -51,10 +21,6 @@ contract RLNTest is Test { uint256 private identityCommitment1 = 5678; uint256 private identityCommitment2 = 9999; - // Sample SNARK proof (8‐element array) - uint256[8] private mockProof = - [uint256(0), uint256(1), uint256(2), uint256(3), uint256(4), uint256(5), uint256(6), uint256(7)]; - // Role‐holders address private owner; Karma private karma; @@ -83,11 +49,8 @@ contract RLNTest is Test { registerAddr = makeAddr("register"); slasherAddr = makeAddr("slasher"); - // Deploy mock verifier - verifier = new MockVerifier(); - // Deploy RLN via UUPS proxy with DEPTH = 2 - rln = _deployRLN(DEPTH, address(verifier), karma); + rln = _deployRLN(DEPTH, karma); // Sanity‐check that roles were assigned correctly assertTrue(rln.hasRole(rln.DEFAULT_ADMIN_ROLE(), adminAddr)); @@ -102,7 +65,7 @@ contract RLNTest is Test { } /// @dev Deploys a new RLN instance (behind ERC1967Proxy). - function _deployRLN(uint256 depth, address verifierAddr, Karma karmaToken) internal returns (RLN) { + function _deployRLN(uint256 depth, Karma karmaToken) internal returns (RLN) { bytes memory initData = abi.encodeCall( RLN.initialize, ( @@ -110,7 +73,6 @@ contract RLNTest is Test { slasherAddr, registerAddr, depth, - verifierAddr, address(karmaToken) // token address unused in these tests ) ); @@ -132,9 +94,6 @@ contract RLNTest is Test { (address user0, uint256 idx0) = _memberData(identityCommitment0); assertEq(user0, address(0)); assertEq(idx0, 0); - - // Verifier address matches - assertEq(address(rln.verifier()), address(verifier)); } /* ---------- REGISTER ---------- */ @@ -169,7 +128,7 @@ contract RLNTest is Test { function test_register_fails_when_index_exceeds_set_size() public { // Deploy a small RLN with depth = 1 => SET_SIZE = 2 - RLN smallRLN = _deployRLN(SMALL_DEPTH, address(verifier), karma); + RLN smallRLN = _deployRLN(SMALL_DEPTH, karma); address smallRegister = registerAddr; // Fill up both slots @@ -198,55 +157,6 @@ contract RLNTest is Test { vm.stopPrank(); } - /* ---------- EXIT ---------- */ - - function test_exit_succeeds() public { - // Register the identity - vm.startPrank(registerAddr); - rln.register(identityCommitment0, user1Addr); - vm.stopPrank(); - - // Ensure mock verifier returns true by default - assertTrue(verifier.result()); - - // Call exit with a valid proof - vm.startPrank(registerAddr); - vm.expectEmit(false, false, false, true); - emit RLN.MemberExited(0); - rln.exit(identityCommitment0, mockProof); - vm.stopPrank(); - - // After exit, the member record should be cleared - (address u0, uint256 i0) = _memberData(identityCommitment0); - assertEq(u0, address(0)); - assertEq(i0, 0); - } - - function test_exit_fails_when_not_registered() public { - // Attempt exit without prior registration - vm.startPrank(registerAddr); - vm.expectRevert(RLN.RLN__MemberNotFound.selector); - rln.exit(identityCommitment1, mockProof); - vm.stopPrank(); - } - - function test_exit_fails_when_invalid_proof() public { - // Register the identity - vm.startPrank(registerAddr); - rln.register(identityCommitment0, user1Addr); - vm.stopPrank(); - - // Make proof invalid - verifier.changeResult(false); - assertFalse(verifier.result()); - - // Attempt exit with invalid proof - vm.startPrank(registerAddr); - vm.expectRevert(RLN.RLN__InvalidProof.selector); - rln.exit(identityCommitment0, mockProof); - vm.stopPrank(); - } - /* ---------- SLASH ---------- */ function test_slash_succeeds() public { @@ -268,7 +178,7 @@ contract RLNTest is Test { vm.startPrank(slasherAddr); vm.expectEmit(false, true, false, true); emit RLN.MemberSlashed(index1, slasherAddr); - rln.slash(identityCommitment1, mockProof); + rln.slash(identityCommitment1); vm.stopPrank(); // After slash, the member record should be cleared @@ -281,24 +191,7 @@ contract RLNTest is Test { // Attempt to slash a non‐existent identity vm.startPrank(slasherAddr); vm.expectRevert(RLN.RLN__MemberNotFound.selector); - rln.slash(identityCommitment0, mockProof); - vm.stopPrank(); - } - - function test_slash_fails_when_invalid_proof() public { - // Register the identity - vm.startPrank(registerAddr); - rln.register(identityCommitment0, user1Addr); - vm.stopPrank(); - - // Make proof invalid - verifier.changeResult(false); - assertFalse(verifier.result()); - - // Attempt to slash with invalid proof - vm.startPrank(slasherAddr); - vm.expectRevert(RLN.RLN__InvalidProof.selector); - rln.slash(identityCommitment0, mockProof); + rln.slash(identityCommitment0); vm.stopPrank(); }