The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/solidity/contracts/Replica.sol

113 lines
3.1 KiB

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.6.11;
import "@summa-tx/memview-sol/contracts/TypedMemView.sol";
import "./Common.sol";
import "./Merkle.sol";
contract Replica is Common {
uint32 public immutable ownSLIP44;
uint256 public optimisticSeconds;
bytes32 current;
bytes32 pending;
uint256 confirmAt;
event DoubleUpdate();
constructor(
uint32 _originSLIP44,
uint32 _ownSLIP44,
address _updater,
uint256 _optimisticSeconds,
bytes32 _start
) Common(_originSLIP44, _updater) {
ownSLIP44 = _ownSLIP44;
optimisticSeconds = _optimisticSeconds;
current = _start;
}
function fail() internal override {
_setFailed();
}
function update(
bytes32 _newRoot,
bytes32 _oldRoot,
bytes memory _signature
) external notFailed {
require(current == _oldRoot, "Not current update");
require(Common.checkSig(_newRoot, _oldRoot, _signature), "Bad sig");
confirmAt = block.timestamp + optimisticSeconds;
pending = _newRoot;
}
function confirm() external notFailed {
require(confirmAt != 0, "No pending");
require(block.timestamp >= confirmAt, "Not yet");
current = pending;
delete pending;
delete confirmAt;
}
}
contract ProcessingReplica is Replica, HasZeroHashes {
using MerkleLib for MerkleLib.Tree;
using TypedMemView for bytes;
using TypedMemView for bytes29;
uint256 lastProcessed;
mapping(bytes32 => MessageStatus) public messages;
enum MessageStatus {None, Pending, Processed}
constructor(
uint32 _originSLIP44,
uint32 _ownSLIP44,
address _updater,
uint256 _optimisticSeconds,
bytes32 _start,
uint256 _lastProcessed
)
HasZeroHashes()
Replica(_originSLIP44, _ownSLIP44, _updater, _optimisticSeconds, _start)
{
lastProcessed = _lastProcessed;
}
function process(bytes calldata _message) external {
bytes29 m = _message.ref(0);
uint32 _destination = uint32(m.indexUint(36, 4));
uint32 _sequence = uint32(m.indexUint(72, 4));
require(_destination == ownSLIP44, "other destination");
require(_sequence == lastProcessed + 1, "out of sequence");
require(
messages[keccak256(_message)] == MessageStatus.Pending,
"not pending"
);
lastProcessed = _sequence;
messages[keccak256(_message)] = MessageStatus.Processed;
// recipient address starts at the 52nd byte. 4 + 36 + 4 + 12
address recipient = m.indexAddress(52);
// TODO: assembly this to avoid the clone?
bytes memory payload = m.slice(76, m.len() - 76, 0).clone();
// results intentionally ignored
recipient.call(payload);
}
function prove(
bytes32 leaf,
bytes32[32] calldata proof,
uint256 index
) external returns (bool) {
if (MerkleLib.branchRoot(leaf, proof, index, zero_hashes) == current) {
messages[leaf] = MessageStatus.Pending;
return true;
}
return false;
}
}