From 98bb0df15d723f8f4494da14d9670521de190918 Mon Sep 17 00:00:00 2001 From: gcranju Date: Fri, 29 Nov 2024 11:04:59 +0545 Subject: [PATCH] cluster connection specs change --- .../contracts/adapters/ClusterConnection.sol | 66 ++++--- .../evm/test/adapters/ClusterConnection.t.sol | 175 +++--------------- 2 files changed, 74 insertions(+), 167 deletions(-) diff --git a/contracts/evm/contracts/adapters/ClusterConnection.sol b/contracts/evm/contracts/adapters/ClusterConnection.sol index a0eb7e43..2f333310 100644 --- a/contracts/evm/contracts/adapters/ClusterConnection.sol +++ b/contracts/evm/contracts/adapters/ClusterConnection.sol @@ -2,11 +2,14 @@ pragma solidity >=0.8.0; pragma abicoder v2; +import {console2 } from "forge-std/Test.sol"; + import "openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol"; import "@xcall/utils/Types.sol"; import "@xcall/contracts/xcall/interfaces/IConnection.sol"; import "@iconfoundation/xcall-solidity-library/interfaces/ICallService.sol"; import "@iconfoundation/xcall-solidity-library/utils/RLPEncode.sol"; +import "@iconfoundation/xcall-solidity-library/utils/RLPEncode.sol"; contract ClusterConnection is Initializable, IConnection { @@ -26,7 +29,7 @@ contract ClusterConnection is Initializable, IConnection { uint8 private validatorsThreshold; event Message(string targetNetwork, uint256 sn, bytes _msg); - event ValidatorSetAdded(address[] _validator, uint8 _threshold); + event ValidatorSetAdded(bytes[] _validator, uint8 _threshold); modifier onlyRelayer() { require(msg.sender == this.relayer(), "OnlyRelayer"); @@ -48,11 +51,12 @@ contract ClusterConnection is Initializable, IConnection { return validators; } - function setValidators(address[] memory _validators, uint8 _threshold) external onlyAdmin { + function updateValidators(bytes[] memory _validators, uint8 _threshold) external onlyAdmin { delete validators; for (uint i = 0; i < _validators.length; i++) { - if(!isValidator(_validators[i]) && _validators[i] != address(0)) { - validators.push(_validators[i]); + address validators_address = publicKeyToAddress(_validators[i]); + if(!isValidator(validators_address) && validators_address != address(0)) { + validators.push(validators_address); } } require(validators.length >= _threshold, "Not enough validators"); @@ -143,10 +147,11 @@ contract ClusterConnection is Initializable, IConnection { bytes32 messageHash = getMessageHash(srcNetwork, _connSn, _msg); uint signerCount = 0; address[] memory collectedSigners = new address[](_signedMessages.length); + for (uint i = 0; i < _signedMessages.length; i++) { address signer = recoverSigner(messageHash, _signedMessages[i]); require(signer != address(0), "Invalid signature"); - if (!isValidatorProcessed(collectedSigners, signer)){ + if (!isValidatorProcessed(collectedSigners, signer) && existsInValidators(signer)){ collectedSigners[signerCount] = signer; signerCount++; } @@ -155,6 +160,13 @@ contract ClusterConnection is Initializable, IConnection { recvMessage(srcNetwork,_connSn,_msg); } + function existsInValidators(address signer) internal view returns (bool) { + for (uint i = 0; i < validators.length; i++){ + if (validators[i] == signer) return true; + } + return false; + } + function isValidatorProcessed(address[] memory processedSigners, address signer) public pure returns (bool) { for (uint i = 0; i < processedSigners.length; i++) { if (processedSigners[i] == signer) { @@ -178,25 +190,14 @@ contract ClusterConnection is Initializable, IConnection { v += 27; } require(v == 27 || v == 28, "Invalid signature 'v' value"); - return ecrecover(toEthSignedMessageHash(messageHash), v, r, s); - } - - function toEthSignedMessageHash(bytes32 _messageHash) internal pure returns (bytes32) { - return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _messageHash)); + return ecrecover(messageHash, v, r, s); } - - /** - @notice Sends the message to a xCall. - @param srcNetwork String ( Network Id ) - @param _connSn Integer ( connection message sn ) - @param _msg Bytes ( serialized bytes of Service Message ) - */ function recvMessage( string memory srcNetwork, uint256 _connSn, bytes calldata _msg - ) public onlyRelayer { + ) internal { require(!receipts[srcNetwork][_connSn], "Duplicate Message"); receipts[srcNetwork][_connSn] = true; ICallService(xCall).handleMessage(srcNetwork, _msg); @@ -232,11 +233,19 @@ contract ClusterConnection is Initializable, IConnection { } /** + @notice Set the address of the admin. + @param _address The address of the admin. + */ + function setAdmin(address _address) external onlyAdmin { + adminAddress = _address; + } + + /** @notice Set the address of the relayer. @param _address The address of the relayer. */ - function setAdmin(address _address) external onlyRelayer { - adminAddress = _address; + function setRelayer(address _address) external onlyAdmin { + relayerAddress = _address; } /** @@ -272,7 +281,22 @@ contract ClusterConnection is Initializable, IConnection { srcNetwork.encodeString(), _connSn.encodeUint(), _msg.encodeBytes() - ); + ).encodeList(); return keccak256(rlp); } + + function publicKeyToAddress(bytes memory publicKey) internal pure returns (address addr) { + require(publicKey.length == 65, "Invalid public key length"); + + bytes32 hash; + + assembly { + let publicKeyStart := add(publicKey, 0x20) + let destinationStart := add(publicKeyStart, 1) + hash := keccak256(destinationStart, 64) + } + + addr = address(uint160(uint256(hash))); + } + } diff --git a/contracts/evm/test/adapters/ClusterConnection.t.sol b/contracts/evm/test/adapters/ClusterConnection.t.sol index 57e4754c..5a52bee4 100644 --- a/contracts/evm/test/adapters/ClusterConnection.t.sol +++ b/contracts/evm/test/adapters/ClusterConnection.t.sol @@ -133,98 +133,6 @@ contract ClusterConnectionTest is Test { vm.stopPrank(); } - function testRecvMessage() public { - bytes memory data = bytes("test"); - string memory iconDapp = NetworkAddress.networkAddress( - nidSource, - "0xa" - ); - Types.CSMessageRequestV2 memory request = Types.CSMessageRequestV2( - iconDapp, - ParseAddress.toString(address(dappSource)), - 1, - Types.CALL_MESSAGE_TYPE, - data, - new string[](0) - ); - Types.CSMessage memory message = Types.CSMessage( - Types.CS_REQUEST, - request.encodeCSMessageRequestV2() - ); - - vm.startPrank(destination_relayer); - adapterTarget.recvMessage( - nidSource, - 1, - RLPEncodeStruct.encodeCSMessage(message) - ); - vm.stopPrank(); - } - - function testRecvMessageUnAuthorized() public { - bytes memory data = bytes("test"); - string memory iconDapp = NetworkAddress.networkAddress( - nidSource, - "0xa" - ); - Types.CSMessageRequestV2 memory request = Types.CSMessageRequestV2( - iconDapp, - ParseAddress.toString(address(dappSource)), - 1, - Types.CALL_MESSAGE_TYPE, - data, - new string[](0) - ); - Types.CSMessage memory message = Types.CSMessage( - Types.CS_REQUEST, - request.encodeCSMessageRequestV2() - ); - - vm.startPrank(user); - vm.expectRevert("OnlyRelayer"); - adapterTarget.recvMessage( - nidSource, - 1, - RLPEncodeStruct.encodeCSMessage(message) - ); - vm.stopPrank(); - } - - function testRecvMessageDuplicateMsg() public { - bytes memory data = bytes("test"); - string memory iconDapp = NetworkAddress.networkAddress( - nidSource, - "0xa" - ); - Types.CSMessageRequestV2 memory request = Types.CSMessageRequestV2( - iconDapp, - ParseAddress.toString(address(dappSource)), - 1, - Types.CALL_MESSAGE_TYPE, - data, - new string[](0) - ); - Types.CSMessage memory message = Types.CSMessage( - Types.CS_REQUEST, - request.encodeCSMessageRequestV2() - ); - - vm.startPrank(destination_relayer); - adapterTarget.recvMessage( - nidSource, - 1, - RLPEncodeStruct.encodeCSMessage(message) - ); - - vm.expectRevert("Duplicate Message"); - adapterTarget.recvMessage( - nidSource, - 1, - RLPEncodeStruct.encodeCSMessage(message) - ); - vm.stopPrank(); - } - function testRevertMessage() public { vm.startPrank(destination_relayer); vm.expectRevert("CallRequestNotFound"); @@ -284,9 +192,9 @@ contract ClusterConnectionTest is Test { vm.stopPrank(); assert(source_relayer.balance == 10 ether); - } + } - function testGetReceipt() public { + function testRecvMessageWithMultiSignatures() public { bytes memory data = bytes("test"); string memory iconDapp = NetworkAddress.networkAddress( nidSource, @@ -304,50 +212,19 @@ contract ClusterConnectionTest is Test { Types.CS_REQUEST, request.encodeCSMessageRequestV2() ); - - assert(adapterTarget.getReceipt(nidSource, 1) == false); - - vm.startPrank(destination_relayer); - adapterTarget.recvMessage( - nidSource, - 1, - RLPEncodeStruct.encodeCSMessage(message) - ); - vm.stopPrank(); - - assert(adapterTarget.getReceipt(nidSource, 1) == true); - } - - function testRecvMessageWithMultiSignature() public { - bytes memory data = bytes("test"); - string memory iconDapp = NetworkAddress.networkAddress( - nidSource, - "0xa" - ); - Types.CSMessageRequestV2 memory request = Types.CSMessageRequestV2( - iconDapp, - ParseAddress.toString(address(dappSource)), - 1, - Types.CALL_MESSAGE_TYPE, - data, - new string[](0) - ); - Types.CSMessage memory message = Types.CSMessage( - Types.CS_REQUEST, - request.encodeCSMessageRequestV2() - ); - uint256 pk = hexStringToUint256("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"); - uint256 pk2 = hexStringToUint256("47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a"); - uint256 pk3 = hexStringToUint256("59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d"); - uint256 pk4 = hexStringToUint256("2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6"); + uint256 pk = 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80; + uint256 pk2 = 0x47e179ec197488593b187f80a00eb0da91f1b9d0b13f8733639f19c30a34926a; + uint256 pk3 = 0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d; + uint256 pk4 = 0x2a871d0798f97d79848a013d4936a73bf4cc922c825d33c1cf7073dff6d409c6; bytes32 hash = getMessageHash(nidSource, 1, RLPEncodeStruct.encodeCSMessage(message)); vm.startPrank(owner); - address[] memory validators = new address[](4); - validators[0] = address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266); - validators[1] = address(0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65); - validators[2] = address(0x70997970C51812dc3A010C7d01b50e0d17dc79C8); - validators[3] = address(0xa0Ee7A142d267C1f36714E4a8F75612F20a79720); - adapterTarget.setValidators(validators, 4); + bytes[] memory validators = new bytes[](4); + validators[0] = bytes(hex"048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5"); + validators[1] = bytes(hex"04bf6ee64a8d2fdc551ec8bb9ef862ef6b4bcb1805cdc520c3aa5866c0575fd3b514c5562c3caae7aec5cd6f144b57135c75b6f6cea059c3d08d1f39a9c227219d"); + validators[2] = bytes(hex"04ba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e53807205fa2f08eec74f4"); + validators[3] = bytes(hex"043255458e24278e31d5940f304b16300fdff3f6efd3e2a030b5818310ac67af45e28d057e6a332d07e0c5ab09d6947fd4eed1a646edbf224e2d2fec6f49f90abc"); + adapterTarget.updateValidators(validators, 4); + adapterTarget.listValidators(); vm.stopPrank(); vm.startPrank(destination_relayer); @@ -370,7 +247,10 @@ contract ClusterConnectionTest is Test { function signMessage(uint256 pk,bytes32 hash) private pure returns (bytes memory){ (uint8 v, bytes32 r, bytes32 s) = vm.sign(pk, hash); + address signer = vm.addr(pk); bytes memory signature = combineSignature(r,s,v); + + address recoverSigner=ecrecover(hash,v,r,s); return signature; } @@ -402,11 +282,14 @@ contract ClusterConnectionTest is Test { function testAddValidator() public { vm.startPrank(owner); - address[] memory validators = new address[](2); - validators[0] = address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266); - validators[1] = address(0x976EA74026E726554dB657fA54763abd0C3a0aa9); - adapterTarget.setValidators(validators, 2); - assertEq(2, adapterTarget.listValidators().length); + bytes[] memory validators = new bytes[](4); + validators[0] = bytes(hex"048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5"); + validators[1] = bytes(hex"04bf6ee64a8d2fdc551ec8bb9ef862ef6b4bcb1805cdc520c3aa5866c0575fd3b514c5562c3caae7aec5cd6f144b57135c75b6f6cea059c3d08d1f39a9c227219d"); + validators[2] = bytes(hex"04ba5734d8f7091719471e7f7ed6b9df170dc70cc661ca05e688601ad984f068b0d67351e5f06073092499336ab0839ef8a521afd334e53807205fa2f08eec74f4"); + validators[3] = bytes(hex"043255458e24278e31d5940f304b16300fdff3f6efd3e2a030b5818310ac67af45e28d057e6a332d07e0c5ab09d6947fd4eed1a646edbf224e2d2fec6f49f90abc"); + adapterTarget.updateValidators(validators, 4); + console2.log(adapterTarget.listValidators()[0]); + assertEq(4, adapterTarget.listValidators().length); vm.stopPrank(); } @@ -439,10 +322,10 @@ contract ClusterConnectionTest is Test { uint256 pk = hexStringToUint256("ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80"); bytes32 hash = keccak256(RLPEncodeStruct.encodeCSMessage(message)); vm.startPrank(owner); - address[] memory validators = new address[](2); - validators[0] = address(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266); - validators[1] = address(0x976EA74026E726554dB657fA54763abd0C3a0aa9); - adapterTarget.setValidators(validators, 2); + bytes[] memory validators = new bytes[](2); + validators[0] = bytes(hex"048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5"); + validators[1] = bytes(hex"04bf6ee64a8d2fdc551ec8bb9ef862ef6b4bcb1805cdc520c3aa5866c0575fd3b514c5562c3caae7aec5cd6f144b57135c75b6f6cea059c3d08d1f39a9c227219d"); + adapterTarget.updateValidators(validators, 2); vm.stopPrank(); vm.startPrank(destination_relayer); vm.expectRevert("Not enough valid signatures passed"); @@ -463,7 +346,7 @@ contract ClusterConnectionTest is Test { srcNetwork.encodeString(), _connSn.encodeUint(), _msg.encodeBytes() - ); + ).encodeList(); return keccak256(rlp); } }