Skip to content

Commit

Permalink
Added an update da
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanSea committed Dec 3, 2024
1 parent 4a4a720 commit 03c2037
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 1 deletion.
41 changes: 40 additions & 1 deletion contracts/core/src/xchain/OmniPortal.sol
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,11 @@ contract OmniPortal is
xheader.sourceChainId == omniCChainId && xmsg_.sender == CChainSender
&& xmsg_.destChainId == BroadcastChainId
&& xmsg_.shardId == ConfLevel.toBroadcastShard(ConfLevel.Finalized)
&& (selector == this.addValidatorSet.selector || selector == this.setNetwork.selector),
&& (
selector == this.addValidatorSet.selector ||
selector == this.setNetwork.selector ||
selector == this.updateValidatorSet.selector
),
"OmniPortal: invalid syscall"
);
} else {
Expand Down Expand Up @@ -416,6 +420,41 @@ contract OmniPortal is
emit ValidatorSetAdded(valSetId);
}

/**
* @notice Update an existing validator set.
* @dev Only callable via xcall from Omni's consensus chain
* @param valSetId Validator set id
* @param validators Validator set
*/
function updateValidatorSet(uint64 valSetId, XTypes.Validator[] calldata validators) external {
require(msg.sender == address(this), "OmniPortal: only self");
require(_xmsg.sourceChainId == omniCChainId, "OmniPortal: only cchain");
require(_xmsg.sender == CChainSender, "OmniPortal: only cchain sender");
_updateValidatorSet(valSetId, validators);
}

/**
* @notice Add a new validator set.
* @param valSetId Validator set id
* @param validators Validator set
*/
function _updateValidatorSet(uint64 valSetId, XTypes.Validator[] calldata validators) internal {
uint256 numVals = validators.length;
require(numVals > 0, "OmniPortal: no validators");

XTypes.Validator memory val; int64 powerDelta;
for (uint256 i; i < numVals; i++) {
val = validators[i];

require(val.addr != address(0), "OmniPortal: no zero validator");

powerDelta += int64(val.power) - int64(valSet[valSetId][val.addr]);
valSet[valSetId][val.addr] = val.power;
}

valSetTotalPower[valSetId] = uint64(int64(valSetTotalPower[valSetId]) + powerDelta);
}

/**
* @notice Set the network of supported chains & shards
* @dev Only callable via xcall from Omni's consensus chain
Expand Down
57 changes: 57 additions & 0 deletions contracts/core/test/xchain/OmniPortal_sys.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,63 @@ contract OmniPortal_sys_Test is OmniPortalFixtures {
assertEq(portal.valSetTotalPower(2), power * maxVals);
}

function test_UpdateValidatorSet() public {
/// ADD
address val1 = address(5551);
address val2 = address(5552);
address val3 = address(5553);

uint64 power1 = 100;
uint64 power2 = 200;
uint64 power3 = 300;

XTypes.Validator[] memory validators = new XTypes.Validator[](3);
validators[0] = XTypes.Validator({ addr: val1, power: power1 });
validators[1] = XTypes.Validator({ addr: val2, power: power2 });
validators[2] = XTypes.Validator({ addr: val3, power: power3 });

XTypes.BlockHeader memory xheader = xsubgen.makeXHeader(omniCChainID, ConfLevel.Finalized);
XTypes.Msg[] memory msgs = new XTypes.Msg[](1);
msgs[0] = _sysXMsg(abi.encodeCall(OmniPortal.addValidatorSet, (2, validators)));

XTypes.Submission memory xsub =
xsubgen.makeXSub(1, xheader, msgs, xsubgen.msgFlagsForDest(msgs, broadcastChainId));

vm.chainId(1);
portal.xsubmit(xsub);

assertEq(portal.valSetTotalPower(2), power1 + power2 + power3);
assertEq(portal.valSet(2, val1), power1);
assertEq(portal.valSet(2, val2), power2);
assertEq(portal.valSet(2, val3), power3);

// UPDATE
address val4 = address(5554);

power1 = 300;
power2 = 100;
uint64 power4 = 200;

validators = new XTypes.Validator[](3);
validators[0] = XTypes.Validator({ addr: val1, power: power1 });
validators[1] = XTypes.Validator({ addr: val2, power: power2 });
validators[2] = XTypes.Validator({ addr: val4, power: power4 });

xheader.offset++; // note: this isn't required but let's assume it's a new xblock
msgs = new XTypes.Msg[](1);
msgs[0] = _sysXMsg(abi.encodeCall(OmniPortal.updateValidatorSet, (2, validators)), 3);

xsub = xsubgen.makeXSub(1, xheader, msgs, xsubgen.msgFlagsForDest(msgs, broadcastChainId));

portal.xsubmit(xsub);

assertEq(portal.valSetTotalPower(2), power1 + power2 + power3 + power4);
assertEq(portal.valSet(2, val1), power1);
assertEq(portal.valSet(2, val2), power2);
assertEq(portal.valSet(2, val3), power3);
assertEq(portal.valSet(2, val4), power4);
}

/// @dev Test syscalls (xcalls to VirtualPortalAddress) are properly authorized
function test_syscall_auth() public {
uint64 destChainId = 1;
Expand Down

0 comments on commit 03c2037

Please sign in to comment.