Cardano Network Tools – CNT

Welcome to the crypto.bi Cardano* Network Tools – CNT home page.

crypto.bi CNT is a Python implementation of the Cardano P2P protocol.

Think of it as a programmable Cardano node but without the staking and block verification components – just the P2P networking code.

You can pick different network message types and develop your own scripts to handle those messages.

These tools can be used to explore the Cardano P2P network, whether you’re a technically skilled staking pool operator or a cryptocurrency enthusiast who just wants to learn more about PoS cryptocurrencies.

We use these functions to measure network parameters like speed and latency, analyze graphs of peers on the network and many other applications.

An example script is provided for each library functionality (modules with the run_ prefix) so you can get up and running quickly and easily adapt the library to your own applications.

Dependencies

Language version: Python 3.7+

Libs:

sudo pip3 install grpcio
sudo pip3 install mysql.connector
sudo pip3 install protobuf

Notes:

  • The grpc module package name is grpcio because grpc was already taken.
  • The mysql.connector library is required to pass tests, but database functionality is not yet implemented on the main library.

Using Cardano Network Tools

Runnable script filenames have a run_ prefix, tests have a test_ prefix and everything else are modules.

Let’s take a look at some of the example runnable scripts:

run_nodetiming.py

Continuously requests new peers from the network, sampling newly discovered peers’ response time. Appends results to a CSV file which can be analyzed using R, Librecalc, Pandas and so forth.

python3 run_nodetiming.py 127.0.0.1:3000 /disk5/jormungandr/local/peer_speed_data.csv
[STDERR] 2020-05-10 10:11:43.624306: Testing 145.239.10.190:5025 ...
[STDERR] 2020-05-10 10:11:44.127956: Received 1 hosts from 145.239.10.190:5025.
[STDERR] 2020-05-10 10:11:44.128331: get_peers_from_host,1589116304,145.239.10.190,5025,0.5039064189768396
[STDERR] 2020-05-10 10:11:44.128391: TOTAL 1020 HOSTS DISCOVERED, 111 TESTED
[STDERR] 2020-05-10 10:11:45.129713: Testing 3.126.89.52:3000 ...
[STDERR] 2020-05-10 10:11:45.674445: get_peers_from_host,1589116305,3.126.89.52,3000,0.5446157240075991
[STDERR] 2020-05-10 10:11:45.674529: TOTAL 1020 HOSTS DISCOVERED, 112 TESTED
[STDERR] 2020-05-10 10:11:46.675766: Testing 185.161.193.90:3202 ...
[STDERR] 2020-05-10 10:11:46.949290: get_peers_from_host,1589116306,185.161.193.90,3202,0.2734085649717599
[STDERR] 2020-05-10 10:11:46.949373: TOTAL 1020 HOSTS DISCOVERED, 113 TESTED
[STDERR] 2020-05-10 10:11:47.951026: Testing 172.104.18.191:4000 ...
[STDERR] 2020-05-10 10:12:07.952628: get_peers_from_host,1589116327,172.104.18.191,4000,20.001443414017558
[STDERR] 2020-05-10 10:12:07.952746: TOTAL 1020 HOSTS DISCOVERED, 114 TESTED
[STDERR] 2020-05-10 10:12:08.954421: Testing 176.223.136.17:3221 ...
[STDERR] 2020-05-10 10:12:09.240545: get_peers_from_host,1589116329,176.223.136.17,3221,0.28600044298218563
[STDERR] 2020-05-10 10:12:09.240633: TOTAL 1020 HOSTS DISCOVERED, 115 TESTED
[STDERR] 2020-05-10 10:12:10.241536: Testing 96.249.237.205:6100 ...

run_handshake.py

Sends a handshake message to the remote peer. The peer should reply with a simple structure containing its genesis block ID and protocol version number.

python3 ./run_handshake.py 95.179.188.245:3000
{'version': 1, 'block0': 'jk0qND89z5MwrZA1s+jRaOZyiQQmLyxDSk+Pk07HtnY='}

python3 ./run_handshake.py 95.179.188.245:3000 --format YAML
block0: jk0qND89z5MwrZA1s+jRaOZyiQQmLyxDSk+Pk07HtnY=
version: 1

run_tip.py

Fetch remote peer’s current chain tip.

