Add info about joining

This commit is contained in:
Andrea Maria Piana 2019-04-11 10:14:57 +02:00
parent 60243545ad
commit f9bca9d526
No known key found for this signature in database
GPG Key ID: AA6CCA6DE0E06424
3 changed files with 141 additions and 45 deletions

View File

@ -9,11 +9,12 @@ contract NodesV2
// Nodes that have not passed any check or failed previous check
Enode[] public inactiveNodes;
uint quorum;
uint16 quorum;
uint16 maxNodes = 6000;
// How many blocks is a session
uint blockPerSession;
uint16 blockPerSession;
uint currentSessionStart;
uint public currentSession;
uint32 public currentSession;
struct Enode {
bytes publicKey;
@ -25,6 +26,10 @@ contract NodesV2
uint lastTimeHasVoted;
// For which voting round are the votes referring to
uint lastTimeHasBeenVoted;
// Session when the node joine
uint32 joiningSession;
// Session when became active
uint32 activeSession;
}
mapping(address => uint) activeNodeIndex;
@ -35,7 +40,7 @@ contract NodesV2
_;
}
constructor(uint _blockPerSession)
constructor(uint16 _blockPerSession)
public
{
owner = msg.sender;
@ -52,16 +57,16 @@ contract NodesV2
}
}
function getNode(uint index) public view returns (bytes memory, uint32, uint16) {
function getNode(uint index) public view returns (bytes memory, uint32, uint16, uint32, uint32) {
Enode memory enode = activeNodes[index];
return (enode.publicKey, enode.ip, enode.port);
return (enode.publicKey, enode.ip, enode.port, enode.joiningSession, enode.activeSession);
}
function getInactiveNode(uint index) public view returns (bytes memory, uint32, uint16) {
function getInactiveNode(uint index) public view returns (bytes memory, uint32, uint16, uint32, uint32) {
Enode memory enode = inactiveNodes[index];
return (enode.publicKey, enode.ip, enode.port);
return (enode.publicKey, enode.ip, enode.port, enode.joiningSession, enode.activeSession);
}
@ -73,8 +78,10 @@ contract NodesV2
require(msg.sender == publicKeyToAddress(publicKey));
// Make sure they haven't registered already
require(activeNodeIndex[msg.sender] == 0 && inactiveNodeIndex[msg.sender] == 0);
// Make sure we don't hit the max nodes limit
require(activeNodes.length + inactiveNodes.length < maxNodes);
Enode memory _node = Enode(publicKey, ip, port, 0, 0, 0, 0);
Enode memory _node = Enode(publicKey, ip, port, 0, 0, 0, 0, currentSession, 0);
inactiveNodes.push(_node);
inactiveNodeIndex[msg.sender] = inactiveNodes.length;
}
@ -120,6 +127,10 @@ contract NodesV2
// Make sure it has not voted already
require(activeNodes[enodeIndex - 1].lastTimeHasVoted != currentSession);
// Make sure it has not just became active, we allow 0 to ease bootstrapping
require(activeNodes[enodeIndex - 1].activeSession == 0 && activeNodes[enodeIndex - 1].activeSession != currentSession);
activeNodes[enodeIndex - 1].lastTimeHasVoted = currentSession;
// Remove nodes that failed the vote
@ -156,6 +167,7 @@ contract NodesV2
if (enode.joinVotes == quorum) {
Enode memory enodeCopy = inactiveNodes[index - 1];
enodeCopy.activeSession = currentSession;
_deleteInactiveNode(index - 1);
_addActiveNode(enodeAddress, enodeCopy);
}
@ -179,8 +191,10 @@ contract NodesV2
address enodeAddress = publicKeyToAddress(publicKey);
// Make sure they haven't registered already
require(activeNodeIndex[enodeAddress] == 0 && inactiveNodeIndex[enodeAddress] == 0);
// Make sure we don't hit the max nodes limit
require(activeNodes.length + inactiveNodes.length < maxNodes);
Enode memory _node = Enode(publicKey, ip, port, 0, 0, 0, 0);
Enode memory _node = Enode(publicKey, ip, port, 0, 0, 0, 0, currentSession, currentSession);
_addActiveNode(enodeAddress, _node);
@ -197,8 +211,8 @@ contract NodesV2
}
function calculateQuorum(uint a) pure internal returns (uint ) {
return a / 2 + 1;
function calculateQuorum(uint a) pure internal returns (uint16) {
return uint16(a) / 2 + 1;
}
function _deleteInactiveNode(uint index) internal {

File diff suppressed because one or more lines are too long

View File

@ -185,10 +185,10 @@ contract('Nodes', async (accounts) => {
});
});
xdescribe('voter is newly active', async () => {
describe('voter is newly active', async () => {
it('throws an exception', async () => {
try {
await instance.vote([node4.address], [node2.address], { from: accounts[3] });
await instance.vote([node4.address], [node2.address], { from: accounts[4] });
} catch (error) {
return;
}
@ -218,6 +218,7 @@ contract('Nodes', async (accounts) => {
assert.equal(inactiveNode1[0], node4.pk);
assert.equal(inactiveNode1[1], node4.ip);
assert.equal(inactiveNode1[2], node4.port);
assert.equal(inactiveNode1[3], 0);
});
it('removes nodes that have failed the checks and promotes those that have passed them', async () => {
@ -233,16 +234,22 @@ contract('Nodes', async (accounts) => {
pk: actualNode1[0],
ip: actualNode1[1],
port: actualNode1[2],
joiningSession: actualNode1[3],
activeSession: actualNode1[4],
},
{
pk: actualNode2[0],
ip: actualNode2[1],
port: actualNode2[2],
joiningSession: actualNode2[3],
activeSession: actualNode2[4],
},
{
pk: actualNode3[0],
ip: actualNode3[1],
port: actualNode3[2],
joiningSession: actualNode3[3],
activeSession: actualNode3[4],
},
];
@ -251,15 +258,66 @@ contract('Nodes', async (accounts) => {
assert.equal(actualNodes[0].pk, node3.pk);
assert.equal(actualNodes[0].port, node3.port);
assert.equal(actualNodes[0].ip, node3.ip);
assert.equal(actualNodes[0].joiningSession, 0);
assert.equal(actualNodes[0].activeSession, 0);
assert.equal(actualNodes[1].pk, node1.pk);
assert.equal(actualNodes[1].port, node1.port);
assert.equal(actualNodes[1].ip, node1.ip);
assert.equal(actualNodes[1].joiningSession, 0);
assert.equal(actualNodes[1].activeSession, 0);
assert.equal(actualNodes[2].pk, node5.pk);
assert.equal(actualNodes[2].port, node5.port);
assert.equal(actualNodes[2].ip, node5.ip);
assert.equal(actualNodes[2].joiningSession, 0);
assert.equal(actualNodes[2].activeSession, 1);
});
describe('a node removed re-register', async () => {
beforeEach(async () => {
await instance.registerNode(node2.pk, node2.ip, node2.port, { from: accounts[1] });
});
it('adds the node', async () => {
const actualNodeCount = await instance.inactiveNodeCount();
assert.equal(2, actualNodeCount);
});
it('adds the node', async () => {
const actualNode1 = await instance.getInactiveNode(0);
const actualNode2 = await instance.getInactiveNode(1);
const actualNodes = [
{
pk: actualNode1[0],
ip: actualNode1[1],
port: actualNode1[2],
joiningSession: actualNode1[3],
activeSession: actualNode1[4],
},
{
pk: actualNode2[0],
ip: actualNode2[1],
port: actualNode2[2],
joiningSession: actualNode2[3],
activeSession: actualNode2[4],
},
];
actualNodes.sort(compareNodes);
assert.equal(actualNodes[0].pk, node4.pk);
assert.equal(actualNodes[0].port, node4.port);
assert.equal(actualNodes[0].ip, node4.ip);
assert.equal(actualNodes[0].joiningSession, 0);
assert.equal(actualNodes[0].activeSession, 0);
assert.equal(actualNodes[1].pk, node2.pk);
assert.equal(actualNodes[1].port, node2.port);
assert.equal(actualNodes[1].ip, node2.ip);
assert.equal(actualNodes[1].joiningSession, 2);
assert.equal(actualNodes[1].activeSession, 0);
});
});
});
});