Usage¶
In this section we will guide you through deploying an application on top of Babble using the socket interface. Babble comes with the Dummy application which is used in this demonstration. It is a simple chat application where users write messages on a channel and Babble guarantees that everyone sees the same messages in the same order.
Docker¶
We have provided a series of scripts to bootstrap a demo. Let us first use the easy method to view the demo and then we will take a closer look at what is happening behind the scenes.
Make sure you have Docker installed.
The demo will pull Docker images from our official public Docker registry
[...]/babble$ cd demo
[...]/babble/demo$ make
Once the testnet is started, a script is automatically launched to monitor consensus figures:
consensus_events:180 consensus_transactions:40 events_per_second:0.00 id:1 last_block_index:3 last_consensus_round:17 num_peers:3 round_events:7 rounds_per_second:0.00 state:Babbling sync_rate:1.00 transaction_pool:0 undetermined_events:18
consensus_events:180 consensus_transactions:40 events_per_second:0.00 id:3 last_block_index:3 last_consensus_round:17 num_peers:3 round_events:7 rounds_per_second:0.00 state:Babbling sync_rate:1.00 transaction_pool:0 undetermined_events:20
consensus_events:180 consensus_transactions:40 events_per_second:0.00 id:2 last_block_index:3 last_consensus_round:17 num_peers:3 round_events:7 rounds_per_second:0.00 state:Babbling sync_rate:1.00 transaction_pool:0 undetermined_events:21
consensus_events:180 consensus_transactions:40 events_per_second:0.00 id:0 last_block_index:3 last_consensus_round:17 num_peers:3 round_events:7 rounds_per_second:0.00 state:Babbling sync_rate:1.00 transaction_pool:0 undetermined_events:20
Running docker ps -a
will show you that 9 docker containers have
been launched:
[...]/babble/demo$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ba80ef275f22 mosaicnetworks/watcher "/watch.sh" 48 seconds ago Up 7 seconds watcher
4620ed62a67d mosaicnetworks/dummy "dummy '--name=client" 49 seconds ago Up 48 seconds 1339/tcp client4
847ea77bd7fc mosaicnetworks/babble "babble run --cache_s" 50 seconds ago Up 49 seconds 80/tcp, 1337-1338/tcp node4
11df03bf9690 mosaicnetworks/dummy "dummy '--name=client" 51 seconds ago Up 50 seconds 1339/tcp client3
00af002747ca mosaicnetworks/babble "babble run --cache_s" 52 seconds ago Up 50 seconds 80/tcp, 1337-1338/tcp node3
b2011d3d65bb mosaicnetworks/dummy "dummy '--name=client" 53 seconds ago Up 51 seconds 1339/tcp client2
e953b50bc1db mosaicnetworks/babble "babble run --cache_s" 53 seconds ago Up 52 seconds 80/tcp, 1337-1338/tcp node2
0c9dd65de193 mosaicnetworks/dummy "dummy '--name=client" 54 seconds ago Up 53 seconds 1339/tcp client1
d1f4e5008d4d mosaicnetworks/babble "babble run --cache_s" 55 seconds ago Up 54 seconds 80/tcp, 1337-1338/tcp node1
Indeed, each node is comprised of an App and a Babble node (cf Design section).
The watcher
container monitors consensus figures.
Run the demo
script to play with the Dummy App
which is a simple chat
application powered by the Babble consensus platform:
[...]/babble/demo$ make demo
Finally, stop the testnet:
[...]/babble/demo$ make stop
Manual Setup¶
The above scripts hide a lot of the work required for setting up a Babble network. They generate the configuration files automatically, copy them to the right places and launch the nodes in Docker containers. We recommend looking at these scripts closely to understand how the demo works. Here, we will attempt to explain the individual steps that take place behind the scenes.
Configuration¶
Babble reads configuration from the directory specified by the datadir
flag
which defaults to ~/.babble
on UNIX systems. This directory should contain
the following files:
priv_key
: The private key of the validator runnning the node.peers.json
: The current validator-set.genesis.peers.json
: (optional, default peers.json) The initial validator-set of the network.
Keys¶
Every participant has a cryptographic key-pair that it uses to encrypt, sign and verify messages. The private key is secret but the public key is used by other nodes to verify messages signed with the private key.
The encryption scheme used by Babble is ECDSA with the secp256k1 curve (like Bitcoin and Ethereum).
Babble’s keygen
command can be used to generate key-pairs in the
appropriate format.
Peers¶
peers.json
and genesis.peers.json
are used to determine the current and
initial validator-sets of a network.
genesis.peers.json
corresponds to the initial validator-set; the one that
the hashgraph was started with. If genesis.peers.json
is not provided,
Babble will use peers.json
as the genesis validator-set.
peers.json
corresponds to the current validator-set. These are the nodes
that are allowed to record new Events in the hashgraph, and who will gossip
among each other.
peers.json
and gensesis.peers.json
are not necessarily equal because
the dynamic membership protocol enables new nodes to
join or leave a live Babble network dynamically. It is important for a joining
node to know the initial validator-set in order to replay and verify the
hashgraph up to the point where it joins.
It is possible to start a Babble network with just a single node, or with a predefined validator-set composed of multiple nodes.
In the latter case, someone, or some process, needs to aggregate the public
keys and network addresses of all participants into a single file
(peers.genesisjson
), and ensure that everyone has a copy of this file. It is
left to the user to derive a scheme to produce the configuration files but the
docker demo scripts are a good place to start.
Example¶
Let us say I want to participate in a Babble network. I am going to start by
running babble keygen
to create a key-pair:
babble keygen
Your private key has been saved to: /home/[user]/.babble/priv_key
Your public key has been saved to: /home/[user]/.babble/key.pub
Next, I am going to copy the public key (key.pub) and communicate it to whoever is responsible for producing the peers.json file. At the same time, I will tell them that I am going to be listening on 172.77.5.2:1337. You may also optionally supply a moniker for each node, which is far more readable than a public key address.
Suppose three other people do the same thing. The resulting peers.json file could look something like this:
[
{
"NetAddr":"172.77.5.1:1337",
"PubKeyHex":"0x0471AEE3CAE4E8442D37C9F5481FB32C4531511988652DF923B79ED4ED992021183D31E0F6FBFE96D89B6D03D7250292DFECD4FC414D83A5C38FA3FAD0D8572864",
"Moniker":"node1"
},
{
"NetAddr":"172.77.5.2:1337",
"PubKeyHex":"0x045E034D73C849756AE7B6515CA60D96A5A911B13A4D8B45BC0E0B02EDB45009DF6CCC074EEB6F7C6795740F993664EDEE970F8A717C89344F8437F412BDF0D17C",
"Moniker":"node2"
},
{
"NetAddr":"172.77.5.3:1337",
"PubKeyHex":"0x047CCCD40D90B331C64CE27911D3A31AF7DC16C1EA6D570FDC2120920663E0A678D7B5D0C19B6A77FEA829F8198F4F487B68206B93B7AD17D7C49CA7E0164D0033",
"Moniker":"node3"
},
{
"NetAddr":"172.77.5.4:1337",
"PubKeyHex":"0x0406CB5043E7337700E3B154993C872B1C61A84B1A739528C4A10135A3D64939C094B4A999BD21C3D5E9E9ECF15B202414F073795C9483B2F51ADA7EE59EB5EAC4",
"Moniker":"node4"
}
]
Now everyone is going to take a copy of this peers.json file and put it in a folder together with the priv_key file they generated in the previous step. That is the folder that they need to specify as the datadir when they run Babble.
Babble Executable¶
Let us take a look at the help provided by the Babble CLI:
Run node
Usage:
babble run [flags]
Flags:
-a, --advertise string Advertise IP:Port for babble node
--bootstrap Load from database
--cache-size int Number of items in LRU caches (default 10000)
-c, --client-connect string IP:Port to connect to client (default "127.0.0.1:1339")
--datadir string Top-level directory for configuration and data (default "/home/martin/.babble")
--db string Dabatabase directory (default "/home/martin/.babble/badger_db")
--fast-sync Enable FastSync
--heartbeat duration Timer frequency when there is something to gossip about (default 10ms)
-h, --help help for run
-j, --join-timeout duration Join Timeout (default 10s)
-l, --listen string Listen IP:Port for babble node (default "127.0.0.1:1337")
--log string debug, info, warn, error, fatal, panic (default "debug")
-R, --maintenance-mode Start Babble in a suspended (non-gossipping) state
--max-pool int Connection pool size max (default 2)
--moniker string Optional name
--no-service Disable HTTP service
-p, --proxy-listen string Listen IP:Port for babble proxy (default "127.0.0.1:1338")
-s, --service-listen string Listen IP:Port for HTTP service (default "127.0.0.1:8000")
--signal-addr string IP:Port of WebRTC signaling server (default "127.0.0.1:2443")
--signal-skip-verify (Insecure) Accept any certificate presented by the signal server
--slow-heartbeat duration Timer frequency when there is nothing to gossip about (default 1s)
--store Use badgerDB instead of in-mem DB
--suspend-limit int Limit of undetermined events (per node) before entering suspended state (default 100)
--sync-limit int Max number of events for sync (default 1000)
-t, --timeout duration TCP Timeout (default 1s)
--webrtc Use WebRTC transport
The listen
flag controls the local address:port where this node gossips with
other nodes. If the node is running behind some kind of NAT, it is possilbe to
advertise a different address with the advertise
flag. If advertise
is
not specified, the node defaults to using the listen
address. By default
listen
is 127.0.0.1:1337
, meaning that Babble will bind to the loopback
addresse on the local machine.
As we explained in the architecture section, each Babble node works in conjunction with an application for which it orders transactions. When Babble and the application are connected by a TCP interface, we specify two other endpoints:
proxy-listen
: where Babble listens for transactions from the Appclient-connect
: where the App listens for transactions from Babble
We can also specify where Babble exposes its HTTP API providing information on
the Hashgraph and Blockchain data store. This is controlled by the optional
service-listen
flag.
The fast-sync
parameter determines whether or not the node will attempt to
fast-forward to the tip of the hashgraph, or download and replay the entire
hashgraph from start. More on this in fast-sync
We can choose to run Babble with a database backend or only with an in-memory
cache. With the store
flag set, Babble will look for a database file in
datadir
/babdger_db or in the path specified by db
. If the database
already exists, and the --boostrap
flag is set, the node will load the
database and bootstrap itself to a state consistent with the database and it
will be able to proceed with the consensus algorithm from there. If the database
does not exist yet, or the --bootstrap
flag is not set, a new one will be
created and the node will start from a clean state.
The node can also be started in maintenance-mode
with the homonymous flag.
The node is started normally but goes straight into the Suspended
state,
where it still responds to sync-requests, and service API requests, but does
not produce or insert new Events in the underlying hashgraph. The Suspended
state is also triggered automatically when more than suspend-limit
undetermined-events were created since last starting the node. This is a
safeguard against runaway conditions when a network does not have a strong
majority and produces undetermined-events ad infinitum.
Here is how the Docker demo starts Babble nodes together wth the Dummy application:
for i in $(seq 1 $N)
do
docker run -d --name=client$i --net=babblenet --ip=172.77.10.$i -it mosaicnetworks/dummy:latest \
--name="client $i" \
--client-listen="172.77.10.$i:1339" \
--proxy-connect="172.77.5.$i:1338" \
--discard \
--log="debug"
done
for i in $(seq 1 $N)
do
docker create --name=node$i --net=babblenet --ip=172.77.5.$i mosaicnetworks/babble:latest run \
--heartbeat=100ms \
--moniker="node$i" \
--cache-size=50000 \
--listen="172.77.5.$i:1337" \
--proxy-listen="172.77.5.$i:1338" \
--client-connect="172.77.10.$i:1339" \
--service-listen="172.77.5.$i:80" \
--sync-limit=500 \
--fast-sync=$FASTSYNC \
--store \
--log="debug"
docker cp $MPWD/conf/node$i node$i:/.babble
docker start node$i
done
Stats, blocks and Logs¶
Once a node is up and running, we can call the stats
endpoint exposed
by the HTTP service:
curl -s http://172.77.5.1:80/stats
Or request to see a specific block:
curl -s http://172.77.5.1:80/block/1
Or we can look at the logs produced by Babble:
docker logs node1
We can look at the current state of docker containers:
docker ps --all