2019-01-28 21:52:58 -08:00
|
|
|
pragma solidity ^0.5.3;
|
2018-07-11 00:25:45 -07:00
|
|
|
|
|
|
|
contract Permissions {
|
2018-11-16 02:08:49 -08:00
|
|
|
address[] initialAcctList;
|
2018-09-05 19:40:21 -07:00
|
|
|
// enum and struct declaration
|
2018-11-02 03:42:14 -07:00
|
|
|
enum NodeStatus {NotInList, PendingApproval, Approved, PendingDeactivation, Deactivated, PendingActivation, PendingBlacklisting, Blacklisted }
|
2018-09-05 19:40:21 -07:00
|
|
|
struct NodeDetails {
|
|
|
|
string enodeId; //e.g. 127.0.0.1:20005
|
2018-08-12 19:00:35 -07:00
|
|
|
string ipAddrPort;
|
|
|
|
string discPort;
|
|
|
|
string raftPort;
|
2018-07-11 00:25:45 -07:00
|
|
|
NodeStatus status;
|
|
|
|
}
|
2018-09-05 19:40:21 -07:00
|
|
|
// use an array to store node details
|
|
|
|
// if we want to list all node one day, mapping is not capable
|
|
|
|
NodeDetails[] private nodeList;
|
|
|
|
// use a mapping of enodeid to array index to track node
|
|
|
|
mapping (bytes32 => uint) private nodeIdToIndex;
|
|
|
|
// keep track of node number
|
|
|
|
uint private numberOfNodes;
|
2018-08-05 22:26:29 -07:00
|
|
|
|
2019-01-28 21:52:58 -08:00
|
|
|
enum AccountAccess { ReadOnly, Transact, ContractDeploy, FullAccess}
|
|
|
|
struct AccountAccessDetails {
|
|
|
|
address acctId;
|
|
|
|
AccountAccess acctAccess;
|
|
|
|
}
|
2018-11-02 03:42:14 -07:00
|
|
|
AccountAccessDetails[] private acctAccessList;
|
|
|
|
mapping (address => uint) private acctToIndex;
|
|
|
|
uint private numberOfAccts;
|
2019-01-28 21:52:58 -08:00
|
|
|
|
2018-09-05 19:40:21 -07:00
|
|
|
// use an array to store account details
|
|
|
|
// if we want to list all account one day, mapping is not capable
|
2019-01-28 21:52:58 -08:00
|
|
|
enum VoterStatus { Active, Inactive }
|
|
|
|
struct VoterAcctDetails {
|
|
|
|
address voterAcct;
|
|
|
|
VoterStatus voterStatus;
|
|
|
|
}
|
|
|
|
VoterAcctDetails[] private voterAcctList;
|
|
|
|
mapping (address => uint) private voterAcctIndex;
|
|
|
|
uint private numberOfVoters;
|
|
|
|
uint private numberOfValidVoters;
|
2018-09-05 19:40:21 -07:00
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// store pre pending status, use for cancelPendingOperation
|
|
|
|
mapping(uint => NodeStatus) private prependingStatus;
|
2018-09-05 19:40:21 -07:00
|
|
|
// store node approval, deactivation and blacklisting vote status (prevent double vote)
|
|
|
|
mapping (uint => mapping (address => bool)) private voteStatus;
|
|
|
|
// valid vote count
|
|
|
|
mapping (uint => uint) private voteCount;
|
|
|
|
|
2018-11-16 02:08:49 -08:00
|
|
|
// checks if first time network boot up has happened or not
|
2018-10-25 22:38:56 -07:00
|
|
|
bool private networkBoot = false;
|
2018-10-24 03:21:21 -07:00
|
|
|
|
2018-09-19 20:18:39 -07:00
|
|
|
// node permission events for new node propose
|
|
|
|
event NodeProposed(string _enodeId);
|
2018-08-12 19:00:35 -07:00
|
|
|
event NodeApproved(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
|
2018-09-19 20:18:39 -07:00
|
|
|
|
|
|
|
// node permission events for node decativation
|
2018-07-11 00:25:45 -07:00
|
|
|
event NodePendingDeactivation (string _enodeId);
|
2018-08-12 19:00:35 -07:00
|
|
|
event NodeDeactivated(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
|
2018-09-19 20:18:39 -07:00
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// node permission events for node activation
|
2018-11-02 03:42:14 -07:00
|
|
|
event NodePendingActivation(string _enodeId);
|
|
|
|
event NodeActivated(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
|
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// node permission events for node blacklist
|
2018-09-19 20:18:39 -07:00
|
|
|
event NodePendingBlacklist(string _enodeId);
|
2018-08-31 04:35:35 -07:00
|
|
|
event NodeBlacklisted(string _enodeId, string _ipAddrPort, string _discPort, string _raftPort);
|
2018-09-19 20:18:39 -07:00
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// pending operation cancelled
|
|
|
|
event PendingOperationCancelled(string _enodeId);
|
|
|
|
|
2018-09-05 19:40:21 -07:00
|
|
|
// account permission events
|
|
|
|
event AccountAccessModified(address _address, AccountAccess _access);
|
2018-09-19 20:18:39 -07:00
|
|
|
|
|
|
|
// Checks if the given enode exists
|
2019-01-28 21:52:58 -08:00
|
|
|
modifier enodeInList(string memory _enodeId)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
|
|
|
require(nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] != 0, "Enode is not in the list");
|
|
|
|
_;
|
|
|
|
}
|
2018-09-19 20:18:39 -07:00
|
|
|
|
|
|
|
// Checks if the given enode does not exists
|
2019-01-28 21:52:58 -08:00
|
|
|
modifier enodeNotInList(string memory _enodeId)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2019-01-23 22:25:44 -08:00
|
|
|
require(nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] == 0 || getNodeStatus(_enodeId) == NodeStatus.NotInList, "Enode is in the list");
|
2018-09-05 19:40:21 -07:00
|
|
|
_;
|
|
|
|
}
|
2018-09-19 20:18:39 -07:00
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// Checks if the account can vote
|
2018-09-05 19:40:21 -07:00
|
|
|
modifier canVote()
|
|
|
|
{
|
|
|
|
bool flag = false;
|
2019-01-28 21:52:58 -08:00
|
|
|
uint voterIndex = getVoterIndex(msg.sender);
|
|
|
|
if ((voterAcctIndex[msg.sender] != 0) && (voterAcctList[voterIndex].voterStatus == VoterStatus.Active)) {
|
|
|
|
flag = true;
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
require(flag, "Account can not vote");
|
|
|
|
_;
|
2018-08-31 04:35:35 -07:00
|
|
|
}
|
|
|
|
|
2018-09-05 19:40:21 -07:00
|
|
|
/* public and external functions */
|
|
|
|
// view functions
|
|
|
|
|
2019-01-08 01:27:13 -08:00
|
|
|
// Get number of voters
|
2018-11-02 03:42:14 -07:00
|
|
|
function getNumberOfVoters() public view returns (uint)
|
2018-10-31 00:15:34 -07:00
|
|
|
{
|
2019-01-31 23:32:45 -08:00
|
|
|
return numberOfVoters;
|
2018-10-31 00:15:34 -07:00
|
|
|
}
|
2018-11-15 21:40:36 -08:00
|
|
|
|
2019-02-01 00:08:48 -08:00
|
|
|
// Get number of valid voters
|
|
|
|
function getNumberOfValidVoters() public view returns (uint)
|
|
|
|
{
|
|
|
|
return numberOfValidVoters;
|
|
|
|
}
|
2018-11-15 21:40:36 -08:00
|
|
|
// Get voter
|
2019-01-28 21:52:58 -08:00
|
|
|
function getVoter(uint i) public view returns (address _addr, VoterStatus _voterStatus)
|
2018-11-15 21:40:36 -08:00
|
|
|
{
|
2019-01-28 21:52:58 -08:00
|
|
|
return (voterAcctList[i].voterAcct, voterAcctList[i].voterStatus);
|
2018-11-15 21:40:36 -08:00
|
|
|
}
|
|
|
|
|
2018-10-25 22:38:56 -07:00
|
|
|
// Get number of nodes
|
|
|
|
function getNetworkBootStatus() public view returns (bool)
|
|
|
|
{
|
|
|
|
return networkBoot;
|
|
|
|
}
|
|
|
|
|
2018-11-18 19:58:34 -08:00
|
|
|
// Get node details given enode Id
|
2019-01-28 21:52:58 -08:00
|
|
|
function getNodeDetails(string memory enodeId) public view returns (string memory _enodeId, string memory _ipAddrPort, string memory _discPort, string memory _raftPort, NodeStatus _nodeStatus)
|
2018-11-18 19:58:34 -08:00
|
|
|
{
|
|
|
|
uint nodeIndex = getNodeIndex(enodeId);
|
|
|
|
return (nodeList[nodeIndex].enodeId, nodeList[nodeIndex].ipAddrPort, nodeList[nodeIndex].discPort, nodeList[nodeIndex].raftPort, nodeList[nodeIndex].status);
|
|
|
|
}
|
2018-11-14 01:58:57 -08:00
|
|
|
// Get node details given index
|
2019-01-28 21:52:58 -08:00
|
|
|
function getNodeDetailsFromIndex(uint nodeIndex) public view returns (string memory _enodeId, string memory _ipAddrPort, string memory _discPort, string memory _raftPort, NodeStatus _nodeStatus)
|
2018-11-14 01:58:57 -08:00
|
|
|
{
|
|
|
|
return (nodeList[nodeIndex].enodeId, nodeList[nodeIndex].ipAddrPort, nodeList[nodeIndex].discPort, nodeList[nodeIndex].raftPort, nodeList[nodeIndex].status);
|
|
|
|
}
|
2018-09-05 19:40:21 -07:00
|
|
|
// Get number of nodes
|
2018-09-17 22:52:46 -07:00
|
|
|
function getNumberOfNodes() public view returns (uint)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
|
|
|
return numberOfNodes;
|
|
|
|
}
|
2018-11-15 20:21:50 -08:00
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// Get account details given index
|
2018-11-21 00:48:03 -08:00
|
|
|
function getAccountDetails(uint acctIndex) public view returns (address _acct, AccountAccess _acctAccess)
|
|
|
|
{
|
|
|
|
return (acctAccessList[acctIndex].acctId, acctAccessList[acctIndex].acctAccess);
|
|
|
|
}
|
2018-11-15 20:21:50 -08:00
|
|
|
|
2018-09-05 19:40:21 -07:00
|
|
|
// Get number of accounts and voting accounts
|
2018-09-17 22:52:46 -07:00
|
|
|
function getNumberOfAccounts() public view returns (uint)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2018-11-02 03:42:14 -07:00
|
|
|
return acctAccessList.length;
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
// Get node status by enode id
|
2019-01-28 21:52:58 -08:00
|
|
|
function getNodeStatus(string memory _enodeId) public view enodeInList(_enodeId) returns (NodeStatus)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
|
|
|
return nodeList[getNodeIndex(_enodeId)].status;
|
|
|
|
}
|
2018-11-21 00:48:03 -08:00
|
|
|
|
2018-11-13 00:15:28 -08:00
|
|
|
function isVoter(address _acctid) external view returns (bool)
|
|
|
|
{
|
2019-01-28 21:52:58 -08:00
|
|
|
if ((voterAcctIndex[_acctid] != 0) &&
|
|
|
|
(voterAcctList[getVoterIndex(_acctid)].voterStatus == VoterStatus.Active)) {
|
|
|
|
return true;
|
2018-11-13 00:15:28 -08:00
|
|
|
}
|
2019-01-28 21:52:58 -08:00
|
|
|
return false;
|
2018-11-13 00:15:28 -08:00
|
|
|
}
|
2018-09-05 19:40:21 -07:00
|
|
|
|
2018-10-24 03:21:21 -07:00
|
|
|
// update the networ boot status as true
|
2018-10-25 22:38:56 -07:00
|
|
|
function updateNetworkBootStatus() external returns (bool)
|
|
|
|
{
|
2018-10-24 03:21:21 -07:00
|
|
|
require (networkBoot == false, "Invalid call: Network boot up completed");
|
|
|
|
networkBoot = true;
|
2018-10-25 22:38:56 -07:00
|
|
|
return networkBoot;
|
2018-10-24 03:21:21 -07:00
|
|
|
}
|
2018-09-05 19:40:21 -07:00
|
|
|
|
2018-11-02 03:42:14 -07:00
|
|
|
function initNodeVoteStatus(uint nodeIndex) internal {
|
|
|
|
voteCount[nodeIndex] = 0;
|
|
|
|
for (uint i = 0; i < voterAcctList.length; i++){
|
2019-01-28 21:52:58 -08:00
|
|
|
if (voterAcctList[i].voterStatus == VoterStatus.Active){
|
|
|
|
voteStatus[nodeIndex][voterAcctList[i].voterAcct] = false;
|
|
|
|
}
|
2018-11-02 03:42:14 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateVoteStatus(uint nodeIndex) internal {
|
|
|
|
voteCount[nodeIndex]++;
|
|
|
|
voteStatus[nodeIndex][msg.sender] = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
function checkEnoughVotes(uint nodeIndex) internal view returns (bool) {
|
|
|
|
bool approvalStatus = false;
|
2019-01-28 21:52:58 -08:00
|
|
|
if (voteCount[nodeIndex] > numberOfValidVoters/2){
|
2018-11-02 03:42:14 -07:00
|
|
|
approvalStatus = true;
|
|
|
|
}
|
|
|
|
return approvalStatus;
|
|
|
|
}
|
|
|
|
|
2018-08-31 04:35:35 -07:00
|
|
|
// propose a new node to the network
|
2019-01-28 21:52:58 -08:00
|
|
|
function proposeNode(string calldata _enodeId, string calldata _ipAddrPort, string calldata _discPort, string calldata _raftPort) external enodeNotInList(_enodeId)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2018-10-24 03:21:21 -07:00
|
|
|
if (!(networkBoot)){
|
2018-09-05 19:40:21 -07:00
|
|
|
numberOfNodes++;
|
|
|
|
nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] = numberOfNodes;
|
2018-10-24 03:21:21 -07:00
|
|
|
nodeList.push(NodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, NodeStatus.Approved));
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if (checkVotingAccountExist()){
|
2019-01-23 22:25:44 -08:00
|
|
|
if (nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] != 0){
|
|
|
|
nodeList[getNodeIndex(_enodeId)].status = NodeStatus.PendingApproval;
|
|
|
|
prependingStatus[getNodeIndex(_enodeId)] = NodeStatus.NotInList;
|
|
|
|
} else {
|
|
|
|
// increment node number, add node to the list
|
|
|
|
numberOfNodes++;
|
|
|
|
nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] = numberOfNodes;
|
|
|
|
nodeList.push(NodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, NodeStatus.PendingApproval));
|
|
|
|
prependingStatus[numberOfNodes] = NodeStatus.NotInList;
|
|
|
|
}
|
2018-11-02 03:42:14 -07:00
|
|
|
|
2018-10-24 03:21:21 -07:00
|
|
|
// add voting status, numberOfNodes is the index of current proposed node
|
2018-11-02 03:42:14 -07:00
|
|
|
initNodeVoteStatus(numberOfNodes);
|
2018-10-24 03:21:21 -07:00
|
|
|
// emit event
|
|
|
|
emit NodeProposed(_enodeId);
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
}
|
2018-07-11 00:25:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Adds a node to the nodeList mapping and emits node added event if successfully and node exists event of node is already present
|
2019-01-28 21:52:58 -08:00
|
|
|
function approveNode(string calldata _enodeId) external canVote
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2019-01-23 22:25:44 -08:00
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.PendingApproval, "Node need to be in PendingApproval status");
|
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
require(voteStatus[nodeIndex][msg.sender] == false, "Node can not double vote");
|
|
|
|
// vote node
|
|
|
|
updateVoteStatus(nodeIndex);
|
|
|
|
// emit event
|
|
|
|
// check if node vote reach majority
|
|
|
|
if (checkEnoughVotes(nodeIndex)) {
|
|
|
|
nodeList[nodeIndex].status = NodeStatus.Approved;
|
|
|
|
emit NodeApproved(nodeList[nodeIndex].enodeId, nodeList[nodeIndex].ipAddrPort, nodeList[nodeIndex].discPort, nodeList[nodeIndex].raftPort);
|
|
|
|
}
|
2018-07-11 00:25:45 -07:00
|
|
|
}
|
|
|
|
|
2018-08-31 04:35:35 -07:00
|
|
|
// Propose a node for deactivation from network
|
2019-01-28 21:52:58 -08:00
|
|
|
function proposeDeactivation(string calldata _enodeId) external enodeInList(_enodeId)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
|
|
|
if (checkVotingAccountExist()){
|
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.Approved, "Node need to be in Approved status");
|
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
2019-01-23 22:25:44 -08:00
|
|
|
prependingStatus[nodeIndex] = NodeStatus.Approved;
|
2018-09-05 19:40:21 -07:00
|
|
|
nodeList[nodeIndex].status = NodeStatus.PendingDeactivation;
|
|
|
|
// add voting status, numberOfNodes is the index of current proposed node
|
2018-11-02 03:42:14 -07:00
|
|
|
initNodeVoteStatus(nodeIndex);
|
2018-09-05 19:40:21 -07:00
|
|
|
// emit event
|
|
|
|
emit NodePendingDeactivation(_enodeId);
|
|
|
|
}
|
2018-07-11 00:25:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
//deactivates a given Enode and emits the decativation event
|
2019-01-28 21:52:58 -08:00
|
|
|
function deactivateNode(string calldata _enodeId) external canVote
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2018-07-11 00:25:45 -07:00
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.PendingDeactivation, "Node need to be in PendingDeactivation status");
|
2018-09-05 19:40:21 -07:00
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
require(voteStatus[nodeIndex][msg.sender] == false, "Node can not double vote");
|
|
|
|
// vote node
|
2018-11-02 03:42:14 -07:00
|
|
|
updateVoteStatus(nodeIndex);
|
2018-09-05 19:40:21 -07:00
|
|
|
// emit event
|
|
|
|
// check if node vote reach majority
|
2018-11-02 03:42:14 -07:00
|
|
|
if (checkEnoughVotes(nodeIndex)) {
|
|
|
|
nodeList[nodeIndex].status = NodeStatus.Deactivated;
|
|
|
|
emit NodeDeactivated(nodeList[nodeIndex].enodeId, nodeList[nodeIndex].ipAddrPort, nodeList[nodeIndex].discPort, nodeList[nodeIndex].raftPort);
|
2019-01-23 22:25:44 -08:00
|
|
|
}
|
2018-11-02 03:42:14 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Propose node for blacklisting
|
2019-01-28 21:52:58 -08:00
|
|
|
function proposeNodeActivation(string calldata _enodeId) external
|
2018-11-02 03:42:14 -07:00
|
|
|
{
|
|
|
|
if (checkVotingAccountExist()){
|
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.Deactivated, "Node need to be in Deactivated status");
|
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
2019-01-23 22:25:44 -08:00
|
|
|
prependingStatus[nodeIndex] = NodeStatus.Deactivated;
|
2018-11-02 03:42:14 -07:00
|
|
|
nodeList[nodeIndex].status = NodeStatus.PendingActivation;
|
|
|
|
// add voting status, numberOfNodes is the index of current proposed node
|
|
|
|
initNodeVoteStatus(nodeIndex);
|
|
|
|
// emit event
|
|
|
|
emit NodePendingActivation(_enodeId);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//deactivates a given Enode and emits the decativation event
|
2019-01-28 21:52:58 -08:00
|
|
|
function activateNode(string calldata _enodeId) external canVote
|
2018-11-02 03:42:14 -07:00
|
|
|
{
|
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.PendingActivation, "Node need to be in PendingActivation status");
|
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
require(voteStatus[nodeIndex][msg.sender] == false, "Node can not double vote");
|
|
|
|
// vote node
|
|
|
|
updateVoteStatus(nodeIndex);
|
|
|
|
// emit event
|
|
|
|
// check if node vote reach majority
|
|
|
|
if (checkEnoughVotes(nodeIndex)) {
|
|
|
|
nodeList[nodeIndex].status = NodeStatus.Approved;
|
|
|
|
emit NodeActivated(nodeList[nodeIndex].enodeId, nodeList[nodeIndex].ipAddrPort, nodeList[nodeIndex].discPort, nodeList[nodeIndex].raftPort);
|
|
|
|
}
|
2018-07-11 00:25:45 -07:00
|
|
|
}
|
|
|
|
|
2018-09-05 19:40:21 -07:00
|
|
|
// Propose node for blacklisting
|
2019-01-28 21:52:58 -08:00
|
|
|
function proposeNodeBlacklisting(string calldata _enodeId, string calldata _ipAddrPort, string calldata _discPort, string calldata _raftPort) external
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
|
|
|
if (checkVotingAccountExist()){
|
2018-11-02 03:42:14 -07:00
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
2018-09-05 19:40:21 -07:00
|
|
|
// check if node is in the nodeList
|
|
|
|
if (nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] != 0){
|
|
|
|
// no matter what status the node is in, vote will reset and node status change to PendingBlacklisting
|
2019-01-23 22:25:44 -08:00
|
|
|
if (!(nodeList[nodeIndex].status == NodeStatus.PendingApproval || nodeList[nodeIndex].status == NodeStatus.PendingActivation || nodeList[nodeIndex].status == NodeStatus.PendingDeactivation || nodeList[nodeIndex].status == NodeStatus.PendingBlacklisting)){
|
|
|
|
prependingStatus[nodeIndex] = nodeList[nodeIndex].status;
|
|
|
|
}
|
2018-09-05 19:40:21 -07:00
|
|
|
nodeList[nodeIndex].status = NodeStatus.PendingBlacklisting;
|
|
|
|
nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
} else {
|
|
|
|
// increment node number, add node to the list
|
|
|
|
numberOfNodes++;
|
|
|
|
nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] = numberOfNodes;
|
2018-09-19 20:18:39 -07:00
|
|
|
nodeList.push(NodeDetails(_enodeId, _ipAddrPort,_discPort, _raftPort, NodeStatus.PendingBlacklisting));
|
2019-01-23 22:25:44 -08:00
|
|
|
prependingStatus[nodeIndex] = NodeStatus.NotInList;
|
2018-09-05 19:40:21 -07:00
|
|
|
nodeIndex = numberOfNodes;
|
|
|
|
}
|
|
|
|
// add voting status, numberOfNodes is the index of current proposed node
|
2018-11-02 03:42:14 -07:00
|
|
|
initNodeVoteStatus(nodeIndex);
|
2018-09-05 19:40:21 -07:00
|
|
|
// emit event
|
2018-09-19 20:18:39 -07:00
|
|
|
emit NodePendingBlacklist(_enodeId);
|
2018-08-31 04:35:35 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//Approve node blacklisting
|
2019-01-28 21:52:58 -08:00
|
|
|
function blacklistNode(string calldata _enodeId) external canVote
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2018-08-31 04:35:35 -07:00
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.PendingBlacklisting, "Node need to be in PendingBlacklisting status");
|
2018-09-05 19:40:21 -07:00
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
require(voteStatus[nodeIndex][msg.sender] == false, "Node can not double vote");
|
|
|
|
// vote node
|
|
|
|
voteStatus[nodeIndex][msg.sender] = true;
|
|
|
|
voteCount[nodeIndex]++;
|
|
|
|
// emit event
|
|
|
|
// check if node vote reach majority
|
2018-11-02 03:42:14 -07:00
|
|
|
if (checkEnoughVotes(nodeIndex)) {
|
|
|
|
nodeList[nodeIndex].status = NodeStatus.Blacklisted;
|
|
|
|
emit NodeBlacklisted(nodeList[nodeIndex].enodeId, nodeList[nodeIndex].ipAddrPort, nodeList[nodeIndex].discPort, nodeList[nodeIndex].raftPort);
|
|
|
|
}
|
2018-08-31 04:35:35 -07:00
|
|
|
}
|
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
// Cancel current pending node operation
|
2019-01-28 22:06:24 -08:00
|
|
|
function cancelPendingOperation(string calldata _enodeId) external canVote
|
2019-01-23 22:25:44 -08:00
|
|
|
{
|
2019-01-28 22:06:24 -08:00
|
|
|
require(getNodeStatus(_enodeId) == NodeStatus.PendingApproval ||
|
|
|
|
getNodeStatus(_enodeId) == NodeStatus.PendingActivation ||
|
|
|
|
getNodeStatus(_enodeId) == NodeStatus.PendingDeactivation ||
|
|
|
|
getNodeStatus(_enodeId) == NodeStatus.PendingBlacklisting,
|
|
|
|
"Node status must be in pending");
|
|
|
|
|
2019-01-23 22:25:44 -08:00
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
nodeList[nodeIndex].status = prependingStatus[nodeIndex];
|
|
|
|
emit PendingOperationCancelled(_enodeId);
|
|
|
|
}
|
|
|
|
|
2018-11-18 19:58:34 -08:00
|
|
|
function initAccounts() external
|
2018-11-21 00:48:03 -08:00
|
|
|
{
|
|
|
|
require(networkBoot == false, "network accounts already boot up");
|
|
|
|
for (uint i=0; i<initialAcctList.length; i++){
|
2019-01-22 16:55:50 -08:00
|
|
|
if (acctToIndex[initialAcctList[i]] == 0){
|
2018-11-21 00:48:03 -08:00
|
|
|
numberOfAccts ++;
|
|
|
|
acctToIndex[initialAcctList[i]] = numberOfAccts;
|
|
|
|
acctAccessList.push(AccountAccessDetails(initialAcctList[i], AccountAccess.FullAccess));
|
|
|
|
emit AccountAccessModified(initialAcctList[i], AccountAccess.FullAccess);
|
2019-01-22 16:55:50 -08:00
|
|
|
}
|
2018-11-16 02:08:49 -08:00
|
|
|
}
|
2018-11-21 00:48:03 -08:00
|
|
|
}
|
2018-11-16 02:08:49 -08:00
|
|
|
|
2018-08-31 04:35:35 -07:00
|
|
|
// Checks if the Node is already added. If yes then returns true
|
2018-09-17 22:52:46 -07:00
|
|
|
function updateAccountAccess(address _address, AccountAccess _accountAccess) external
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2018-11-02 03:42:14 -07:00
|
|
|
// Check if account already exists
|
|
|
|
uint acctIndex = getAcctIndex(_address);
|
|
|
|
if (acctToIndex[_address] != 0){
|
|
|
|
acctAccessList[acctIndex].acctAccess = _accountAccess;
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
numberOfAccts ++;
|
|
|
|
acctToIndex[_address] = numberOfAccts;
|
|
|
|
acctAccessList.push(AccountAccessDetails(_address, _accountAccess));
|
|
|
|
}
|
2018-11-15 19:07:10 -08:00
|
|
|
emit AccountAccessModified(_address, _accountAccess);
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
// Add voting account
|
2018-09-17 22:52:46 -07:00
|
|
|
function addVoter(address _address) external
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2019-01-28 21:52:58 -08:00
|
|
|
uint vId = getVoterIndex(_address);
|
|
|
|
if (voterAcctIndex[_address] != 0) {
|
|
|
|
if (voterAcctList[vId].voterStatus == VoterStatus.Inactive){
|
|
|
|
voterAcctList[vId].voterStatus = VoterStatus.Active;
|
|
|
|
numberOfValidVoters ++;
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
}
|
2019-01-28 21:52:58 -08:00
|
|
|
else {
|
|
|
|
numberOfVoters ++;
|
|
|
|
voterAcctIndex[_address] = numberOfVoters;
|
|
|
|
voterAcctList.push(VoterAcctDetails(_address, VoterStatus.Active));
|
|
|
|
numberOfValidVoters ++;
|
|
|
|
}
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
// Remove voting account
|
2018-09-17 22:52:46 -07:00
|
|
|
function removeVoter(address _address) external
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2019-01-28 21:52:58 -08:00
|
|
|
uint vId = getVoterIndex(_address);
|
|
|
|
if (voterAcctIndex[_address] != 0) {
|
|
|
|
voterAcctList[vId].voterStatus = VoterStatus.Inactive;
|
|
|
|
numberOfValidVoters --;
|
2018-09-05 19:40:21 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-28 21:52:58 -08:00
|
|
|
function getVoteStatus(string memory _enodeId, address _address) public view returns (bool){
|
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
return voteStatus[nodeIndex][_address];
|
|
|
|
}
|
|
|
|
function getVoterCount() public view returns (uint, uint)
|
|
|
|
{
|
|
|
|
return (numberOfVoters,numberOfValidVoters);
|
|
|
|
}
|
|
|
|
|
|
|
|
function getVoteCount(string memory _enodeId) public view returns (uint)
|
|
|
|
{
|
|
|
|
uint nodeIndex = getNodeIndex(_enodeId);
|
|
|
|
return voteCount[nodeIndex];
|
|
|
|
}
|
|
|
|
|
2018-09-05 19:40:21 -07:00
|
|
|
/* private functions */
|
2019-01-28 21:52:58 -08:00
|
|
|
function getNodeIndex(string memory _enodeId) internal view returns (uint)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
|
|
|
return nodeIdToIndex[keccak256(abi.encodePacked(_enodeId))] - 1;
|
|
|
|
}
|
|
|
|
|
2018-11-02 03:42:14 -07:00
|
|
|
/* private functions */
|
|
|
|
function getAcctIndex(address _acct) internal view returns (uint)
|
|
|
|
{
|
|
|
|
return acctToIndex[_acct] - 1;
|
|
|
|
}
|
|
|
|
|
2019-01-28 21:52:58 -08:00
|
|
|
/* private functions */
|
|
|
|
function getVoterIndex(address _acct) internal view returns (uint)
|
|
|
|
{
|
|
|
|
return voterAcctIndex[_acct] - 1;
|
|
|
|
}
|
|
|
|
|
2018-11-21 00:48:03 -08:00
|
|
|
function checkVotingAccountExist() internal view returns (bool)
|
2018-09-05 19:40:21 -07:00
|
|
|
{
|
2019-01-28 21:52:58 -08:00
|
|
|
if (numberOfValidVoters == 0) {
|
2018-09-05 19:40:21 -07:00
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-07-11 00:25:45 -07:00
|
|
|
}
|