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; }