126 lines
4.5 KiB
Solidity
126 lines
4.5 KiB
Solidity
pragma solidity 0.4.24;
|
|
|
|
import "./Ownable.sol";
|
|
import "openzeppelin-solidity/contracts/math/SafeMath.sol";
|
|
import "./InitializableBridge.sol";
|
|
|
|
contract BaseBridgeValidators is InitializableBridge, Ownable {
|
|
using SafeMath for uint256;
|
|
|
|
address public constant F_ADDR = 0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF;
|
|
uint256 internal constant MAX_VALIDATORS = 50;
|
|
bytes32 internal constant REQUIRED_SIGNATURES = 0xd18ea17c351d6834a0e568067fb71804d2a588d5e26d60f792b1c724b1bd53b1; // keccak256(abi.encodePacked("requiredSignatures"))
|
|
bytes32 internal constant VALIDATOR_COUNT = 0x8656d603d9f985c3483946a92789d52202f49736384ba131cb92f62c4c1aa082; // keccak256(abi.encodePacked("validatorCount"))
|
|
|
|
event ValidatorAdded(address indexed validator);
|
|
event ValidatorRemoved(address indexed validator);
|
|
event RequiredSignaturesChanged(uint256 requiredSignatures);
|
|
|
|
function setRequiredSignatures(uint256 _requiredSignatures) external onlyOwner {
|
|
require(validatorCount() >= _requiredSignatures);
|
|
require(_requiredSignatures != 0);
|
|
uintStorage[REQUIRED_SIGNATURES] = _requiredSignatures;
|
|
emit RequiredSignaturesChanged(_requiredSignatures);
|
|
}
|
|
|
|
function getBridgeValidatorsInterfacesVersion() external pure returns (uint64 major, uint64 minor, uint64 patch) {
|
|
return (2, 3, 0);
|
|
}
|
|
|
|
function validatorList() external view returns (address[]) {
|
|
address[] memory list = new address[](validatorCount());
|
|
uint256 counter = 0;
|
|
address nextValidator = getNextValidator(F_ADDR);
|
|
require(nextValidator != address(0));
|
|
|
|
while (nextValidator != F_ADDR) {
|
|
list[counter] = nextValidator;
|
|
nextValidator = getNextValidator(nextValidator);
|
|
counter++;
|
|
|
|
require(nextValidator != address(0));
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
function _addValidator(address _validator) internal {
|
|
require(_validator != address(0) && _validator != F_ADDR);
|
|
require(!isValidator(_validator));
|
|
|
|
address firstValidator = getNextValidator(F_ADDR);
|
|
require(firstValidator != address(0));
|
|
setNextValidator(_validator, firstValidator);
|
|
setNextValidator(F_ADDR, _validator);
|
|
setValidatorCount(validatorCount().add(1));
|
|
}
|
|
|
|
function _removeValidator(address _validator) internal {
|
|
require(validatorCount() > requiredSignatures());
|
|
require(isValidator(_validator));
|
|
address validatorsNext = getNextValidator(_validator);
|
|
address index = F_ADDR;
|
|
address next = getNextValidator(index);
|
|
require(next != address(0));
|
|
|
|
while (next != _validator) {
|
|
index = next;
|
|
next = getNextValidator(index);
|
|
|
|
require(next != F_ADDR && next != address(0));
|
|
}
|
|
|
|
setNextValidator(index, validatorsNext);
|
|
deleteItemFromAddressStorage("validatorsList", _validator);
|
|
setValidatorCount(validatorCount().sub(1));
|
|
}
|
|
|
|
function requiredSignatures() public view returns (uint256) {
|
|
return uintStorage[REQUIRED_SIGNATURES];
|
|
}
|
|
|
|
function validatorCount() public view returns (uint256) {
|
|
return uintStorage[VALIDATOR_COUNT];
|
|
}
|
|
|
|
function isValidator(address _validator) public view returns (bool) {
|
|
return _validator != F_ADDR && getNextValidator(_validator) != address(0);
|
|
}
|
|
|
|
function getNextValidator(address _address) public view returns (address) {
|
|
return addressStorage[keccak256(abi.encodePacked("validatorsList", _address))];
|
|
}
|
|
|
|
function deleteItemFromAddressStorage(string _mapName, address _address) internal {
|
|
delete addressStorage[keccak256(abi.encodePacked(_mapName, _address))];
|
|
}
|
|
|
|
function setValidatorCount(uint256 _validatorCount) internal {
|
|
require(_validatorCount <= MAX_VALIDATORS);
|
|
uintStorage[VALIDATOR_COUNT] = _validatorCount;
|
|
}
|
|
|
|
function setNextValidator(address _prevValidator, address _validator) internal {
|
|
addressStorage[keccak256(abi.encodePacked("validatorsList", _prevValidator))] = _validator;
|
|
}
|
|
|
|
function isValidatorDuty(address _validator) external view returns (bool) {
|
|
uint256 counter = 0;
|
|
address next = getNextValidator(F_ADDR);
|
|
require(next != address(0));
|
|
|
|
while (next != F_ADDR) {
|
|
if (next == _validator) {
|
|
return (block.number % validatorCount() == counter);
|
|
}
|
|
|
|
next = getNextValidator(next);
|
|
counter++;
|
|
|
|
require(next != address(0));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|