120 lines
4.6 KiB
Solidity
120 lines
4.6 KiB
Solidity
|
// Source for the test AuRa validator set contract. DO NOT USE IN PRODUCTION.
|
||
|
//
|
||
|
// Contains POSDAO features. The full POSDAO ValidatorSet contract production code is available at
|
||
|
// https://github.com/poanetwork/posdao-contracts/blob/master/contracts/ValidatorSetAuRa.sol
|
||
|
//
|
||
|
// The bytecode of this contract is included in `validator_contract.json` as the
|
||
|
// constructor of address `0x0000..0005`.
|
||
|
|
||
|
pragma solidity ^0.5.0;
|
||
|
|
||
|
contract TestValidatorSet {
|
||
|
|
||
|
address public disliked; // contains the address of validator reported by `reportBenign`
|
||
|
mapping(address => bool) public isValidatorBanned; // if the validator is banned by `reportMalicious`
|
||
|
|
||
|
// The initial set of validators
|
||
|
address[] public validators = [
|
||
|
0x7d577a597B2742b498Cb5Cf0C26cDCD726d39E6e,
|
||
|
0x82A978B3f5962A5b0957d9ee9eEf472EE55B42F1
|
||
|
];
|
||
|
|
||
|
// The mappings used by POSDAO features testing (see `reportMalicious` and `shouldValidatorReport` functions below)
|
||
|
mapping(address => mapping(uint256 => address[])) private _maliceReportedForBlock;
|
||
|
mapping(address => mapping(uint256 => mapping(address => bool))) private _maliceReportedForBlockMapped;
|
||
|
mapping(address => uint256) private _validatorIndex;
|
||
|
|
||
|
// The standard event to notify the engine about the validator set changing in the contract
|
||
|
event InitiateChange(bytes32 indexed parentHash, address[] newSet);
|
||
|
|
||
|
constructor() public {
|
||
|
// Initialize validator indices to be able to correctly remove
|
||
|
// a malicious validator from the validator set later
|
||
|
for (uint i = 0; i < validators.length; i++) {
|
||
|
_validatorIndex[validators[i]] = i;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Emits an `InitiateChange` event with the current (or new) validator set
|
||
|
function emitInitiateChange() public {
|
||
|
emit InitiateChange(blockhash(block.number - 1), validators);
|
||
|
}
|
||
|
|
||
|
// Applies a validator set change in production code. Does nothing in the test
|
||
|
function finalizeChange() pure public {}
|
||
|
|
||
|
// Benign validator behaviour report. Kept here for regression testing
|
||
|
function reportBenign(address _validator, uint256) public {
|
||
|
disliked = _validator;
|
||
|
}
|
||
|
|
||
|
// Removes a malicious validator from the list
|
||
|
function reportMalicious(address _validator, uint256 _blockNum, bytes calldata) external {
|
||
|
address reportingValidator = msg.sender;
|
||
|
|
||
|
// Mark the `_validator` as reported by `reportingValidator` for the block `_blockNum`
|
||
|
_maliceReportedForBlock[_validator][_blockNum].push(reportingValidator);
|
||
|
_maliceReportedForBlockMapped[_validator][_blockNum][reportingValidator] = true;
|
||
|
isValidatorBanned[_validator] = true;
|
||
|
|
||
|
// If the passed validator is in the validator set
|
||
|
if (validators[_validatorIndex[_validator]] == _validator) {
|
||
|
// Remove the validator from the set
|
||
|
validators[_validatorIndex[_validator]] = validators[validators.length - 1];
|
||
|
delete _validatorIndex[_validator];
|
||
|
delete validators[validators.length - 1];
|
||
|
validators.length--;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Tests validator set changing and emitting the `InitiateChange` event
|
||
|
function setValidators(address[] memory _validators) public {
|
||
|
validators = _validators;
|
||
|
emitInitiateChange();
|
||
|
}
|
||
|
|
||
|
// Checks if `emitInitiateChange` can be called (used by POSDAO tests)
|
||
|
function emitInitiateChangeCallable() view public returns(bool) {
|
||
|
return block.number > 0;
|
||
|
}
|
||
|
|
||
|
// Returns the current validator set
|
||
|
function getValidators() public view returns(address[] memory) {
|
||
|
return validators;
|
||
|
}
|
||
|
|
||
|
// Returns the list of all validators that reported the given validator
|
||
|
// as malicious for the given block. Used by POSDAO tests
|
||
|
function maliceReportedForBlock(address _validator, uint256 _blockNum) public view returns(address[] memory) {
|
||
|
return _maliceReportedForBlock[_validator][_blockNum];
|
||
|
}
|
||
|
|
||
|
// Returns a boolean flag indicating whether the specified validator
|
||
|
// should report about some validator's misbehaviour at the specified block.
|
||
|
// Used by POSDAO tests.
|
||
|
// `_reportingValidator` is the address of validator who reports.
|
||
|
// `_maliciousValidator` is the address of malicious validator.
|
||
|
// `_blockNumber` is the block number at which the malicious validator misbehaved.
|
||
|
function shouldValidatorReport(
|
||
|
address _reportingValidator,
|
||
|
address _maliciousValidator,
|
||
|
uint256 _blockNumber
|
||
|
) public view returns(bool) {
|
||
|
uint256 currentBlock = block.number;
|
||
|
if (_blockNumber > currentBlock) {
|
||
|
return false;
|
||
|
}
|
||
|
if (currentBlock > 100 && currentBlock - 100 > _blockNumber) {
|
||
|
return false;
|
||
|
}
|
||
|
if (isValidatorBanned[_maliciousValidator]) {
|
||
|
// We shouldn't report the malicious validator
|
||
|
// as it has already been reported and banned
|
||
|
return false;
|
||
|
}
|
||
|
// Return `false` if already reported by the same `_reportingValidator` for the same `_blockNumber`
|
||
|
return !_maliceReportedForBlockMapped[_maliciousValidator][_blockNumber][_reportingValidator];
|
||
|
}
|
||
|
|
||
|
}
|