Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Feature) Add new validator with mining/voting/payout keys at once #118

Merged
merged 1 commit into from
Jun 1, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions contracts/KeysManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ contract KeysManager is EternalStorage, IKeysManager {
string internal constant IS_MINING_ACTIVE = "isMiningActive";
string internal constant IS_PAYOUT_ACTIVE = "isPayoutActive";
string internal constant IS_VOTING_ACTIVE = "isVotingActive";
string internal constant MINING_KEY_BY_PAYOUT = "miningKeyByPayout";
string internal constant MINING_KEY_BY_VOTING = "miningKeyByVoting";
string internal constant MINING_KEY_HISTORY = "miningKeyHistory";
string internal constant PAYOUT_KEY = "payoutKey";
Expand Down Expand Up @@ -111,6 +112,12 @@ contract KeysManager is EternalStorage, IKeysManager {
]);
}

function miningKeyByPayout(address _payoutKey) public view returns(address) {
return addressStorage[
keccak256(abi.encodePacked(MINING_KEY_BY_PAYOUT, _payoutKey))
];
}

function miningKeyByVoting(address _votingKey) public view returns(address) {
return addressStorage[
keccak256(abi.encodePacked(MINING_KEY_BY_VOTING, _votingKey))
Expand Down Expand Up @@ -177,12 +184,14 @@ contract KeysManager is EternalStorage, IKeysManager {
require(!isMiningActive(_miningKey));
require(!successfulValidatorClone(_miningKey));
address votingKey = previous.getVotingByMining(_miningKey);
address payoutKey = previous.getPayoutByMining(_miningKey);
_setVotingKey(votingKey, _miningKey);
_setPayoutKey(previous.getPayoutByMining(_miningKey), _miningKey);
_setPayoutKey(payoutKey, _miningKey);
_setIsMiningActive(previous.isMiningActive(_miningKey), _miningKey);
_setIsVotingActive(previous.isVotingActive(votingKey), _miningKey);
_setIsPayoutActive(previous.isPayoutActive(_miningKey), _miningKey);
_setMiningKeyByVoting(previous.getVotingByMining(_miningKey), _miningKey);
_setMiningKeyByVoting(votingKey, _miningKey);
_setMiningKeyByPayout(payoutKey, _miningKey);
_setSuccessfulValidatorClone(true, _miningKey);
address currentMiningKey = _miningKey;
for (uint8 i = 0; i < 25; i++) {
Expand Down Expand Up @@ -246,6 +255,7 @@ contract KeysManager is EternalStorage, IKeysManager {
_setIsVotingActive(true, _miningKey);
_setIsPayoutActive(true, _miningKey);
_setMiningKeyByVoting(_votingKey, _miningKey);
_setMiningKeyByPayout(_payoutKey, _miningKey);
_setInitialKeyStatus(msg.sender, uint8(InitialKeyState.Deactivated));
IPoaNetworkConsensus(poaNetworkConsensus()).addValidator(_miningKey, true);
emit ValidatorInitialized(_miningKey, _votingKey, _payoutKey);
Expand Down Expand Up @@ -334,11 +344,12 @@ contract KeysManager is EternalStorage, IKeysManager {
public
onlyVotingToChangeKeys
{
require(isMiningActive(_oldMiningKey));
_setMiningKeyHistory(_key, _oldMiningKey);
address votingKey = getVotingByMining(_oldMiningKey);
require(isMiningActive(_oldMiningKey));
address payoutKey = getPayoutByMining(_oldMiningKey);
_setVotingKey(votingKey, _key);
_setPayoutKey(getPayoutByMining(_oldMiningKey), _key);
_setPayoutKey(payoutKey, _key);
_setIsMiningActive(true, _key);
_setIsVotingActive(isVotingActive(votingKey), _key);
_setIsPayoutActive(isPayoutActive(_oldMiningKey), _key);
Expand All @@ -349,6 +360,7 @@ contract KeysManager is EternalStorage, IKeysManager {
_setIsVotingActive(false, _oldMiningKey);
_setIsPayoutActive(false, _oldMiningKey);
_setMiningKeyByVoting(votingKey, _key);
_setMiningKeyByPayout(payoutKey, _key);
emit MiningKeyChanged(_key, "swapped");
}

Expand Down Expand Up @@ -406,6 +418,7 @@ contract KeysManager is EternalStorage, IKeysManager {
} else {
_setPayoutKey(_key, _miningKey);
_setIsPayoutActive(true, _miningKey);
_setMiningKeyByPayout(_key, _miningKey);
emit PayoutKeyChanged(_key, _miningKey, "added");
}
}
Expand All @@ -414,6 +427,7 @@ contract KeysManager is EternalStorage, IKeysManager {
require(initDisabled());
require(isMiningActive(_key));
_setMiningKeyByVoting(getVotingByMining(_key), address(0));
_setMiningKeyByPayout(getPayoutByMining(_key), address(0));
_setVotingKey(address(0), _key);
_setPayoutKey(address(0), _key);
_setIsMiningActive(false, _key);
Expand Down Expand Up @@ -442,6 +456,7 @@ contract KeysManager is EternalStorage, IKeysManager {
address oldPayout = getPayoutByMining(_miningKey);
_setPayoutKey(address(0), _miningKey);
_setIsPayoutActive(false, _miningKey);
_setMiningKeyByPayout(oldPayout, address(0));
emit PayoutKeyChanged(oldPayout, _miningKey, "removed");
}

Expand Down Expand Up @@ -489,7 +504,15 @@ contract KeysManager is EternalStorage, IKeysManager {
] = _active;
}

function _setMiningKeyByPayout(address _payoutKey, address _miningKey) private {
if (_payoutKey == address(0)) return;
addressStorage[
keccak256(abi.encodePacked(MINING_KEY_BY_PAYOUT, _payoutKey))
] = _miningKey;
}

function _setMiningKeyByVoting(address _votingKey, address _miningKey) private {
if (_votingKey == address(0)) return;
addressStorage[
keccak256(abi.encodePacked(MINING_KEY_BY_VOTING, _votingKey))
] = _miningKey;
Expand Down
161 changes: 115 additions & 46 deletions contracts/VotingToChangeKeys.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
string internal constant AFFECTED_KEY_TYPE = "affectedKeyType";
string internal constant BALLOT_TYPE = "ballotType";
string internal constant MINING_KEY = "miningKey";
string internal constant NEW_PAYOUT_KEY = "newPayoutKey";
string internal constant NEW_VOTING_KEY = "newVotingKey";

enum KeyTypes {Invalid, MiningKey, VotingKey, PayoutKey}

Expand All @@ -23,59 +25,61 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
require(_ballotType >= uint256(BallotTypes.KeyAdding));
require(_ballotType <= uint256(BallotTypes.KeySwap));
require(_affectedKey != address(0));
require(_affectedKeyType > 0);
require(_affectedKeyType >= uint256(KeyTypes.MiningKey));
require(_affectedKeyType <= uint256(KeyTypes.PayoutKey));

IKeysManager keysManager = IKeysManager(getKeysManager());
address key;

if (_affectedKeyType == uint256(KeyTypes.MiningKey)) {
if (_ballotType != uint256(BallotTypes.KeyRemoval)) {
require(!checkIfMiningExisted(_miningKey, _affectedKey));
if (_ballotType == uint256(BallotTypes.KeyAdding)) {
if (_affectedKeyType == uint256(KeyTypes.MiningKey)) {
return !checkIfMiningExisted(_miningKey, _affectedKey);
}
} else if (_affectedKeyType == uint256(KeyTypes.VotingKey)) {
if (_ballotType == uint256(BallotTypes.KeyAdding)) {
if (_affectedKeyType == uint256(KeyTypes.VotingKey)) {
require(_miningKey != keysManager.masterOfCeremony());
return _affectedKey != _miningKey;
}
if (_affectedKeyType == uint256(KeyTypes.PayoutKey)) {
return _affectedKey != _miningKey;
}
}
bool isMiningActive = keysManager.isMiningActive(_miningKey);
if (_affectedKeyType == uint256(KeyTypes.MiningKey)) {
if (_ballotType == uint256(BallotTypes.KeyAdding)) {

require(keysManager.isMiningActive(_miningKey));

if (_ballotType == uint256(BallotTypes.KeyRemoval)) {
if (_affectedKeyType == uint256(KeyTypes.MiningKey)) {
return true;
}
if (_ballotType == uint256(BallotTypes.KeyRemoval)) {
return isMiningActive;
if (_affectedKeyType == uint256(KeyTypes.VotingKey)) {
require(_affectedKey != _miningKey);
key = keysManager.getVotingByMining(_miningKey);
require(_affectedKey == key);
return keysManager.isVotingActive(key);
}
if (_affectedKeyType == uint256(KeyTypes.PayoutKey)) {
require(_affectedKey != _miningKey);
key = keysManager.getPayoutByMining(_miningKey);
require(_affectedKey == key);
return keysManager.isPayoutActive(_miningKey);
}
}
require(_affectedKey != _miningKey);
bool keyCheck;
if (
_ballotType == uint256(BallotTypes.KeyRemoval) ||
_ballotType == uint256(BallotTypes.KeySwap)
) {

if (_ballotType == uint256(BallotTypes.KeySwap)) {
require(_affectedKey != _miningKey);
if (_affectedKeyType == uint256(KeyTypes.MiningKey)) {
return isMiningActive;
return !checkIfMiningExisted(_miningKey, _affectedKey);
}
if (_affectedKeyType == uint256(KeyTypes.VotingKey)) {
address votingKey = keysManager.getVotingByMining(_miningKey);
if (_ballotType == uint256(BallotTypes.KeyRemoval)) {
keyCheck = _affectedKey == votingKey;
} else {
keyCheck = _affectedKey != votingKey;
}
return keysManager.isVotingActive(votingKey) && keyCheck && isMiningActive;
key = keysManager.getVotingByMining(_miningKey);
require(_affectedKey != key);
return keysManager.isVotingActive(key);
}
if (_affectedKeyType == uint256(KeyTypes.PayoutKey)) {
address payoutKey = keysManager.getPayoutByMining(_miningKey);
if (_ballotType == uint256(BallotTypes.KeyRemoval)) {
keyCheck = _affectedKey == payoutKey;
} else {
keyCheck = _affectedKey != payoutKey;
}
return keysManager.isPayoutActive(_miningKey) && keyCheck && isMiningActive;
}
key = keysManager.getPayoutByMining(_miningKey);
require(_affectedKey != key);
return keysManager.isPayoutActive(_miningKey);
}
}
return true;
}
// solhint-enable code-complexity, function-max-lines

Expand All @@ -89,6 +93,10 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
if (keysManager.isMiningActive(_newKey)) {
return true;
}

if (_currentKey == address(0)) {
return false;
}

uint8 maxDeep = maxOldMiningKeysDeepCheck();

Expand All @@ -114,8 +122,7 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
address _miningKey,
uint256 _ballotType,
string _memo
) public {
//only if ballotType is swap or remove
) public returns(uint256) {
require(areBallotParamsValid(
_ballotType,
_affectedKey,
Expand All @@ -127,6 +134,32 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
_setAffectedKeyType(ballotId, _affectedKeyType);
_setMiningKey(ballotId, _miningKey);
_setBallotType(ballotId, _ballotType);
return ballotId;
}

function createBallotToAddNewValidator(
uint256 _startTime,
uint256 _endTime,
address _newMiningKey,
address _newVotingKey,
address _newPayoutKey,
string _memo
) public returns(uint256) {
IKeysManager keysManager = IKeysManager(getKeysManager());
require(keysManager.miningKeyByVoting(_newVotingKey) == address(0));
require(keysManager.miningKeyByPayout(_newPayoutKey) == address(0));
uint256 ballotId = createBallot(
_startTime,
_endTime,
_newMiningKey, // _affectedKey
uint256(KeyTypes.MiningKey), // _affectedKeyType
address(0), // _miningKey
uint256(BallotTypes.KeyAdding), // _ballotType
_memo
);
_setNewVotingKey(ballotId, _newVotingKey);
_setNewPayoutKey(ballotId, _newPayoutKey);
return ballotId;
}

function getAffectedKey(uint256 _id) public view returns(address) {
Expand All @@ -153,6 +186,18 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
];
}

function getNewPayoutKey(uint256 _id) public view returns(address) {
return addressStorage[
keccak256(abi.encodePacked(VOTING_STATE, _id, NEW_PAYOUT_KEY))
];
}

function getNewVotingKey(uint256 _id) public view returns(address) {
return addressStorage[
keccak256(abi.encodePacked(VOTING_STATE, _id, NEW_VOTING_KEY))
];
}

function migrateBasicOne(
uint256 _id,
address _prevVotingToChange,
Expand Down Expand Up @@ -181,14 +226,26 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
function _finalizeAdding(uint256 _id) internal {
require(getBallotType(_id) == uint256(BallotTypes.KeyAdding));
IKeysManager keysManager = IKeysManager(getKeysManager());
if (getAffectedKeyType(_id) == uint256(KeyTypes.MiningKey)) {
keysManager.addMiningKey(getAffectedKey(_id));
}
if (getAffectedKeyType(_id) == uint256(KeyTypes.VotingKey)) {
keysManager.addVotingKey(getAffectedKey(_id), getMiningKey(_id));
}
if (getAffectedKeyType(_id) == uint256(KeyTypes.PayoutKey)) {
keysManager.addPayoutKey(getAffectedKey(_id), getMiningKey(_id));

address affectedKey = getAffectedKey(_id);
uint256 affectedKeyType = getAffectedKeyType(_id);

if (affectedKeyType == uint256(KeyTypes.MiningKey)) {
keysManager.addMiningKey(affectedKey);

address newVotingKey = getNewVotingKey(_id);
if (newVotingKey != address(0)) {
keysManager.addVotingKey(newVotingKey, affectedKey);
}

address newPayoutKey = getNewPayoutKey(_id);
if (newPayoutKey != address(0)) {
keysManager.addPayoutKey(newPayoutKey, affectedKey);
}
} else if (affectedKeyType == uint256(KeyTypes.VotingKey)) {
keysManager.addVotingKey(affectedKey, getMiningKey(_id));
} else if (affectedKeyType == uint256(KeyTypes.PayoutKey)) {
keysManager.addPayoutKey(affectedKey, getMiningKey(_id));
}
}

Expand Down Expand Up @@ -254,4 +311,16 @@ contract VotingToChangeKeys is IVotingToChangeKeys, VotingToChange {
] = _value;
}

function _setNewPayoutKey(uint256 _ballotId, address _value) internal {
addressStorage[
keccak256(abi.encodePacked(VOTING_STATE, _ballotId, NEW_PAYOUT_KEY))
] = _value;
}

function _setNewVotingKey(uint256 _ballotId, address _value) internal {
addressStorage[
keccak256(abi.encodePacked(VOTING_STATE, _ballotId, NEW_VOTING_KEY))
] = _value;
}

}
2 changes: 2 additions & 0 deletions contracts/interfaces/IKeysManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,6 @@ interface IKeysManager {
function getMiningKeyByVoting(address) external view returns(address);
function getInitialKey(address) external view returns(uint8);
function masterOfCeremony() external view returns(address);
function miningKeyByPayout(address) external view returns(address);
function miningKeyByVoting(address) external view returns(address);
}
Loading