-
Notifications
You must be signed in to change notification settings - Fork 226
/
BaseBridgeValidators.sol
124 lines (96 loc) · 4.48 KB
/
BaseBridgeValidators.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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 = 100;
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, 2, 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 {
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;
}
}