feature: cache previous root, add _before hooks

buddies-main-deployment
James Prestwich 4 years ago
parent ff4962729c
commit 6a52a03bc4
No known key found for this signature in database
GPG Key ID: 75A7F5C06D747046
  1. 50
      solidity/contracts/Replica.sol

@ -5,7 +5,7 @@ import "@summa-tx/memview-sol/contracts/TypedMemView.sol";
import "./Common.sol";
import "./Merkle.sol";
contract Replica is Common {
abstract contract Replica is Common {
uint32 public immutable ownSLIP44;
uint256 public optimisticSeconds;
@ -31,6 +31,12 @@ contract Replica is Common {
_setFailed();
}
/// Hook for tasks
function _beforeConfirm() internal virtual;
/// Hook for tasks
function _beforeUpdate() internal virtual;
function update(
bytes32 _newRoot,
bytes32 _oldRoot,
@ -39,6 +45,8 @@ contract Replica is Common {
require(current == _oldRoot, "Not current update");
require(Common.checkSig(_newRoot, _oldRoot, _signature), "Bad sig");
_beforeUpdate();
confirmAt = block.timestamp + optimisticSeconds;
pending = _newRoot;
}
@ -46,6 +54,9 @@ contract Replica is Common {
function confirm() external notFailed {
require(confirmAt != 0, "No pending");
require(block.timestamp >= confirmAt, "Not yet");
_beforeConfirm();
current = pending;
delete pending;
delete confirmAt;
@ -57,6 +68,7 @@ contract ProcessingReplica is Replica, HasZeroHashes {
using TypedMemView for bytes;
using TypedMemView for bytes29;
bytes32 previous; // to smooth over witness invalidation
uint256 lastProcessed;
mapping(bytes32 => MessageStatus) public messages;
enum MessageStatus {None, Pending, Processed}
@ -75,11 +87,17 @@ contract ProcessingReplica is Replica, HasZeroHashes {
lastProcessed = _lastProcessed;
}
function process(bytes calldata _message) external {
bytes29 m = _message.ref(0);
function _beforeConfirm() internal override {
previous = current;
}
function _beforeUpdate() internal override {}
uint32 _destination = uint32(m.indexUint(36, 4));
uint32 _sequence = uint32(m.indexUint(72, 4));
function process(bytes calldata _message) public {
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(
@ -87,12 +105,12 @@ contract ProcessingReplica is Replica, HasZeroHashes {
"not pending"
);
lastProcessed = _sequence;
messages[keccak256(_message)] = MessageStatus.Processed;
messages[_m.keccak()] = MessageStatus.Processed;
// recipient address starts at the 52nd byte. 4 + 36 + 4 + 12
address recipient = m.indexAddress(52);
address recipient = _m.indexAddress(52);
// TODO: assembly this to avoid the clone?
bytes memory payload = m.slice(76, m.len() - 76, 0).clone();
bytes memory payload = _m.slice(76, _m.len() - 76, 0).clone();
// results intentionally ignored
recipient.call(payload);
@ -102,11 +120,23 @@ contract ProcessingReplica is Replica, HasZeroHashes {
bytes32 leaf,
bytes32[32] calldata proof,
uint256 index
) external returns (bool) {
if (MerkleLib.branchRoot(leaf, proof, index, zero_hashes) == current) {
) public returns (bool) {
bytes32 actual = MerkleLib.branchRoot(leaf, proof, index, zero_hashes);
if (actual == current || actual == previous) {
messages[leaf] = MessageStatus.Pending;
return true;
}
return false;
}
function proveAndProcess(
bytes32 leaf,
bytes32[32] calldata proof,
uint256 index,
bytes calldata message
) external {
require(prove(leaf, proof, index), "!prove");
process(message);
}
}

Loading…
Cancel
Save