|
| 1 | +# BABBLE |
| 2 | +## Consensus platform for distributed applications. |
| 3 | + |
| 4 | +Nodes in a distributed application require a component to communicate and order |
| 5 | +transactions before they get applied locally. Babble is a plug and play solution |
| 6 | +for this component. It uses the Hashgraph consensus algorithm which is optimal |
| 7 | +in terms of fault tolerance and messaging. |
| 8 | + |
| 9 | +## Architecture |
| 10 | +``` |
| 11 | + ======================================== |
| 12 | + = APP = |
| 13 | + = = |
| 14 | + = =============== ============== = |
| 15 | + = = Service = <-- = State = = |
| 16 | + = = = = = = |
| 17 | + = =============== ============== = |
| 18 | + = | | = |
| 19 | + = ======================== = |
| 20 | + = = Babble Proxy = = |
| 21 | + = ======================== = |
| 22 | + = | ^ = |
| 23 | + ===========|================|=========== |
| 24 | + | | |
| 25 | +--------- SubmitTx(tx) ---- CommitTx(tx) ------- |
| 26 | + | | |
| 27 | + ==============|================|=============== |
| 28 | + = BABBLE | | = |
| 29 | + = v | = |
| 30 | + = ======================== = |
| 31 | + = = App Proxy = = |
| 32 | + = = = = |
| 33 | + = ======================== = |
| 34 | + = | = |
| 35 | + = ======================================= = |
| 36 | + = = Core = = |
| 37 | + = = = = |
| 38 | + = = ============= =========== = = |
| 39 | + = = = Hashgraph = = Store = = = |
| 40 | + = = ============= =========== = = |
| 41 | + = = = = |
| 42 | + = ======================================= = |
| 43 | + = | = |
| 44 | + = ======================================= = |
| 45 | + = = Transport = = |
| 46 | + = = = = |
| 47 | + = ======================================= = |
| 48 | + = ^ = |
| 49 | + ======================|======================== |
| 50 | + | |
| 51 | + v |
| 52 | + |
| 53 | + Network |
| 54 | +``` |
| 55 | + |
| 56 | +### Proxy |
| 57 | + |
| 58 | +The Babble node and the App are loosely coupled and can run in separate processes. |
| 59 | +They communicate via a very simple **JSON-RPC** interface over a **TCP** connection. |
| 60 | + |
| 61 | +The App submits transactions for consensus ordering via the **SubmitTx** endpoint |
| 62 | +exposed by the **App Proxy**. Babble asynchrously processes transactions and |
| 63 | +eventually feeds them back to the App, in consensus order, with a **CommitTx** |
| 64 | +message. |
| 65 | + |
| 66 | +Transactions are represented as raw bytes and Babble does not need to know what |
| 67 | +they represent. Therefore, encoding and decoding transactions is done by the App. |
| 68 | + |
| 69 | +Apps must implement their own **Babble Proxy** to submit and receive committed |
| 70 | +transactions from Babble. The advantage of using a JSON-RPC API is that there is |
| 71 | +no restriction on the programming language for the App. It only requires a component |
| 72 | +that sends SubmitTx messages to Babble and exposes a TCP enpoint where Babble can |
| 73 | +send CommitTx messages. |
| 74 | + |
| 75 | +When launching a Babble node, one must specify the address and port exposed by the |
| 76 | +Babble Proxy of the App. Is is also possible to configure which address and port |
| 77 | +the App Proxy exposes. |
| 78 | + |
| 79 | +### Transport |
| 80 | + |
| 81 | +Babble nodes communicate whith other Babble nodes in a fully connected Peer To Peer |
| 82 | +network. Nodes gossip by choosing another node at random and telling them evertying |
| 83 | +they know about the Hashgraph that the other doesnt. The gossip protocol is |
| 84 | +extremely simple and serves the dual purpose of gossiping about transactions and |
| 85 | +about the gossip itself (the Hashgraph). The Hashraph contains enough information |
| 86 | +to compute a consensus ordering of transactions. |
| 87 | + |
| 88 | +The communication mechansim is a custom RPC protocol over TCP connections. There |
| 89 | +are only two types of RPC commands, **Known** and **Sync**. For example, when |
| 90 | +node **A** wants to sync with node **B**, it starts by sending a **Known** request |
| 91 | +to **B**. **B** responds with what it knows about the Hashgraph. **A** computes what |
| 92 | +it knows that **B** doesnt and sends the diff with a **Sync** request. Upon receiving |
| 93 | +the **Sync** request, **B** updates its Hashgraph accordingly and calculates the |
| 94 | +consensus order. |
| 95 | + |
| 96 | +The list of peers must be predefined and known to all peers. At the moment, it is |
| 97 | +not possible to dynamically modify the list of peers while the network is running |
| 98 | +but this is not a limitation of the Hashgraph algorithm, just an implemention |
| 99 | +prioritization. |
| 100 | + |
| 101 | +### Core |
| 102 | + |
| 103 | +The core of Babble is the component that maintains and computes the Hashgraph. |
| 104 | +The consensus algorithm, invented by Leemon Baird, is best described in the [white-paper](http://www.swirlds.com/downloads/SWIRLDS-TR-2016-01.pdf) |
| 105 | +and its [accompanying document](http://www.swirlds.com/downloads/SWIRLDS-TR-2016-02.pdf). |
| 106 | + |
| 107 | +The Hashgraph itself is a data structure that contains all the information about |
| 108 | +the history of the gossip and thereby grows and grows in size as gossip spreads. |
| 109 | +There are various strategies to keep the size of the Hashgraph limited. In our |
| 110 | +implementation, the **Hashgraph** object has a dependency on a **Store** object |
| 111 | +which contains the actual data and is abstracted behind an interface. |
| 112 | + |
| 113 | +The current implementation of the **Store** interface uses a set of in-memory LRU |
| 114 | +caches which can be extended to persist stale items to disk. The size of the LRU |
| 115 | +caches is configurable. |
| 116 | + |
| 117 | +## Usage |
| 118 | + |
| 119 | +### Go |
| 120 | +Babble is written in [Golang](https://golang.org/). Hence, the first step is to install Go which is both |
| 121 | +the programming language and a CLI tool for managing Go code. Go is very opinionated |
| 122 | +and will require you to [define a workspace](https://golang.org/doc/code.html#Workspaces) where all your gocode will reside. |
| 123 | + |
| 124 | +### Babble and dependencies |
| 125 | +Babble is a private repository on [Bitbucket](https://bitbucket.org). Get access rights from someone at |
| 126 | +Babble and clone the repository in the appropriate GOPATH subdirectory: |
| 127 | + |
| 128 | +```bash |
| 129 | +$ mkdir -p $GOPATH/src/bitbucket.org/mosaicnet/ |
| 130 | +$ cd $GOPATH/src/bitbucket.org/mosaicnet |
| 131 | +[...]/babble$ git clone https://[username]@bitbucket.org/mosaicnet/babble.git |
| 132 | +``` |
| 133 | +Replace **[username]** with whatever credentials you may have on Bitbucket. |
| 134 | + |
| 135 | +Babble uses [Glide](http://github.com/Masterminds/glide) to manage dependencies. |
| 136 | + |
| 137 | +```bash |
| 138 | +[...]/babble$ sudo add-apt-repository ppa:masterminds/glide && sudo apt-get update |
| 139 | +[...]/babble$ sudo apt-get install glide |
| 140 | +[...]/babble$ glide install |
| 141 | +``` |
| 142 | +This will download all dependencies and put them in the **vendor** folder. |
| 143 | + |
| 144 | +### Testing |
| 145 | + |
| 146 | +Babble has extensive unit-testing. Use the Go tool to run tests: |
| 147 | +```bash |
| 148 | +[...]/babble$ go test $(glide novendor) |
| 149 | +``` |
| 150 | + |
| 151 | +If everything goes well, it should output something along these lines: |
| 152 | +``` |
| 153 | +ok bitbucket.org/mosaicnet/babble/net 0.052s |
| 154 | +ok bitbucket.org/mosaicnet/babble/common 0.011s |
| 155 | +? bitbucket.org/mosaicnet/babble/cmd [no test files] |
| 156 | +? bitbucket.org/mosaicnet/babble/cmd/dummy_client [no test files] |
| 157 | +ok bitbucket.org/mosaicnet/babble/hashgraph 0.174s |
| 158 | +ok bitbucket.org/mosaicnet/babble/node 1.699s |
| 159 | +ok bitbucket.org/mosaicnet/babble/proxy 0.018s |
| 160 | +ok bitbucket.org/mosaicnet/babble/crypto 0.028s |
| 161 | +``` |
| 162 | + |
| 163 | +### Docker Testnet |
| 164 | + |
| 165 | +To see Babble in action, we have provided a series of scripts to bootstrap a |
| 166 | +test network of four nodes locally. |
| 167 | + |
| 168 | +Make sure you have [Docker](https://docker.com) installed. |
| 169 | + |
| 170 | +Then, run the testnet: |
| 171 | + |
| 172 | +```bash |
| 173 | +[...]/babble$ cd docker |
| 174 | +[...]/babble/docker$ ./build-images |
| 175 | +[...]/babble/docker$ ./run-testnet |
| 176 | + |
| 177 | +``` |
| 178 | + |
| 179 | +Running ```docker ps -a``` will show you that 8 docker containers have been launched: |
| 180 | +``` |
| 181 | +[...]/babble/docker$ docker ps -a |
| 182 | +CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES |
| 183 | +9e4c863c9e83 dummy "dummy '--name=cli..." 9 seconds ago Up 8 seconds 1339/tcp client4 |
| 184 | +40c92938a986 babble "babble run --cach..." 10 seconds ago Up 9 seconds 1337-1338/tcp node4 |
| 185 | +4c1eb201d29d dummy "dummy '--name=cli..." 10 seconds ago Up 9 seconds 1339/tcp client3 |
| 186 | +cda62387e4fd babble "babble run --cach..." 11 seconds ago Up 9 seconds 1337-1338/tcp node3 |
| 187 | +765c73d66bcf dummy "dummy '--name=cli..." 11 seconds ago Up 10 seconds 1339/tcp client2 |
| 188 | +a6895aaa141a babble "babble run --cach..." 11 seconds ago Up 10 seconds 1337-1338/tcp node2 |
| 189 | +8f996e13eda7 dummy "dummy '--name=cli..." 12 seconds ago Up 11 seconds 1339/tcp client1 |
| 190 | +36c97a968d22 babble "babble run --cach..." 12 seconds ago Up 11 seconds 1337-1338/tcp node1 |
| 191 | +
|
| 192 | +``` |
| 193 | +Indeed, each node is comprised of an App and a Babble node (cf Architecture section). |
| 194 | + |
| 195 | +Run the **watch** script to monitor consensus figures: |
| 196 | +``` |
| 197 | +[...]/babble/docker$ ./watch |
| 198 | +node1: last_consensus_round=626 consensus_events=5106 consensus_transactions=0 transaction_pool=0 undetermined_events=23 events/s=9.64 sync_rate=0.99 |
| 199 | +node2: last_consensus_round=627 consensus_events=5115 consensus_transactions=0 transaction_pool=0 undetermined_events=18 events/s=9.68 sync_rate=0.98 |
| 200 | +node3: last_consensus_round=627 consensus_events=5115 consensus_transactions=0 transaction_pool=0 undetermined_events=18 events/s=9.69 sync_rate=0.98 |
| 201 | +node4: last_consensus_round=627 consensus_events=5115 consensus_transactions=0 transaction_pool=0 undetermined_events=19 events/s=9.70 sync_rate=0.99 |
| 202 | +
|
| 203 | +``` |
| 204 | + |
| 205 | +Run the **demo** scipt to play with the **Dummy App** which is a simple chat application |
| 206 | +powered by the Babble consensus platform: |
| 207 | + |
| 208 | +``` |
| 209 | +[...]/babble/docker$ ./demo |
| 210 | +``` |
| 211 | + |
| 212 | + |
| 213 | + |
| 214 | +Finally, stop the testnet: |
| 215 | +``` |
| 216 | +[...]/babble/docker$ ./stop-testnet |
| 217 | +``` |
| 218 | + |
| 219 | +### Creating a Babble Network |
| 220 | + |
| 221 | +The files contained in the docker demo presented above should contain helpfull |
| 222 | +inforation to understand how Babble networks can be configured and implemented. |
| 223 | + |
| 224 | +Basically, the steps are as follows: |
| 225 | +1) Create a network of machines where the nodes will be deployed. Note the addresses |
| 226 | +and ports where each node will be listening for Babble messages. |
| 227 | +2) Create a private-public key pair for each node using the **babble keygen** utility. |
| 228 | + In production scenarios, you are more likely to ask each participant to generate |
| 229 | + their key pair and send you only the public key. Private keys are stored in |
| 230 | + individual **priv_key.pem** files and should remain secret. |
| 231 | +3) Create the **peers.json** file which contains the list of all participants. |
| 232 | +4) Copy the **peers.json** and **priv_key.pem** files in the appropritate folder |
| 233 | + on each node. |
| 234 | +5) Install Babble and App on nodes |
| 235 | +6) Run Babble with appropriate flags |
| 236 | + |
| 237 | + |
| 238 | +**Babble Keygen** is a utility that generates cryptographic key pairs in the |
| 239 | +format used by Babble. |
| 240 | + |
| 241 | +Example: |
| 242 | +``` |
| 243 | +$ babble keygen |
| 244 | +PublicKey: |
| 245 | +0x044CA00BEE8CBF2ABA4086D9C407F23223552951878DC63DEC3B8E9D127B29A4B79B4037563B690CEDABFE3A3A86DE9255577A0ABFF3357619E8789DD54A9A9F0B |
| 246 | +PrivateKey: |
| 247 | +-----BEGIN EC PRIVATE KEY----- |
| 248 | +MHcCAQEEIPCUYVgk3o5dTmT97MMgpHQKxK4AKb6KNwpjfe3eZdRVoAoGCCqGSM49 |
| 249 | +AwEHoUQDQgAETKAL7oy/KrpAhtnEB/IyI1UpUYeNxj3sO46dEnsppLebQDdWO2kM |
| 250 | +7av+OjqG3pJVV3oKv/M1dhnoeJ3VSpqfCw== |
| 251 | +-----END EC PRIVATE KEY----- |
| 252 | +``` |
| 253 | + |
| 254 | +One would typically extract the Private Key part and copy it into a **priv_key.pem** |
| 255 | +file. |
| 256 | + |
| 257 | +The **peers.json** file list all the participants in the network and identifies |
| 258 | +them by public key and address. |
| 259 | + |
| 260 | +Example peers.json file defining four peers: |
| 261 | +``` |
| 262 | +[ |
| 263 | + { |
| 264 | + "NetAddr":"172.77.5.1:1337", |
| 265 | + "PubKeyHex":"0x0445E0DA94DFC18BF38C8F0C95C1B21A2AE248CCD1CD490C83CDE9FF9FD43DEA7F59E294010386FDFE71F3FEDBCD6507803F49758733C349279610D54C3D82DD9B" |
| 266 | + }, |
| 267 | + { |
| 268 | + "NetAddr":"172.77.5.2:1337", |
| 269 | + "PubKeyHex":"0x04AF55528C5648AE08E3B7BB1F2FB0B6F758145DA3B489D3FBA122B92317E50D31E75834AA2F405421326C2F4B24868AB3578E09D26F6A4F243B631FA06A5645FA" |
| 270 | + }, |
| 271 | + { |
| 272 | + "NetAddr":"172.77.5.3:1337", |
| 273 | + "PubKeyHex":"0x044D9F2AD5A17CB1D15CACAACCA4306F565F8957A48E0D246330DEBC47B3385FF3F085D67AF02295400DE96062489B49420965BED0C2181309DEB4290FD307C01D" |
| 274 | + }, |
| 275 | + { |
| 276 | + "NetAddr":"172.77.5.4:1337", |
| 277 | + "PubKeyHex":"0x0475010E2F079A8012FBA55C7BEDB963950325822E6837B6AF21D92B3239C7E6C321BF3632BA365FEE2CA35DFC4B045A02DB10A501EEE4091EB8470B9012B44937" |
| 278 | + } |
| 279 | +] |
| 280 | +``` |
| 281 | +Each Babble node requires a **peers.json** and a **priv_key.pem** file. **peers.json** |
| 282 | +files must be identical but the **priv_key.pem** is unique to each node and must correspond |
| 283 | +to one of the public keys listed in the **peers.json** file. |
| 284 | + |
| 285 | +Both files must reside in the folder specified to Babbled by the **datadir** flag |
| 286 | +which default to ~/.babble on linux machines. |
| 287 | + |
| 288 | +```bash |
| 289 | +---:~/.babble$ tree |
| 290 | +. |
| 291 | +├── peers.json |
| 292 | +└── priv_key.pem |
| 293 | + |
| 294 | +``` |
| 295 | + |
| 296 | +Run a node |
| 297 | + |
| 298 | +``` |
| 299 | +NAME: |
| 300 | + babble run - Run node |
| 301 | +
|
| 302 | +USAGE: |
| 303 | + babble run [command options] [arguments...] |
| 304 | +
|
| 305 | +OPTIONS: |
| 306 | + --datadir value Directory for the configuration (default: "/home/<user>/.babble") |
| 307 | + --node_addr value IP:Port to bind Babble (default: "127.0.0.1:1337") |
| 308 | + --no_client Run Babble with dummy in-memory App client |
| 309 | + --proxy_addr value IP:Port to bind Proxy Server (default: "127.0.0.1:1338") |
| 310 | + --client_addr value IP:Port of Client App (default: "127.0.0.1:1339") |
| 311 | + --log_level value debug, info, warn, error, fatal, panic (default: "debug") |
| 312 | + --heartbeat value Heartbeat timer milliseconds (time between gossips) (default: 1000) |
| 313 | + --max_pool value Max number of pooled connections (default: 2) |
| 314 | + --tcp_timeout value TCP timeout milliseconds (default: 1000) |
| 315 | + --cache_size value Number of items in LRU caches (default: 500) |
| 316 | +
|
| 317 | +``` |
| 318 | + |
| 319 | +Example: |
| 320 | +``` |
| 321 | +$ babble run --node_addr="172.77.5.1:1337" --proxy_addr="172.77.5.1:1338" --client_addr="172.77.5.1:1339" |
| 322 | +``` |
| 323 | + |
| 324 | +Here Babble listens to other Babble nodes on 172.77.5.1:1337. |
| 325 | +It listens to the App on 172.77.5.1:1338 |
| 326 | +It expects the App to be listening on 172.77.5.1.1339 |
| 327 | + |
| 328 | + |
| 329 | + |
| 330 | + |
| 331 | + |
| 332 | + |
0 commit comments