python3 ./run_tip.py 95.179.188.245:3000
{'blockHeader': 'AAIAAAAAAAAAkAAAppYAB+B4DldRwCblQ7Loqy6wYJnaodHl30d3j3eH+qtFzfEv46jfmJ9A5/twvtVi36/9J1rQw64dzK9oLCmrUH/0qxw1RxOq+2DzPzmy5RO2BhpJv5TIgyJg7MkjM3no1he8ULPOhBtpGf4U6fgl+UfyHAF8kDhs1sV343vzxsszBR4yTUmrEkyB88M0taUKEqHcumIFEL2Y/g7XOM5ESKuJpbZhCQ0kTMe+MUW0rJ8qP+tMAolSr3pdREucJ5kf1AZIfUAGAAAAAFpyShLzaP+8EXc/k4NJt3jcdgD/D7W9ZoSL58pdcB+QcAXqHp80/QWr9H+B5iBZl6Za/hxTqzOqth/deIDl8AymCb7a2hsbN2nYPwpq0CLjneYRmlg6PEMJ3wN0iFzjcn9XPQKtroeCSjJAJz191m+KKNqooXOEPvjm6x1A8TOWSipC9H9YTRqpY47B/jXv8R+92JNzpWHUAOp3dXYac41qfuf8gdTdPAzNTbQyGBx91Vm0pkxE1vTHQHIylloxmVPPc1YydedkCyxt+EQGY7qlj8qIixr789inJ3g95oNMhvBv+87wsntnuc0FFR2eHWbRMC2O/KKFV237ca5+tEtuaIXkx7ReiPFez/UTaYEkNIf1d2d8yRMsjA7VLpA9cmWFHFvFMKwpkeGzZ1pqrTiI3b1uDB9MFqqEAdKsZJ2aNzxgP+KchXQayk0jGeu5Lg8TYKnGPsLX3hqnIOHix72i1EoW41w4a4nVEQof6anxz6xNQNuROP0mOtWr//bcxCvY6SBHsLm2rdwAzv3la2EpA4H1y/7KZP7xDeYsT9GQsMC3U9rUjAiFM7UCAl+/4kcBZibsmaw+iIJJIPW91NJeU2Wf4g1u87PzRUu8xVCcMgYiAvqJGI7CTxdwGudKJQ=='}

run_fetch_peers.py

Attempts to fetch peers from a remote host, like a running Cardano node would.

[
{
"address": "/ip4/62.109.22.213/tcp/3100",
"id": "bc9afa9d75fc1731aa3028925bcad59523bd75025ca610ac"
},
{
"address": "/ip4/167.71.74.208/tcp/3000",
"id": "bab959898963d30044d0a74681b548c9381af85f551c348b"
},
{
"address": "/ip4/69.164.201.77/tcp/3000",
"id": "3901dc09b14c15c32445d84938714e435bfd8bd3c3f87a7d"
},
{
"address": "/ip4/18.219.181.172/tcp/9000",
"id": "86a79c909c3d68b0249f085b64f01331b03ea1ac0edab19b"
}
]

YAML format:

python3 ./run_fetch_peers.py 95.179.188.245:3000 --format YAML

- address: /ip4/159.203.118.149/tcp/3000
id: b16820f6b8896654fd5e651df9e0c47a12f0506b8804cb4e
- address: /ip4/13.58.50.56/tcp/9000
id: 1adf6969ac2aaedee97155f3b08383b8bee3fd2f37862485
- address: /ip4/18.224.171.160/tcp/9000
id: 1699780b3cc7cffe363d17ca7462352df7e71cb1823eb24f
- address: /ip4/93.190.141.157/tcp/3002
id: 7737db50b97521d6d3c3c31d51db69995062f73f7579ce0d
- address: /ip4/167.172.207.34/tcp/3301
id: 3ee2f611b9a99a13e35e11996d7d38e5ad986bdcfe1726aa

run_fetch_connected.py

Reads a list of local connections, logs or and produces JSON, CLI or YAML suitable to bootstrap a jormungandr node.

Uses netstat -tan to fetch a list of local connections, then generates random ID’s for each host.

The three output formats are suitable for config.yaml and CLI usage. The latter will output --trusted-peers <IPs> command line option for jormungandr

python3 ./run_fetch_connected.py --format YAML

