Proof of concept for ISAAC consensus protocol
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
.github
examples
scripts
src
.flake8
.gitignore
.travis.yml
CONTRIBUTING.md
LICENSE
README.md
conftest.py
requirements.txt
setup.py

README.md

ISAAC Consensus Protocol

Official implementation of ISAAC protocol based on the consensus model of mFBA

Build Status

Notice

This is not a repository for running a node. This is only a proof of concept for BOSCoin's ISAAC consensus protocol. Feel free to test.

Installation

To install and deploy the source, you need to install these packages,

  • python: 3.6 or higher
  • pip

Once the dependencies are installed, clone this repository and run.

$ python setup.py develop

Deployment

$ run-blockchain.py -h
usage: run-blockchain.py [-h] [-verbose]
                         [-log-level {critical,fatal,error,warn,warning,info,debug}]
                         [-log-output LOG_OUTPUT]
                         [-log-output-metric LOG_OUTPUT_METRIC]
                         [-log-show-line] [-log-no-color]
                         conf

positional arguments:
  conf                  ini config file for server node

optional arguments:
  -h, --help            show this help message and exit
  -verbose              verbose log (default: False)
  -log-level {critical,fatal,error,warn,warning,info,debug}
                        set log level (default: debug)
  -log-output LOG_OUTPUT
                        set log output file (default: None)
  -log-output-metric LOG_OUTPUT_METRIC
                        set metric output file (default: None)
  -log-show-line        show seperate lines in log (default: False)
  -log-no-color         disable colorized log message by level (default:
                        False)

Running Node Server

Set the config file.

$ run-blockchain.py examples/node5001.ini
2017-12-06 15:21:48,459 - __main__ - DEBUG - Node ID: 5001
2017-12-06 15:21:48,459 - __main__ - DEBUG - Node PORT: 5001
2017-12-06 15:21:48,459 - __main__ - DEBUG - Validators: ['localhost:5002', 'localhost:5003']

Run the other nodes like this.

$ run-blockchain.py examples/node5002.ini
$ run-blockchain.py examples/node5003.ini

Running Message Client, run-client.py

$ run-client.py  -h
usage: run-client.py [-h] [-verbose]
                     [-log-level {critical,fatal,error,warn,warning,info,debug}]
                     [-log-output LOG_OUTPUT]
                     [-log-output-metric LOG_OUTPUT_METRIC] [-log-show-line]
                     [-log-no-color] [-m MESSAGE] [-i IP] [-p PORT]

optional arguments:
  -h, --help            show this help message and exit
  -verbose              verbose log (default: False)
  -log-level {critical,fatal,error,warn,warning,info,debug}
                        set log level (default: debug)
  -log-output LOG_OUTPUT
                        set log output file (default: None)
  -log-output-metric LOG_OUTPUT_METRIC
                        set metric output file (default: None)
  -log-show-line        show seperate lines in log (default: False)
  -log-no-color         disable colorized log message by level (default:
                        False)
  -m MESSAGE, --message MESSAGE
                        Messages you want to send to the server (default:
                        Quaerat)
  -i IP, --ip IP        Server IP you want to send the message to (default:
                        localhost)
  -p PORT, --port PORT  Server port you want to send the message to (default:
                        5001)

After checking node state in the cmd line, run the run-client.py to send a message to node '5001' as below.

$ run-client.py --ip "localhost" --port 5001 --message "message"

Send five messages at a time every 4 seconds to node 5001

$ for i in $(seq 5)
do
    run-client.py \
        --ip localhost \
        --port 5001 \
        --message "message-$i"
        sleep 4
done

Send five messages at a time every 4 seconds to node 5001 and 5002,

$ for port in 5001 5002
do
    for i in $(seq 5)
    do
        run-client.py \
            --ip localhost \
            --port $port \
            --message "message-$i"
            sleep 4
    done
done

Send five messages at a time every 4 seconds to 5000-5003 randomly three times

$ for _ in $(seq 3)
do
    p=$(expr $RANDOM % 4)
    for i in $(seq 5)
    do
        run-client.py \
            --ip localhost \
            --port "500$p" \
            --message "message-$i"
            sleep 4
    done
done

Test

$ pytest
$ flake8

Examples

See the examples.

