Skip to content

Commit

Permalink
wip: added test to check if nodes are properly added to the seed node…
Browse files Browse the repository at this point in the history
…s when entering the network

This tests for if the Seed node contains the new nodes when they are created. It also checks if the new nodes discover each other after being created.

There is a problem that needs to be fixed. With the RefreshBucket operations happening when syncing the node graph. It is extremely likely that a node will not be found when preforming a `findNode`. Currently, this WILL throw an error but we need to allow for the case where the node can't be found. So when a node can't be found the thing calling `findNode` should throw the error.
  • Loading branch information
tegefaulkes committed Apr 28, 2022
1 parent 08beafc commit 882d66b
Show file tree
Hide file tree
Showing 3 changed files with 98 additions and 6 deletions.
11 changes: 8 additions & 3 deletions src/nodes/NodeConnectionManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -458,9 +458,12 @@ class NodeConnectionManager {
});
// TODO: This currently just does one iteration
// If not found in this single iteration, we throw an exception
if (address == null) {
throw new nodesErrors.ErrorNodeGraphNodeIdNotFound();
}
// FIXME: This can and will not find nodes when refreshing a bucket.
// We can't throw an error here, we need to handle it.
// if (address == null) {
// throw new nodesErrors.ErrorNodeGraphNodeIdNotFound();
// }
address = { host: '1.1.1.1' as Host, port: 55555 as Port };
}
// We ensure that we always return a NodeAddress (either by lookup, or
// network search) - if we can't locate it from either, we throw an exception
Expand Down Expand Up @@ -633,6 +636,7 @@ class NodeConnectionManager {
*/
@ready(new nodesErrors.ErrorNodeConnectionManagerNotRunning())
public async syncNodeGraph(block: boolean = true, timer?: Timer) {
this.logger.info('Syncing nodeGraph');
for (const seedNodeId of this.getSeedNodes()) {
// Check if the connection is viable
try {
Expand All @@ -646,6 +650,7 @@ class NodeConnectionManager {
this.keyManager.getNodeId(),
timer,
);
// FIXME: we need to ping a node before setting it
for (const [nodeId, nodeData] of nodes) {
if (!block) {
this.queue.push(() =>
Expand Down
4 changes: 2 additions & 2 deletions src/nodes/NodeManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ class NodeManager {
protected refreshBucketQueue: Set<NodeBucketIndex> = new Set();
protected refreshBucketQueueRunning: boolean = false;
protected refreshBucketQueueRunner: Promise<void>;
protected refreshBucketQueuePlug_: PromiseType<void>;
protected refreshBucketQueueDrained_: PromiseType<void>;
protected refreshBucketQueuePlug_: PromiseType<void> = promise();
protected refreshBucketQueueDrained_: PromiseType<void> = promise();
protected refreshBucketQueueAbortController: AbortController;

constructor({
Expand Down
89 changes: 88 additions & 1 deletion tests/nodes/NodeConnectionManager.seednodes.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { NodeId, SeedNodes } from '@/nodes/types';
import type { NodeId, NodeIdEncoded, SeedNodes } from '@/nodes/types';
import type { Host, Port } from '@/network/types';
import type { Sigchain } from '@/sigchain';
import fs from 'fs';
Expand Down Expand Up @@ -123,6 +123,13 @@ describe(`${NodeConnectionManager.name} seed nodes test`, () => {
});

beforeEach(async () => {
// Clearing nodes from graphs
for await (const [nodeId] of remoteNode1.nodeGraph.getNodes()) {
await remoteNode1.nodeGraph.unsetNode(nodeId);
}
for await (const [nodeId] of remoteNode2.nodeGraph.getNodes()) {
await remoteNode2.nodeGraph.unsetNode(nodeId);
}
dataDir = await fs.promises.mkdtemp(
path.join(os.tmpdir(), 'polykey-test-'),
);
Expand Down Expand Up @@ -417,4 +424,84 @@ describe(`${NodeConnectionManager.name} seed nodes test`, () => {
await queue?.stop();
}
});
test('should expand the network when nodes enter', async () => {
// Using a single seed node we need to check that each entering node adds itself to the seed node.
// Also need to check that the new nodes can be seen in the network.
let node1: PolykeyAgent | undefined;
let node2: PolykeyAgent | undefined;
const seedNodes: SeedNodes = {};
seedNodes[nodesUtils.encodeNodeId(remoteNodeId1)] = {
host: remoteNode1.proxy.getProxyHost(),
port: remoteNode1.proxy.getProxyPort(),
};
seedNodes[nodesUtils.encodeNodeId(remoteNodeId2)] = {
host: remoteNode2.proxy.getProxyHost(),
port: remoteNode2.proxy.getProxyPort(),
};
try {
logger.setLevel(LogLevel.WARN);
node1 = await PolykeyAgent.createPolykeyAgent({
nodePath: path.join(dataDir, 'node1'),
password: 'password',
networkConfig: {
proxyHost: localHost,
agentHost: localHost,
clientHost: localHost,
forwardHost: localHost,
},
seedNodes,
logger,
});
node2 = await PolykeyAgent.createPolykeyAgent({
nodePath: path.join(dataDir, 'node2'),
password: 'password',
networkConfig: {
proxyHost: localHost,
agentHost: localHost,
clientHost: localHost,
forwardHost: localHost,
},
seedNodes,
logger,
});

await node1.queue.drained();
await node1.nodeManager.refreshBucketQueueDrained();
await node2.queue.drained();
await node2.nodeManager.refreshBucketQueueDrained();

const getAllNodes = async (node: PolykeyAgent) => {
const nodes: Array<NodeIdEncoded> = [];
for await (const [nodeId] of node.nodeGraph.getNodes()) {
nodes.push(nodesUtils.encodeNodeId(nodeId));
}
return nodes;
};
const rNode1Nodes = await getAllNodes(remoteNode1);
const rNode2Nodes = await getAllNodes(remoteNode2);
const node1Nodes = await getAllNodes(node1);
const node2Nodes = await getAllNodes(node2);

const nodeIdR1 = nodesUtils.encodeNodeId(remoteNodeId1);
const nodeIdR2 = nodesUtils.encodeNodeId(remoteNodeId2);
const nodeId1 = nodesUtils.encodeNodeId(node1.keyManager.getNodeId());
const nodeId2 = nodesUtils.encodeNodeId(node2.keyManager.getNodeId());
expect(rNode1Nodes).toContain(nodeId1);
expect(rNode1Nodes).toContain(nodeId2);
expect(rNode2Nodes).toContain(nodeId1);
expect(rNode2Nodes).toContain(nodeId2);
expect(node1Nodes).toContain(nodeIdR1);
expect(node1Nodes).toContain(nodeIdR2);
expect(node1Nodes).toContain(nodeId2);
expect(node2Nodes).toContain(nodeIdR1);
expect(node2Nodes).toContain(nodeIdR2);
expect(node2Nodes).toContain(nodeId1);
} finally {
logger.setLevel(LogLevel.WARN);
await node1?.stop();
await node1?.destroy();
await node2?.stop();
await node2?.destroy();
}
});
});

0 comments on commit 882d66b

Please sign in to comment.