Skip to content

Commit

Permalink
fix: change input validators to uncompressed public key
Browse files Browse the repository at this point in the history
  • Loading branch information
gcranju committed Nov 8, 2024
1 parent b133c29 commit 68c731e
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 37 deletions.
51 changes: 36 additions & 15 deletions contracts/evm/contracts/adapters/ClusterConnection.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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");
Expand All @@ -48,11 +51,12 @@ contract ClusterConnection is Initializable, IConnection {
return validators;
}

function updateValidators(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");
Expand Down Expand Up @@ -147,7 +151,7 @@ contract ClusterConnection is Initializable, IConnection {
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++;
}
Expand All @@ -156,6 +160,13 @@ contract ClusterConnection is Initializable, IConnection {
recvMessage(srcNetwork,_connSn,_msg);
}

function existsInValidators(address signer) internal 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) {
Expand All @@ -179,14 +190,9 @@ 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);
}


function recvMessage(
string memory srcNetwork,
uint256 _connSn,
Expand Down Expand Up @@ -264,10 +270,25 @@ contract ClusterConnection is Initializable, IConnection {

function getMessageHash(string memory srcNetwork, uint256 _connSn, bytes calldata _msg) internal pure returns (bytes32) {
bytes memory rlp = abi.encodePacked(
srcNetwork,
_connSn,
_msg
);
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)));
}

}
51 changes: 29 additions & 22 deletions contracts/evm/test/adapters/ClusterConnection.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,7 @@ contract ClusterConnectionTest is Test {
assert(source_relayer.balance == 10 ether);
}

function testRecvMessageWithMultiSignature() public {
function testRecvMessageWithMultiSignatures() public {
bytes memory data = bytes("test");
string memory iconDapp = NetworkAddress.networkAddress(
nidSource,
Expand All @@ -212,18 +212,19 @@ contract ClusterConnectionTest is Test {
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);
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);
Expand All @@ -246,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;
}

Expand Down Expand Up @@ -278,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.updateValidators(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();
}

Expand Down Expand Up @@ -315,9 +322,9 @@ 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);
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);
Expand All @@ -336,10 +343,10 @@ contract ClusterConnectionTest is Test {

function getMessageHash(string memory srcNetwork, uint256 _connSn, bytes memory _msg) internal pure returns (bytes32) {
bytes memory rlp = abi.encodePacked(
srcNetwork,
_connSn,
_msg
);
srcNetwork.encodeString(),
_connSn.encodeUint(),
_msg.encodeBytes()
).encodeList();
return keccak256(rlp);
}
}

0 comments on commit 68c731e

Please sign in to comment.