send-message.py

Before running this script, please run python setup.py develop.

$ send-message.py -h
usage: send-message.py [-h] [-verbose]
                       [-log-level {critical,fatal,error,warn,warning,info,debug}]
                       [-log-output LOG_OUTPUT]
                       [-log-output-metric LOG_OUTPUT_METRIC] [-log-show-line]
                       [-log-no-color]
                       endpoints [endpoints ...] [message]

positional arguments:
  endpoints             endpoints and it's number of messages, you want to
                        send; ex) http://localhost:80?m=5
                        http://localhost:80?m=10
  message               Messages you want to send to the server (default:
                        None)

optional arguments:
  -h, --help            show this help message and exit
  -verbose              verbose log (default: False)
  -log-level {critical,fatal,error,warn,warning,info,debug}
                        set log level (default: debug)
  -log-output LOG_OUTPUT
                        set log output file (default: None)
  -log-output-metric LOG_OUTPUT_METRIC
                        set metric output file (default: None)
  -log-show-line        show seperate lines in log (default: False)
  -log-no-color         disable colorized log message by level (default:
                        False)

This script will try to send messages to multiple nodes simultaneously.

This will send one random message to http://localhost:54320.

$ send-message.py http://localhost:54320

This will send one random message to http://localhost:54320 and http://localhost:54321 at the same time.

$ send-message.py http://localhost:54320 http://localhost:54321

You can set the number of messages for each node. For example, this will send 9 random messages to http://localhost:54320 and 10 random messages to http://localhost:54321.

$ send-message.py http://localhost:54320?m=9 http://localhost:54321?m=10

metric-analyzer.py

This simple script will try to analyze the metric messages from node. Mainly this will handle below issues,

  • node activity
  • fault tolerance for nodes
  • safety between quorum(2 nodes)
  • liveness between quorum(2 nodes)

The terminology of these terms are described in the BOSCoin official homepage. The interesting thing is that to check the health of quorum, this script will create a superset in all the validators and compose the quorum with each 2 nodes.

Usage

Before running the metric-analyzer.py, the 'metric' messages from running nodes should be stored in an output file.

For example, metric logs can be generated in /tmp/metric.json by the following scripts

$ run-blockchain.py examples/node5001.ini -log-output-metric /tmp/metric.json
$ run-blockchain.py examples/node5002.ini -log-output-metric /tmp/metric.json
$ run-blockchain.py examples/node5003.ini -log-output-metric /tmp/metric.json
$ run-blockchain.py examples/node5004.ini -log-output-metric /tmp/metric.json

Then send messages to nodes.

$ for port in 5001 5002 5003 5004
do
    for i in $(seq 5)
    do
        python scripts/run-client.py \
            --ip localhost \
            --port $port \
            --message "message-$i"
            sleep 2
    done
done
$ metric-analyzer.py -h
usage: metric-analyzer.py [-h] [-verbose]
                          [-log-level {critical,fatal,error,warn,warning,info,debug}]
                          [-log-output LOG_OUTPUT]
                          [-log-output-metric LOG_OUTPUT_METRIC]
                          [-log-show-line] [-log-no-color] [-type TYPE]
                          [-nodes NODES] [-node NODE]
                          [metric]

positional arguments:
  metric                metric file (default: None)

optional arguments:
  -h, --help            show this help message and exit
  -verbose              verbose log (default: False)
  -log-level {critical,fatal,error,warn,warning,info,debug}
                        set log level (default: debug)
  -log-output LOG_OUTPUT
                        set log output file (default: None)
  -log-output-metric LOG_OUTPUT_METRIC
                        set metric output file (default: None)
  -log-show-line        show seperate lines in log (default: False)
  -log-no-color         disable colorized log message by level (default:
                        False)
  -type TYPE        set the analyzer type to be shown
                        (dict_keys(['history', 'safety', 'fault-tolerance']))
                        (default: None)
  -nodes NODES          set the nodes to be shown (default: None)

If you have /tmp/metric.json,

$ metric-analyzer.py /tmp/metric.json

You can filter multiple types as you want. For example the following script will only show the results for safety and fault tolerance of node 5001.

$ metric-analyzer.py -type safety,fault-tolerance -nodes 5001 /tmp/metric.json