This post is part of the Infineon Blockchain Starter Kit road test.

Blockchain - outside of the bitcoin context - is new to me.

Follow along with me on this path to learn the technology....

 

 

In the previous post, I set up a Hyperledger Fabric chain. In this post, it's going to be a small footprint Burrow chain. It's from the same organisation, but runs on small devices. Several chains can run comfortably on a Raspberry Pi.

I'm documenting the steps I used to get 3 chains running, synchronising and validating each other.

 

Prerequisite: have Burrow binary in your path. I've documented the raw steps in Road Test notepad: Infineon Blockchain Starter Kit.

Burrow uses the single binary executable approach. The same program is used to generate configurations, to generate keys, to run a ledger service, to run a synchronisation service, to deploy smart contracts, ....

 

We Will Set Up 3 Distributed BlockChain Ledgers and a Synchronisation Manager

 

A typical blockchain ledger landscape exists of a set of chains. Each participant can run their own local chain and have it synchronised with the others.

This will take care that there isn't a single source of truth, but a distributed one, validated by several parties.

 

In this Hyperledger Burrow example, 3 separate ledger instances are created. They all run a s a different process, a different entity. Writing to their own private database.

A 4th instance of Burrow has a complete different task. It's task is to let the 3 distributed instances talk, synchronise and validate each other. It's called a Seed instance in Burrow lingo.

There are other possible configurations. You don't need a Seed instance. You can register one ledger directly to another one. And ledger instances can double as Seed instance ...

 

hyperledger burrow with seed node

 

The process is described in the Burrow Tutorial. I had to change a few settings though to make it work on my setup.

The configuration files I used are attached to this post (you can use them to copy/paste content), and I'll focus on the differences in this post.

 

On the Linux prompt, first create a play directory and navigate to there. I created ~/burrow_try.

 

Seed Node

 

Let Burrow generate seed keys and a configuration file template:

 

burrow spec --full-accounts=3 | burrow configure -s- > .burrow_init.toml
burrow spec -f1 | burrow configure --keys-dir=.keys_seed -s- > /dev/null
cp .burrow_init.toml .burrow_seed.toml  

 

Then make changes to the generated file burrow_seed.toml. I had to change the ListenAddress to 127.0.0.1 instead of 0.0.0.0 to make the whole process work.

If you know why, post in the comments.

 

BurrowDir = ".burrow_seed_0"

[Tendermint]
  Enabled = true
  SeedMode = true
  PersistentPeers = ""
  ListenHost = "127.0.0.1"
  ListenPort = "10000"
  ExternalAddress = ""
  AddrBookStrict = false
  Moniker = "seed_node_0"
  IdentifyPeers = false
  AuthorizedPeers = ""
  CreateEmptyBlocks = "5m"

[Execution]

[Keys]
  GRPCServiceEnabled = false
  AllowBadFilePermissions = true
  RemoteAddress = ""
  KeysDirectory = ".keys_seed"

[RPC]
  [RPC.Info]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "10001"
  [RPC.Profiler]
    Enabled = false
  [RPC.GRPC]
    Enabled = false
  [RPC.Metrics]
    Enabled = false
  [RPC.Web3]
    Enabled = false

 

You can now start the Seed node and retrieve it's address:

burrow start --address=`basename .keys_seed/data/* .json` --config=.burrow_seed.toml  > .burrow_seed.log 2>&1 &

 

When started:

SEED_URL=`curl -s 127.0.0.1:10001/network | jq -r '.result.ThisNode | [.ID, .ListenAddress] | join("@") | ascii_downcase'`
echo $SEED_URL

 

We'll use that address later to update our 3 chain configuration files.

 

3 Chain Nodes with Validators

 

Then, make 3 mor copies from the template file for the 3 chain instances:

cp .burrow_init.toml .burrow_val0.toml
cp .burrow_init.toml .burrow_val1.toml
cp .burrow_init.toml .burrow_val2.toml

 

Edit each of these files and make the following changes:

 

Chain 1:

 

BurrowDir = ".burrow_node0"

[Tendermint]
  Enabled = true
  Seeds = "PUT_HERE_SEED_NODE_ID@LISTEN_EXTERNAL_ADDRESS"
  SeedMode = false
  PersistentPeers = ""
  ListenHost = "127.0.0.1"
  ListenPort = "20000"
  ExternalAddress = ""
  AddrBookStrict = false
  Moniker = "val_node_0"
  IdentifyPeers = false
  AuthorizedPeers = ""
  CreateEmptyBlocks = "5m"

[Execution]

[Keys]
  GRPCServiceEnabled = false
  AllowBadFilePermissions = true
  RemoteAddress = ""
  KeysDirectory = ".keys"

[RPC]
  [RPC.Info]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "20001"
  [RPC.Profiler]
    Enabled = false
  [RPC.GRPC]
    Enabled = true
    ListenHost = "127.0.0.1"
    ListenPort = "20002"
  [RPC.Metrics]
    Enabled = false
  [RPC.Web3]
    Enabled = false

 

Chain 2, the same, except:

BurrowDir = ".burrow_node1"

[Tendermint]
  ListenPort = "30000"

