Simulate a simple blockchain on a real distributed network emulated on Mininet. For more information on Mininet, see the Mininet website or the Wiki.
Dependencies:
- Python 2.7.x
- pyzmq
Process to run in each host participating in the network. The script doesn't necessarily need to run on Mininet hosts, any machine could do it. Mininet only facilitates the network and usage of multiple nodes.
$ ./node.py -i 10.0.0.1 -p 9000 --peers 10.0.0.2 10.0.0.3 --log=debug --miner
Arguments:
-i
IP address of this node in the network-p
port to listen to peers (defaults to 9000)--peers
list of peers IP addresses that the node will try to connect--miner
flag to start this node also executing the mining process--log
console log level
$ ./node.py -h
usage: node.py [-h] [-i ip] [-p port] [--peers [PEERS [PEERS ...]]] [--miner]
[--log [LOGLEVEL]] [-c CONFIG_FILE]
Blockchain simulation
optional arguments:
-h, --help show this help message and exit
-i ip, --ip ip Specify listen IP address
-p port, --port port Specify listen port
--peers [PEERS [PEERS ...]]
Specify peers IP addresses
--miner Start the node immediately mining
--log [LOGLEVEL] Set the logging output level ['CRITICAL', 'ERROR',
'WARNING', 'INFO', 'DEBUG']
-c CONFIG_FILE, --config CONFIG_FILE
Specify the configuration file
The optional configuration file should have INI format, here's an example:
# node.conf
[node]
# default ip 127.0.0.1
ip = 10.0.0.1
# default port 9000
port = 9090
# one peer each line
peers = 10.0.0.2
10.0.0.3
miner = false # true/false or yes/no
#loglevel = debug
This script is a simple single switch Mininet topology that runs node.py
in each emulated host with private directories.
More complex networks are also possible, but the user should ensure the connectivity.
Arguments:
- number of hosts on switch (pending)
Example:
$ sudo python simpleNet.py 10
*** Creating network
*** Adding controller
*** Adding hosts and stations:
h1 h2 h3 h4 h5 h6 h7 h8 h9 h10
*** Adding switches and access point(s):
s1
*** Adding link(s):
(h1, s1) (h2, s1) (h3, s1) (h4, s1) (h5, s1) (h6, s1) (h7, s1) (h8, s1) (h9, s1) (h10, s1)
*** Configuring hosts
*** Starting controller(s)
c0
*** Starting switches and/or access points
s1 ...
*** Blockchain node starting on h1
*** Blockchain node starting on h2
*** Blockchain node starting on h3
*** Blockchain node starting on h4
*** Blockchain node starting on h5
*** Blockchain node starting on h6
*** Blockchain node starting on h7
*** Blockchain node starting on h8
*** Blockchain node starting on h9
*** Blockchain node starting on h10
*** Starting CLI:
mininet>
After this you can execute commands on hosts through the mininet CLI, or even access each host terminal.
mininet> h1 rpc/rpcclient.py getlastblock
{
"nonce": "214074",
"index": "132",
"hash": "00000223e62597da220d29f46d1f309d8db8a573b8474b01d26b1909ea9c42d0",
"tx": "\u001e",
"timestamp": "2018-11-23 08:54:14.682075",
"merkle_root": "9652595f37edd08c51dfa26567e6cd76e6fa2709c3e578478ca398d316837a7a",
"prev_hash": "0000095b7a0e31959780884b0d81b062a21f2a2a34a0ae40538d5795330a85ac"
}
mininet> h5 rpc/rpcclient.py getlastblock
{
"nonce": "214074",
"index": "132",
"hash": "00000223e62597da220d29f46d1f309d8db8a573b8474b01d26b1909ea9c42d0",
"tx": "\u001e",
"timestamp": "2018-11-23 08:54:14.682075",
"merkle_root": "9652595f37edd08c51dfa26567e6cd76e6fa2709c3e578478ca398d316837a7a",
"prev_hash": "0000095b7a0e31959780884b0d81b062a21f2a2a34a0ae40538d5795330a85ac"
}
mininet> h9 rpc/rpcclient.py getblocks 131 132
{
"nonce": "688688",
"index": "131",
"hash": "0000095b7a0e31959780884b0d81b062a21f2a2a34a0ae40538d5795330a85ac",
"tx": " ",
"timestamp": "2018-11-23 08:54:11.136267",
"merkle_root": "36a9e7f1c95b82ffb99743e0c5c4ce95d83c9a430aac59f84ef3cbfab6145068",
"prev_hash": "000001f7d66514ed999b044c87371f455273b00b0b683016265864bd8c06bc47"
}
{
"nonce": "214074",
"index": "132",
"hash": "00000223e62597da220d29f46d1f309d8db8a573b8474b01d26b1909ea9c42d0",
"tx": "\u001e",
"timestamp": "2018-11-23 08:54:14.682075",
"merkle_root": "9652595f37edd08c51dfa26567e6cd76e6fa2709c3e578478ca398d316837a7a",
"prev_hash": "0000095b7a0e31959780884b0d81b062a21f2a2a34a0ae40538d5795330a85ac"
}
Localhost client to communicate with the node process and obtain blockchain info
Arguments:
getlastblock
last block on the chainaddpeer X
add X peer IP and connect to itremovepeer X
remove X peer and disconnectgetblock X
block X informationgetblocks X Y
blocks X to Y informationgetpeerinfo
IP of all connected peersstartmining
start mining on the nodestopmining
stop mining on the nodeexit
stop node process
$ ./rpc/rpcclient.py -h
usage: ./rpc/rpcclient.py [-h]
<command> [<args>]
Blockchain RPC client
These are the commands available:
getlastblock Print the last block info
getblock <index> Print the block info with index <index>
getblocks <list> Print the blocks info from index <list>
startmining Start the miner thread
stopmining Stop the miner thread
addpeer <ip> Add <ip> to the node peers list
removepeer <ip> Remove <ip> to the node peers list
getpeerinfo Print the peers list
exit Terminate and exit the node.py program running
Examples:
$ ./rpc/rpcclient.py getlastblock
{
"nonce": "0",
"index": "0",
"hash": "adbc2423894ab7d91ab583be0e660aa92673ec6445f026a9aeed4289e5ed6fe3",
"tx": "",
"timestamp": "2018-10-10 00:00:0.0",
"merkle_root": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
"prev_hash": ""
}
$ ./rpc/rpcclient.py startmining
Starting mining...
$ ./rpc/rpcclient.py stopmining
Stopping mining...
$ ./rpc/rpcclient.py getlastblock
{
"nonce": "3117090",
"index": "2",
"hash": "00000e1164cd1e93becf31b16c1ab66e7370e4265a5cfc9c6028ebb81c7bd913",
"tx": "\n",
"timestamp": "2018-12-02 20:47:11.589315",
"merkle_root": "01ba4719c80b6fe911b091a7c05124b64eeece964e09c058ef8f9805daca546b",
"prev_hash": "00000d354ffca98697c2804202d79a179f5e4e3ab6f5edb87a0c1f3d47810df6"
}
$ ./rpc/rpcclient.py exit
Exiting...