openethereum/crates/ethcore/res/contracts/test_authority_round_random...

102 lines
5.0 KiB
Solidity

pragma solidity 0.5.10;
/// @dev Randomness test contract based on https://github.com/poanetwork/posdao-contracts.
/// Generates and stores random numbers in a RANDAO manner and accumulates a random seed.
contract Random {
mapping(uint256 => mapping(address => bytes32)) public hashes;
mapping(uint256 => mapping(address => bytes)) public ciphers;
mapping(uint256 => mapping(address => uint256)) public secrets;
uint256 public value;
/// @dev Called by the validator's node to store a hash and a cipher of the validator's secret on each collection
/// round. The validator's node must use its mining address to call this function.
/// This function can only be called once per collection round (during the `commits phase`).
/// @param _secretHash The Keccak-256 hash of the validator's secret.
/// @param _cipher The cipher of the validator's secret. Can be used by the node to decrypt and reveal.
function commitHash(bytes32 _secretHash, bytes calldata _cipher) external {
require(block.coinbase == msg.sender);
require(_isCommitPhase(block.number - 1));
uint256 round = _collectRound(block.number - 1);
require(!isCommitted(round, msg.sender));
hashes[round][msg.sender] = _secretHash;
ciphers[round][msg.sender] = _cipher;
}
/// @dev Called by the validator's node to XOR its secret with the current random seed.
/// The validator's node must use its mining address to call this function.
/// This function can only be called once per collection round (during the `reveals phase`).
/// @param _number The validator's secret.
function revealNumber(uint256 _number) external {
require(block.coinbase == msg.sender);
require(_isRevealPhase(block.number - 1));
uint256 round = _collectRound(block.number - 1);
require(!sentReveal(round, msg.sender));
require(hashes[round][msg.sender] == keccak256(abi.encodePacked(_number)));
secrets[round][msg.sender] = _number;
value ^= _number;
}
/// @dev Returns the Keccak-256 hash and cipher of the validator's secret for the specified collection round
/// and the specified validator stored by the validator through the `commitHash` function.
/// @param _collectRound The serial number of the collection round for which hash and cipher should be retrieved.
/// @param _miningAddress The mining address of validator.
function getCommitAndCipher(
uint256 _collectRound,
address _miningAddress
) public view returns(bytes32, bytes memory) {
return (hashes[_collectRound][_miningAddress], ciphers[_collectRound][_miningAddress]);
}
/// @dev Returns a boolean flag indicating whether the specified validator has committed their secret's hash for the
/// specified collection round.
/// @param _collectRound The serial number of the collection round for which the checkup should be done.
/// @param _miningAddress The mining address of the validator.
function isCommitted(uint256 _collectRound, address _miningAddress) public view returns(bool) {
return hashes[_collectRound][_miningAddress] != bytes32(0);
}
/// @dev Returns a boolean flag indicating whether the current phase of the current collection round
/// is a `commits phase`. Used by the validator's node to determine if it should commit the hash of
/// the secret during the current collection round.
function isCommitPhase() public view returns(bool) {
return _isCommitPhase(block.number);
}
/// @dev Returns a boolean flag indicating whether the current phase of the current collection round
/// is a `reveals phase`. Used by the validator's node to determine if it should reveal the secret during
/// the current collection round.
function isRevealPhase() public view returns(bool) {
return _isRevealPhase(block.number);
}
/// @dev Returns a boolean flag of whether the specified validator has revealed their secret for the
/// specified collection round.
/// @param _collectRound The serial number of the collection round for which the checkup should be done.
/// @param _miningAddress The mining address of the validator.
function sentReveal(uint256 _collectRound, address _miningAddress) public view returns(bool) {
return secrets[_collectRound][_miningAddress] != uint256(0);
}
/// @dev Returns the current collect round number.
function currentCollectRound() public view returns(uint256) {
return _collectRound(block.number);
}
/// @dev Returns the current random value.
function getValue() public view returns(uint256) {
return value;
}
function _collectRound(uint256 blockNumber) private pure returns(uint256) {
return blockNumber / 6;
}
function _isCommitPhase(uint256 blockNumber) private pure returns(bool) {
return blockNumber % 6 < 3;
}
function _isRevealPhase(uint256 blockNumber) private pure returns(bool) {
return blockNumber % 6 >= 3;
}
}