[RPC]
  [RPC.Info]
    ListenPort = "30001"

  [RPC.GRPC]
    ListenPort = "30002"

 

Chain 3, also the same, except:

BurrowDir = ".burrow_node2"

[Tendermint]
  ListenPort = "40000"

[RPC]
  [RPC.Info]
    ListenPort = "40001"

  [RPC.GRPC]
    ListenPort = "40002"

 

You'll see that each node is the same, except that they all listen to different ports.

Again, the only changes are that in the [Tendermint] section, I had to change the ListenAddress to 127.0.0.1 instead of 0.0.0.0.

(If you don't like all this typing, grab the files from the attached archive and copy the relevant parts over).

 

Replace the Seeds placeholder with the Seed of the Seed node:

sed -i s%PUT_HERE_SEED_NODE_ID@LISTEN_EXTERNAL_ADDRESS%${SEED_URL}% .burrow_val0.toml
sed -i s%PUT_HERE_SEED_NODE_ID@LISTEN_EXTERNAL_ADDRESS%${SEED_URL}% .burrow_val1.toml
sed -i s%PUT_HERE_SEED_NODE_ID@LISTEN_EXTERNAL_ADDRESS%${SEED_URL}% .burrow_val2.toml

 

This will replace the fixed text that we typed in the Tendermint's Seeds attribute of all 3 config files with the Seeds node address we extracted after starting that node.

 

Then start the 3 chains:

burrow start -v=0 --config=.burrow_val0.toml  > .burrow_val0.log 2>&1 &
burrow start -v=1 --config=.burrow_val1.toml  > .burrow_val1.log 2>&1 &
burrow start -v=2 --config=.burrow_val2.toml  > .burrow_val2.log 2>&1 &

 

That's it. You can now check how many validators are running in each chain, and retrieve their IDs.

This again is different than in the tutorial.

In my case, Burrow doesn't use the values set in Moniker attribute but generates it's own unique ones:

 

pi@raspberrypi:~/burrow_try $ curl -s 127.0.0.1:10001/network | jq -r '.result.peers[].node_info'
{
  "protocol_version": {
    "p2p": 7,
    "block": 10,
    "app": 0
  },
  "id": "8d98af16e204ebec471f3405c2b02af433a7b50e",
  "listen_addr": "127.0.0.1:20000",
  "network": "BurrowChain_CC48E7-D0177C",
  "version": "0.32.8",
  "channels": "4020212223303800",
  "moniker": "BurrowChain_CC48E7-D0177C_Node_10831306A234166B3A4FA5AF20B340720B4A50C2",
  "other": {
    "tx_index": "off",
    "rpc_address": ""
  }
}
{
  "protocol_version": {
    "p2p": 7,
    "block": 10,
    "app": 0
  },
  "id": "5d2784a432f8ac1f942193f2240440814d967ece",
  "listen_addr": "127.0.0.1:30000",
  "network": "BurrowChain_CC48E7-D0177C",
  "version": "0.32.8",
  "channels": "4020212223303800",
  "moniker": "BurrowChain_CC48E7-D0177C_Node_058F785C636A31F61D9E7C73C5196F43D0CE8898",
  "other": {
    "tx_index": "off",
    "rpc_address": ""
  }
}
{
  "protocol_version": {
    "p2p": 7,
    "block": 10,
    "app": 0
  },
  "id": "8cf13f32943a1c3e8cd3a73967b6c78acc209907",
  "listen_addr": "127.0.0.1:40000",
  "network": "BurrowChain_CC48E7-D0177C",
  "version": "0.32.8",
  "channels": "4020212223303800",
  "moniker": "BurrowChain_CC48E7-D0177C_Node_1D03B0C6AB90644F96047D677E2D6E8149B2B55B",
  "other": {
    "tx_index": "off",
    "rpc_address": ""
  }
}

 

Here is a trace of a vote between the chains:

curl -s 127.0.0.1:20001/consensus

 

 

What now? First I want to find out why I had to make changes to the listener address. I could not find any evidence online that others had to do that.

Second, I'd like to run a few ledgers on different computers (PIs , BeagleBones, a VM on my laptop) and have them work together in a truly distributed setting.

And then, deploy smart contracts, post transactions, use the chains to create traceable events.

Ultimately, link in the Infineon Security 2Go smart cards into the process - either as ID to start the chain, or as signature mechanism when posting transactions ...

 

Related Blog
Blockchain - HyperLedger Fabric: post and search transactions on a distributed trusted ledger
Blockchain - Hyperledger Burrow: set up a distributed ledger
Blockchain - Get Some Crypto Currency on an Infineon Security 2Go Card
Blockchain - Debug the Infineon Demo App with Android Studio and Your Phone
Blockchain - Analyse the Infineon Android Demo App - part a: Detect Card
Blockchain - Analyse the Infineon Android Demo App - part b: Retrieve Ethereum Crypto Currency Balance
Blockchain - Analyse the Infineon Android Demo App - part c: Transaction, Move Crypto Currency to Another Account
Blockchain - Talk Directly to the Infineon 2Go Smart Cards API
Blockchain - Smart Contract Test
Road Test notepad: Infineon Blockchain Starter Kit
Infineon Blockchain Starter Kit - Review