- address: /ip4/3.127.17.18/tcp/3000
id: e147ced916b394eece1efd9cc3dfbf0173fbd29da23d22c1
- address: /ip4/185.170.114.129/tcp/3000
id: 4c2c0a37adb084280736b32a432c3fe1c71ecd0c89c3dd77
- address: /ip4/104.140.241.201/tcp/3000
id: c13f693e91ca166d06c876f56fc2ef402051060394e26cf0
- address: /ip4/3.125.75.156/tcp/3000
id: d02b240ae45f18ff358b128fd3fa062f0da3233a5cafc2c4
- address: /ip4/82.209.54.76/tcp/3000
id: a80c8f8ecb9b960c0604340f12fac45ef531887aef2e066a
- address: /ip4/34.223.43.234/tcp/3000
id: 824a6786fb19c89be649091a545c67a08369274600093a39
- address: /ip4/18.220.65.184/tcp/3000
id: 40231ee844b20236367c39d4b7e47519d964da8d51fa0eb4
- address: /ip4/52.44.60.23/tcp/3000
id: 34c5758609200c06eb111fd2243b920396fec3de36a9b17a

run_getblocks.py

Fetch the raw contents of a list blocks identified by a comma-separated list of block hashes.

python3 run_getblocks.py 127.0.0.1:3000 8e4d2a343f3dcf9330ad9035b3e8d168e6728904262f2c434a4f8f934ec7b676,52a04b633054063332f56e09e40a476ea5d0ca3419835f66d0b825cb79a5c14f

run_pullblockstotip.py

Pull blocks from an initial block hash all the way to the remote peer’s current chain tip.

python3 run_pullblockstotip.py 127.0.0.1:3000 8e4d2a343f3dcf9330ad9035b3e8d168e6728904262f2c434a4f8f934ec7b676,52a04b633054063332f56e09e40a476ea5d0ca3419835f66d0b825cb79a5c14f

run_getheaders.py

Get headers for a list of block ID’s specified in a comma delimited list.

python3 run_getheaders.py 127.0.0.1:3000 8e4d2a343f3dcf9330ad9035b3e8d168e6728904262f2c434a4f8f934ec7b676,52a04b633054063332f56e09e40a476ea5d0ca3419835f66d0b825cb79a5c14f

run_pullheaders.py

Pull headers for a range of blocks starting in the first block hash ID until the second block hash ID. Client must know starting and ending block.

python3 run_pullheaders.py 127.0.0.1:3000 745354e0d599252f7b21807381a34e23ccc1fd17169a1ea56e28c62ae3c1fd03 cf1f4029df6edbbd9491856ac0ccef6425cf37186a1cb4a64873728ad160d5ec

run_getfragments.py

Get fragments from their ID hashes. Not yet implemented in the jormungandr code.

python3 run_getfragments.py 127.0.0.1:3000 4f4a3d46c80ad6b8f644480739c6c5473bc628cd20ebcbd972d46bca3710d389

run_pushheaders.py

Push a raw block header to a peer.

From the original jormungandr documentation:

Sends headers of blocks to the service in response to a `missing` item received from the BlockSubscription response stream. The headers are streamed the in chronological order of the chain.

python3 run_pushheaders.py 127.0.0.1:3000 <raw_header_bytes>

run_uploadblock.py

Upload a raw block to a peer.

From the original jormungandr documentation:

Uploads blocks to the service in response to a `solicit` item received from the BlockSubscription response stream.

python3 run_uploadblock.py 127.0.0.1:3000 <raw_block_bytes>

run_blocksub.py

Subscribe to a remote Block stream.

python3 run_blocksub.py 127.0.0.1:3000 

run_fragmentsub.py

Subscribe to a remote Fragment stream.

python3 run_fragmentsub.py 127.0.0.1:3000 

run_gossipsub.py

Subscribe to a remote Gossip stream.

python3 run_gossipsub.py 127.0.0.1:3000 

Source Code

Browse crypto.bi CNT on Github

Browse other crypto.bi projects for cryptocurrency enthusiasts

License

crypto.bi CNT is open source software, licensed under the GPL v3 software license.

CNT is free to use and modify as you please.

We appreciate a mention of https://crypto.bi in case you find this software useful!

* This is not an official Cardano project. We’re in no way affiliated with IOHK, Cardano Foundation or any other official Cardano organization.

Meta