From 6bbe992ab4f1bd8330868c0937a41c8acb6408b0 Mon Sep 17 00:00:00 2001 From: DZariusz Date: Wed, 30 Oct 2019 13:40:57 +0100 Subject: [PATCH] feat(*): flexible duration of election phases Add option to change duration of the phases inside election. Restriction is, that total election duration must stay the same. Propose phase is more time consuming for validators, because data needs to be prepared. When we will be able to adjust propose/reveal ratio we can make more time for send a proposal. --- CHANGELOG.md | 1 + contracts/Chain.sol | 32 ++++++++++++++++++++------ contracts/ChainStorage.sol | 46 ++++++++++++++++++++++++++++++++------ 3 files changed, 65 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbc3bce..bc55e6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - when verifier proposing, `Chain` checks, if verifier is active instead of if it is only created. - split Chain contract into two separate contracts (storage and manager) +- Flexible duration of election phases ## [0.3.0] - 2018-12-13 ### Added: diff --git a/contracts/Chain.sol b/contracts/Chain.sol index 349da37..6522fb9 100644 --- a/contracts/Chain.sol +++ b/contracts/Chain.sol @@ -20,11 +20,11 @@ contract Chain is IChain, RegistrableWithSingleStorage, ReentrancyGuard, Ownable bytes32 constant NAME = "Chain"; modifier whenProposePhase() { - require(getCurrentElectionCycleBlock() < blocksPerPhase(), "we are not in propose phase"); + require(getCurrentElectionCycleBlock() < blocksPerPropose(), "we are not in propose phase"); _; } modifier whenRevealPhase() { - require(getCurrentElectionCycleBlock() >= blocksPerPhase(), "we are not in reveal phase"); + require(getCurrentElectionCycleBlock() >= blocksPerPropose(), "we are not in reveal phase"); _; } @@ -113,7 +113,7 @@ contract Chain is IChain, RegistrableWithSingleStorage, ReentrancyGuard, Ownable } function getBlockHeight() public view returns (uint256) { - return block.number.div(uint256(blocksPerPhase()) * 2); + return block.number.div(uint256(blocksPerElection())); } /// @dev this function needs to be called each time we successfully reveal a proposal @@ -214,6 +214,10 @@ contract Chain is IChain, RegistrableWithSingleStorage, ReentrancyGuard, Ownable _storage().setInitialBlockHeight(_shard, _blockHeight); } + function updatePhasesDurations(uint8 _blocksPerPropose, uint8 _blocksPerReveal) external onlyOwner { + _storage().updatePhasesDurations(_blocksPerPropose, _blocksPerReveal); + } + function updateMinimumStakingTokenPercentage(uint8 _minimumStakingTokenPercentage) public onlyOwner @@ -235,18 +239,32 @@ contract Chain is IChain, RegistrableWithSingleStorage, ReentrancyGuard, Ownable return _storage().minimumStakingTokenPercentage(); } - function blocksPerPhase() + function blocksPerPropose() + public + view + returns (uint8) { + return _storage().blocksPerPropose(); + } + + function blocksPerReveal() + public + view + returns (uint8) { + return _storage().blocksPerReveal(); + } + + function blocksPerElection() public view returns (uint8) { - return _storage().blocksPerPhase(); + return _storage().blocksPerPropose() + _storage().blocksPerReveal(); } function getCurrentElectionCycleBlock() public view returns (uint256) { - return block.number % (uint256(blocksPerPhase()) * 2); + return block.number % uint256(blocksPerElection()); } /// @return first block number (blockchain block) of current cycle @@ -261,7 +279,7 @@ contract Chain is IChain, RegistrableWithSingleStorage, ReentrancyGuard, Ownable public view returns (bool) { - return getCurrentElectionCycleBlock() < blocksPerPhase(); + return getCurrentElectionCycleBlock() < blocksPerPropose(); } function initialBlockHeights(uint256 _shard) diff --git a/contracts/ChainStorage.sol b/contracts/ChainStorage.sol index a69ab1a..19ba983 100644 --- a/contracts/ChainStorage.sol +++ b/contracts/ChainStorage.sol @@ -46,17 +46,28 @@ contract ChainStorage is StorageBase { bool public updateMinimumStakingTokenPercentageEnabled; - uint8 public blocksPerPhase; + uint8 public blocksPerPropose; + uint8 public blocksPerReveal; uint8 public minimumStakingTokenPercentage; - event LogChainConfig(uint8 blocksPerPhase, uint8 requirePercentOfTokens, bool updateMinimumStakingTokenPercentageEnabled); + event LogChainConfig( + uint8 blocksPerPropose, + uint8 blocksPerReveal, + uint8 requirePercentOfTokens, + bool updateMinimumStakingTokenPercentageEnabled + ); - constructor(uint8 _blocksPerPhase, + constructor( + uint8 _blocksPerPropose, + uint8 _blocksPerReveal, uint8 _minimumStakingTokenPercentage, bool _updateMinimumStakingTokenPercentageEnabled) public { - require(_blocksPerPhase > 0, "_blocksPerPhase can't be empty"); - blocksPerPhase = _blocksPerPhase; + require(_blocksPerPropose > 0, "_blocksPerPhase can't be empty"); + require(_blocksPerReveal > 0, "_blocksPerReveal can't be empty"); + + blocksPerPropose = _blocksPerPropose; + blocksPerReveal = _blocksPerReveal; require(_minimumStakingTokenPercentage > 0, "_minimumStakingTokenPercentage can't be empty"); require(_minimumStakingTokenPercentage <= 100, "_minimumStakingTokenPercentage can't be over 100%"); @@ -64,7 +75,12 @@ contract ChainStorage is StorageBase { updateMinimumStakingTokenPercentageEnabled = _updateMinimumStakingTokenPercentageEnabled; - emit LogChainConfig(_blocksPerPhase, _minimumStakingTokenPercentage, _updateMinimumStakingTokenPercentageEnabled); + emit LogChainConfig( + _blocksPerPropose, + _blocksPerReveal, + _minimumStakingTokenPercentage, + _updateMinimumStakingTokenPercentageEnabled + ); } function getInitialBlockHeight(uint256 _shard) public view returns (uint256) { @@ -160,6 +176,22 @@ contract ChainStorage is StorageBase { return true; } + function updatePhasesDurations(uint8 _blocksPerPropose, uint8 _blocksPerReveal) + external + onlyFromStorageOwner + returns (bool) { + require(_blocksPerPropose > 0, "_blocksPerPropose can't be empty"); + require(_blocksPerReveal > 0, "_blocksPerReveal can't be empty"); + require(blocksPerPropose + blocksPerReveal == _blocksPerPropose + _blocksPerReveal, "election duration must be fixed"); + + blocksPerPropose = _blocksPerPropose; + blocksPerReveal = _blocksPerReveal; + + emit LogChainConfig(blocksPerPropose, blocksPerReveal, minimumStakingTokenPercentage, true); + + return true; + } + function updateMinimumStakingTokenPercentage(uint8 _minimumStakingTokenPercentage) external onlyFromStorageOwner @@ -170,7 +202,7 @@ contract ChainStorage is StorageBase { require(_minimumStakingTokenPercentage <= 100, "_minimumStakingTokenPercentage can't be over 100%"); minimumStakingTokenPercentage = _minimumStakingTokenPercentage; - emit LogChainConfig(blocksPerPhase, _minimumStakingTokenPercentage, true); + emit LogChainConfig(blocksPerPropose, blocksPerReveal, _minimumStakingTokenPercentage, true); return true; }