Nyzo techRelease notesNyzo 614: client node management

Nyzo 614: client node management

Nyzo version 614 (commit on GitHub) improves management of nodes in ClientNodeManager, imposing a maximum number of nodes and implementing a scoring system to track node performance.

This version affects the client only.

The client plays an interesting role in the Nyzo ecosystem. It serves as a bridge to the mesh, providing a traditional web interface and API server. It provides these in a decentralized fashion, unlike the nyzo.co web server. Anyone can set up their own copy of the client quickly and easily, on a modest virtual server and without control of any in-cycle nodes, to provide their own window into the Nyzo blockchain. While we provide client.nyzo.co as a convenience, we hope that many more client instances will be established as Nyzo adoption increases.

This version improves client mesh management to improve robustness of client blockchain tracking. This will significantly reduce the effort required to maintain a client instance.

In ClientDataManager, counters were added for numberOfNonPreferredBlockFetches and numberOfPreferredBlockFetches. These are for monitoring only. Accessors were added to expose the values to the ClientHealthCommand.

RN_614 image 0

In ClientDataManager.requestBlockWithVotes(), a preferred node is now requested when the number of consecutive failures is odd. The appropriate counter is incremented in both cases.

RN_614 image 1

Success and failure is marked for each response. This is used by the ClientNodeManager for performance scoring.

RN_614 image 2

In ClientNodeManager, constants were added to bound the scoring system. A maximumMapSize was added to protect memory, and the nodes map was replaced with two maps to allow node scores to be tracked. Lists were added for efficient pseudorandom lookup of nodes in the preferred and general node pools, and a BiFunction was added for thread-safe tallying of scores.

RN_614 image 3

Each time a Node is present in a MeshResponse, its score increases by 1. After the mesh response is processed, nodes are removed to ensure the maps do not exceed the maximum allowable size and to ensure that no nodes with scores of 0 remain.

RN_614 image 4

The last section of the ClientNodeManager.processMeshResponse() method rebuilds the lists that are used to provide nodes to clients of the class through the randomNode() and randomPreferredNode() methods. The calculation for determining preferred nodes is explained in the comment.

RN_614 image 5

The method for providing a randomNode() is simpler due to the new allNodes list. The randomElement() method is no longer necessary. A new method provides a randomPreferredNode(). The getMesh() method references one of the new maps, and the getNumberOfNodes() method references the new allNodes list. The getNumberOfPreferredNodes() method provides additional information to the ClientHealthCommand.

RN_614 image 6

The client-health command displays the following new information:

RN_614 image 7

The rest of the commit is testing code. This is a typical NyzoTest, and it includes a main() method to allow it to be run independently of the other tests. The batchSize and numberOfBatches are constants for which many different values allow the test to complete successfully. There are also many values that can be assigned to these constants for which the test will not complete successfully. This is due to limitations of the test, not limitations of the ClientNodeManager.

RN_614 image 8

The ClientNodeManagerTest.run() method implements the test logic. Nodes are added to the ClientNodeManager. The same nodes are then added again, which increases their scores. Successes are marked, and failures are marked. The number of nodes and number of preferred nodes are checked after each operation.

RN_614 image 9

Lastly, the map size limit is tested.

RN_614 image 10

The ClientNodeManagerTest.addNodes() method creates simple Node objects for testing, and it performs the full and preferred size checks.

RN_614 image 11

The ClientNodeManagerTest.markSuccesses() method simulates successful block fetches and performs size checks.

RN_614 image 12

The ClientNodeManagerTest.markFailures() method simulates unsuccessful block fetches and performs size checks.

RN_614 image 13

The ClientNodeManagerTest.nodeWithTagAndIndex() method produces simple nodes for testing. The ClientNodeManagerTest.getFailureCause() method provides a description of any failure that the test encounters.

RN_614 image 14

The TestUtil suite now includes the ClientNodeManagerTest.

RN_614 image 15