Skip to content
This repository has been archived by the owner on Jan 11, 2024. It is now read-only.

Commit

Permalink
feat: add apply msg
Browse files Browse the repository at this point in the history
  • Loading branch information
arrusev committed Mar 31, 2023
1 parent 04ee542 commit d307b4b
Show file tree
Hide file tree
Showing 3 changed files with 87 additions and 3 deletions.
69 changes: 66 additions & 3 deletions src/Gateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ contract Gateway is IGateway, ReentrancyGuard {
using FilAddress for address payable;
using AccountHelper for address;
using SubnetIDHelper for SubnetID;
using CrossMsgHelper for CrossMsg;
using CheckpointHelper for Checkpoint;
using CheckpointMappingHelper for mapping(int64 => Checkpoint);
using StorableMsgHelper for StorableMsg;
Expand Down Expand Up @@ -90,6 +91,8 @@ contract Gateway is IGateway, ReentrancyGuard {
/// @notice fee amount charged per cross message
uint256 public crossMsgFee;

mapping(uint64 => bytes4) public methodSelectors;

/// epoch => SubnetID => [childIndex, exists(0 - no, 1 - yes)]
mapping(int64 => mapping(bytes32 => uint256[2])) internal children;
/// epoch => SubnetID => check => exists
Expand Down Expand Up @@ -119,6 +122,14 @@ contract Gateway is IGateway, ReentrancyGuard {
: DEFAULT_CHECKPOINT_PERIOD;
appliedBottomUpNonce = MAX_NONCE;
crossMsgFee = msgFee;

methodSelectors[2] = IGateway.register.selector;
methodSelectors[3] = IGateway.addStake.selector;
methodSelectors[4] = IGateway.releaseStake.selector;
methodSelectors[5] = IGateway.kill.selector;
methodSelectors[6] = IGateway.commitChildCheck.selector;
methodSelectors[9] = IGateway.sendCross.selector;
methodSelectors[10] = IGateway.applyMsg.selector;
}

function getCrossMsgsLength(
Expand Down Expand Up @@ -387,6 +398,57 @@ contract Gateway is IGateway, ReentrancyGuard {
payable(down.getActor()).sendValue(topDownFee);
}

function applyMsg(
CrossMsg calldata crossMsg
) external returns (bool success) {
require(
crossMsg.message.to.rawAddress != address(0),
"error getting raw address from msg"
);
require(
crossMsg.message.to.subnetId.route.length > 0,
"error getting subnet from msg"
);
require(
crossMsg.message.to.subnetId.equals(networkName),
"the message being applied doesn't belong to this subnet"
);
require(
methodSelectors[crossMsg.message.method] != bytes4(0),
"method not found"
);

if (crossMsg.message.applyType(networkName) == IPCMsgType.BottomUp) {
_bottomUpStateTransition(crossMsg.message);
} else {
require(
appliedTopDownNonce == crossMsg.message.nonce,
"the top-down message being applied doesn't hold the subsequent nonce"
);
appliedTopDownNonce += 1;
}

// execute the message
success = crossMsg.execute(methodSelectors[crossMsg.message.method]);

//todo postbox
}

function _bottomUpStateTransition(
StorableMsg calldata storableMsg
) internal {
if (appliedBottomUpNonce == 2 ** 64 - 1 && storableMsg.nonce == 0) {
appliedBottomUpNonce = 0;
} else if (appliedBottomUpNonce + 1 == storableMsg.nonce) {
appliedBottomUpNonce += 1;
}

require(
appliedBottomUpNonce == storableMsg.nonce,
"the bottom-up message being applied doesn't hold the subsequent nonce"
);
}

function _commitCrossMessage(
CrossMsg memory crossMessage
) internal returns (bool, uint256) {
Expand All @@ -396,14 +458,15 @@ contract Gateway is IGateway, ReentrancyGuard {
!crossMessage.message.to.subnetId.equals(networkName),
"should already be committed"
);

SubnetID memory from = crossMessage.message.from.subnetId;
IPCMsgType applyType = crossMessage.message.applyType(networkName);
bool shouldCommitBottomUp;

if (applyType == IPCMsgType.BottomUp) {
require(from.route.length > 0, "error getting subnet from msg");
shouldCommitBottomUp = to.commonParent(from).equals(networkName) == false;
shouldCommitBottomUp =
to.commonParent(from).equals(networkName) == false;
}

if (shouldCommitBottomUp) {
Expand All @@ -413,7 +476,7 @@ contract Gateway is IGateway, ReentrancyGuard {

appliedTopDownNonce += applyType == IPCMsgType.TopDown ? 1 : 0;
_commitTopDownMsg(crossMessage);

return (false, crossMsgFee);
}

Expand Down
9 changes: 9 additions & 0 deletions src/interfaces/IGateway.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,13 @@ interface IGateway {
external
payable;

/// ApplyMessage triggers the execution of a cross-subnet message validated through the consensus.
///
/// This function can only be triggered using `ApplyImplicitMessage`, and the source needs to
/// be the SystemActor. Cross messages are applied similarly to how rewards are applied once
/// a block has been validated. This function:
/// - Determines the type of cross-message.
/// - Performs the corresponding state changes.
/// - And updated the latest nonce applied for future checks.
function applyMsg(CrossMsg calldata crossMsg) external returns (bool);
}
12 changes: 12 additions & 0 deletions src/lib/CrossMsgHelper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,16 @@ library CrossMsgHelper {
) internal pure returns (bytes32) {
return keccak256(abi.encode(crossMsgs));
}

function execute(
CrossMsg calldata crossMsg,
bytes4 methodSelector
) public returns (bool success) {
bytes memory params = crossMsg.wrapped
? abi.encode(crossMsg)
: crossMsg.message.params;
(success, ) = crossMsg.message.to.rawAddress.call{
value: crossMsg.message.value
}(abi.encodeWithSelector(methodSelector, params));
}
}

0 comments on commit d307b4b

Please sign in to comment.