Skip to content

Commit

Permalink
Extensible proof structure for periods (#125)
Browse files Browse the repository at this point in the history
* fix tests for new proofs in lib

* add period root test to poa operator

* add period root test to poa operator

* adjusted reward function to extensible proof

* syntax

* making things nice

* fix tests for new proofs in lib

* add period root test to poa operator

* add period root test to poa operator

* adjusted reward function to extensible proof

* syntax

* making things nice

* Update leap-core dependancy

* made PoS inherit from PoA

* Fix tests to work with new leap-core

* rename operator

* rename operator
  • Loading branch information
johannbarbie authored and eezcjkr committed Jan 25, 2019
1 parent d97b62f commit ba1e768
Show file tree
Hide file tree
Showing 13 changed files with 185 additions and 198 deletions.
2 changes: 1 addition & 1 deletion contracts/Bridge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ contract Bridge is Adminable {
public onlyOperator returns (uint256 newHeight) {

require(periods[_prevHash].parent > 0, "Parent node should exist");
require(periods[_root].height == 0, "Given root shouldn't be submitted yet");
require(periods[_root].height == 0, "Trying to submit the same root twice");

// calculate height
newHeight = periods[_prevHash].height + 1;
Expand Down
59 changes: 37 additions & 22 deletions contracts/PoaOperator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
pragma solidity 0.5.2;

import "./Adminable.sol";
import "./Vault.sol";
import "./Bridge.sol";

contract PoaOperator is Adminable {
Expand Down Expand Up @@ -49,13 +50,18 @@ contract PoaOperator is Adminable {

struct Slot {
uint32 eventCounter;
address owner;
uint64 stake;
address signer;
bytes32 tendermint;
uint32 activationEpoch;
address newOwner;
uint64 newStake;
address newSigner;
bytes32 newTendermint;
}

Vault public vault;
Bridge public bridge;

uint256 public epochLength; // length of epoch in periods (32 blocks)
Expand All @@ -64,7 +70,9 @@ contract PoaOperator is Adminable {

mapping(uint256 => Slot) public slots;

function initialize(Bridge _bridge, uint256 _epochLength) public initializer {

function initialize(Bridge _bridge, Vault _vault, uint256 _epochLength) public initializer {
vault = _vault;
bridge = _bridge;
epochLength = _epochLength;
emit EpochLength(epochLength);
Expand All @@ -81,6 +89,7 @@ contract PoaOperator is Adminable {

// taking empty slot
if (slot.signer == address(0)) {
slot.owner = _signerAddr;
slot.signer = _signerAddr;
slot.tendermint = _tenderAddr;
slot.activationEpoch = 0;
Expand Down Expand Up @@ -122,6 +131,7 @@ contract PoaOperator is Adminable {
lastCompleteEpoch + 1
);
}
slot.owner = slot.newOwner;
slot.signer = slot.newSigner;
slot.tendermint = slot.newTendermint;
slot.activationEpoch = 0;
Expand All @@ -139,7 +149,7 @@ contract PoaOperator is Adminable {
}
}

function submitPeriod(uint256 _slotId, bytes32 _prevHash, bytes32 _root) public {
function submitPeriod(uint256 _slotId, bytes32 _prevHash, bytes32 _blocksRoot) public {
require(_slotId < epochLength, "Incorrect slotId");
Slot storage slot = slots[_slotId];
require(slot.signer == msg.sender, "not submitted by signerAddr");
Expand All @@ -149,31 +159,36 @@ contract PoaOperator is Adminable {
require(lastCompleteEpoch + 2 < slot.activationEpoch, "slot not active");
}

uint256 newHeight = bridge.submitPeriod(_prevHash, _root);
// check if epoch completed
if (newHeight >= lastEpochBlockHeight + epochLength) {
lastCompleteEpoch++;
lastEpochBlockHeight = newHeight;
emit Epoch(lastCompleteEpoch);
// validator root
bytes32 hashRoot = bytes32(_slotId << 160 | uint160(slot.owner));
assembly {
mstore(0, hashRoot)
mstore(0x20, 0x0000000000000000000000000000000000000000)
hashRoot := keccak256(0, 0x40)
}
}

function submitPeriodForReward(uint256 _slotId, bytes32 _prevHash, bytes32 _blocksRoot) public {
require(_slotId < epochLength, "Incorrect slotId");
Slot storage slot = slots[_slotId];
require(slot.signer == msg.sender, "not submitted by signerAddr");
// This is here so that I can submit in the same epoch I auction/logout but not after
if (slot.activationEpoch > 0) {
// if slot not active, prevent submission
require(lastCompleteEpoch + 2 < slot.activationEpoch, "slot not active");
// cas root
assembly {
mstore(0, 0x0000000000000000000000000000000000000000)
mstore(0x20, hashRoot)
hashRoot := keccak256(0, 0x40)
}
bytes32 periodRood = bytes32(_slotId << 160 | uint160(msg.sender));

// consensus root
bytes32 consensusRoot;
assembly {
mstore(0, _blocksRoot)
mstore(0x20, periodRood)
periodRood := keccak256(0, 0x40)
mstore(0x20, 0x0000000000000000000000000000000000000000)
consensusRoot := keccak256(0, 0x40)
}
uint256 newHeight = bridge.submitPeriod(_prevHash, periodRood);

// period root
assembly {
mstore(0, consensusRoot)
mstore(0x20, hashRoot)
hashRoot := keccak256(0, 0x40)
}

uint256 newHeight = bridge.submitPeriod(_prevHash, hashRoot);
// check if epoch completed
if (newHeight >= lastEpochBlockHeight + epochLength) {
lastCompleteEpoch++;
Expand Down
93 changes: 2 additions & 91 deletions contracts/POSoperator.sol → contracts/PosOperator.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,81 +9,11 @@
pragma solidity 0.5.2;

import "../node_modules/openzeppelin-solidity/contracts/math/SafeMath.sol";
import "./Adminable.sol";
import "./Vault.sol";
import "./Bridge.sol";
import "./PoaOperator.sol";

contract POSoperator is Adminable {
contract PosOperator is PoaOperator {
using SafeMath for uint256;

event Epoch(uint256 epoch);
event EpochLength(uint256 epochLength);

event ValidatorJoin(
address indexed signerAddr,
uint256 indexed slotId,
bytes32 indexed tenderAddr,
uint256 eventCounter,
uint256 epoch
);

event ValidatorLogout(
address indexed signerAddr,
uint256 indexed slotId,
bytes32 indexed tenderAddr,
address newSigner,
uint256 eventCounter,
uint256 epoch
);

event ValidatorLeave(
address indexed signerAddr,
uint256 indexed slotId,
bytes32 indexed tenderAddr,
uint256 epoch
);

event ValidatorUpdate(
address indexed signerAddr,
uint256 indexed slotId,
bytes32 indexed tenderAddr,
uint256 eventCounter
);

struct Slot {
uint32 eventCounter;
address owner;
uint64 stake;
address signer;
bytes32 tendermint;
uint32 activationEpoch;
address newOwner;
uint64 newStake;
address newSigner;
bytes32 newTendermint;
}

Vault public vault;
Bridge public bridge;

uint256 public epochLength; // length of epoch in periods (32 blocks)
uint256 public lastCompleteEpoch; // height at which last epoch was completed
uint256 public lastEpochBlockHeight;

mapping(uint256 => Slot) public slots;

function initialize(Bridge _bridge, Vault _vault, uint256 _epochLength) public initializer {
vault = _vault;
bridge = _bridge;
epochLength = _epochLength;
emit EpochLength(epochLength);
}

function setEpochLength(uint256 _epochLength) public ifAdmin {
epochLength = _epochLength;
emit EpochLength(epochLength);
}

// solium-disable security/no-tx-origin
// TODO: consider not to use tx.origin
function bet(
Expand Down Expand Up @@ -199,23 +129,4 @@ contract POSoperator is Adminable {
);
}
}

function submitPeriod(uint256 _slotId, bytes32 _prevHash, bytes32 _root) public {
require(_slotId < epochLength, "Incorrect slotId");
Slot storage slot = slots[_slotId];
require(slot.signer == msg.sender);
// This is here so that I can submit in the same epoch I auction/logout but not after
if (slot.activationEpoch > 0) {
// if slot not active, prevent submission
require(lastCompleteEpoch.add(2) < slot.activationEpoch);
}

uint256 newHeight = bridge.submitPeriod(_prevHash, _root);
// check if epoch completed
if (newHeight >= lastEpochBlockHeight.add(epochLength)) {
lastCompleteEpoch++;
lastEpochBlockHeight = newHeight;
emit Epoch(lastCompleteEpoch);
}
}
}
35 changes: 30 additions & 5 deletions contracts/SwapRegistry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,14 +45,39 @@ contract SwapRegistry is Adminable {
poaReward = _poaReward;
}

function claim(uint256 _slotId, bytes32[] memory _roots) public {
function claim(
uint256 _slotId,
bytes32[] memory _consensusRoots,
bytes32[] memory _cas,
bytes32[] memory _validatorData,
bytes32[] memory _rest
) public {
uint256 maxHeight = slotToHeight[_slotId];
uint32 claimCount = 0;
for (uint256 i = 0; i < _roots.length; i += 2) {
require(_slotId == uint256(_roots[i+1] >> 160), "unexpected slotId");
require(msg.sender == address(uint160(uint256(_roots[i+1]))), "unexpected claimant");
for (uint256 i = 0; i < _consensusRoots.length; i += 1) {
require(_slotId == uint256(_validatorData[i] >> 160), "unexpected slotId");
require(msg.sender == address(uint160(uint256(_validatorData[i]))), "unexpected claimant");
uint256 height;
(,height ,,) = bridge.periods(keccak256(abi.encodePacked(_roots[i], _roots[i + 1])));
bytes32 left = _validatorData[i];
bytes32 right = _rest[i];
assembly {
mstore(0, left)
mstore(0x20, right)
right := keccak256(0, 0x40)
}
left = _cas[i];
assembly {
mstore(0, left)
mstore(0x20, right)
right := keccak256(0, 0x40)
}
left = _consensusRoots[i];
assembly {
mstore(0, left)
mstore(0x20, right)
right := keccak256(0, 0x40)
}
(,height ,,) = bridge.periods(right);
require(height > maxHeight, "unorderly claim");
maxHeight = height;
claimCount += 1;
Expand Down
8 changes: 4 additions & 4 deletions contracts/proxies/OperatorProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
pragma solidity 0.5.2;

import "./AdminableProxy.sol";
import "../POSoperator.sol";
import "../PosOperator.sol";

/**
* @title OperatorProxy
* @dev Proxy for POSoperator/PoaOperator contract upgradeability. Should be used to
* communicate with POSoperator/PoaOperator contract
* @dev Proxy for PosOperator/PoaOperator contract upgradeability. Should be used to
* communicate with PosOperator/PoaOperator contract
*/
contract OperatorProxy is AdminableProxy {

constructor(POSoperator _implementation, bytes memory _data)
constructor(PosOperator _implementation, bytes memory _data)
AdminableProxy(address(_implementation), _data) public payable {
}

Expand Down
2 changes: 1 addition & 1 deletion migrations/3_deploy_plasma.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ module.exports = (deployer, network, accounts) => {
const exitHandlerProxy = await deployer.deploy(ExitHandlerProxy, exitHandlerCont.address, data, { from: admin });

const operatorCont = await deployer.deploy(PoaOperator);
data = await operatorCont.contract.methods.initialize(bridgeProxy.address, DEFAULT_EPOCH_LENGTH).encodeABI();
data = await operatorCont.contract.methods.initialize(bridgeProxy.address, exitHandlerProxy.address, DEFAULT_EPOCH_LENGTH).encodeABI();
const operatorProxy = await deployer.deploy(OperatorProxy, operatorCont.address, data, { from: admin });

const bridge = await Bridge.at(bridgeProxy.address);
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"babel-preset-env": "^1.6.1",
"babel-register": "^6.26.0",
"bn.js": "^4.11.8",
"jsbi": "^2.0.5",
"chai": "^4.1.2",
"chai-as-promised": "^7.1.1",
"dotenv": "^6.2.0",
Expand All @@ -44,7 +45,7 @@
"ethereumjs-util": "^6.0.0",
"ganache-cli": "^6.2.3",
"husky": "^1.2.0",
"leap-core": "^0.20.5",
"leap-core": "^0.21.1",
"solium": "^1.1.8",
"truffle": "^5.0.0"
},
Expand Down
8 changes: 7 additions & 1 deletion test/helpers/submitNewPeriodWithTx.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,13 @@ export default async (txs, bridge, opts) => {
// create new period
const prevPeriodRoot = await bridge.tipHash();
const period = new Period(prevPeriodRoot, [block]);
const newPeriodRoot = period.merkleRoot();

let { slotId } = opts;
let { signerAddr } = opts;
slotId = (slotId) || 0;
signerAddr = (signerAddr) || '0x0000000000000000000000000000000000000000';
period.setValidatorData(slotId, signerAddr);
const newPeriodRoot = period.proof(txs[0])[0];

await bridge.submitPeriod(prevPeriodRoot, newPeriodRoot, opts).should.be.fulfilled;
return period;
Expand Down
Loading

0 comments on commit ba1e768

Please sign in to comment.