Skcript's Logo
Skcript's Logo

Setting up a Blockchain Business Network With Hyperledger Fabric & Composer Running in Multiple Physical Machine

In my previous article, I wrote about how to setup the Hyperledger Fabric Composer Business Network with a basic structure explaining each components of the architecture. This article is focused on how to setup a network with multiple peers running in different physical machines.

Subscribe to our awesome Newsletter.

Setting up a Blockchain Business Network With Hyperledger Fabric & Composer Running in Multiple Physical Machine

Currently reading:

Setting up a Blockchain Business Network With Hyperledger Fabric & Composer Running in Multiple Physical Machine


Subscribe to our Newsletter:


Share article on:

The Architecture

Hyperledger Fabric has a set of components each with its own roles and functionalities. Each of these will be running on it’s own Docker instances and are configured to work together. These Docker instances even when running on multiple physical machines, can still communicate with each other. That’s essentially the crux of how a blockchain runs on several physical machines.

Terms

Certificate Authority

The certificate authority is responsible for handling all the access control logic, issuing the identities and permission for the users in the Hyperledger blockchain network.

Orderer

In order to keep the entire network in a synchronized state, the orderer is used. Whenever a new transaction is to be committed, the orderer is the one informing all the peers about the transaction. A network can have multiple orderers, also it’s advised in order to maintain less faults.

Peers

Only peers are allowed to commit transactions in the business network. Also each peer has its own copy of the entire world state. It’s connected with CouchDB instances which acts as the database. An organisation can have multiple peers and one or more anchor peer will be used to communicate with other organisations.

In this example, we’ll be having 1 CA, 1 Orderer, and 3 Peers. With 2 Peers running in the first machine, and the other in a second machine.

Prerequisites

  • Install Docker
  • Install Composer
  • Install Fabric Images (1.0.4)
  • Install Fabric Tools (Use this)

Setting Up

Since all the components are running inside individual Docker instances, we can easily configure them to run separately.

In this example, I’ll be taking the fabric-dev-serverand modify it to run on multiple machines. This is mainly focused towards easier understanding and to use it like a boilerplate.

Here since we’re using only the hlfv1 we’re removing the hlfv11 folder and bringing all the contents of hlfv1 outside.

The Folder Structure

This is how your codebase should look,

Here if you notice, there are three new files docker-compose-peer2.yml, startFabric-Peer2.sh and stopFabric.sh. As the name implies these are related to the third peer which we will be running on a separate machine.

Peer Configurations

The default dev server comes with configuration for running one Peer. So, the certificates are created correspondingly. Since we have three peers in total, we need to generate certificates for all the three.

If you’ve installed the fabric tools with the above mentioned script, you’ll have configtxgen and cryptogen in your system. We’ll be using this to generate the certificates for our peers, and CA.

In cypto-config.yaml change the count under PeerOrgs → Template → Count to number of peers you want. In our case it is 3. Thus the contents of crypto-config.yaml looks like below.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
OrdererOrgs:

- Name: Orderer

  Domain: example.com

  Specs:

    - Hostname: orderer

PeerOrgs:

- Name: Org1

  Domain: org1.example.com

  Template:

    Count: 3

  Users:

    Count: 0

And the configtx.yaml looks like,

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
---

Profiles:



    ComposerOrdererGenesis:

        Orderer:

            <<: *OrdererDefaults

            Organizations:

                - *OrdererOrg

        Consortiums:

            ComposerConsortium:

                Organizations:

                    - *Org1

    ComposerChannel:

        Consortium: ComposerConsortium

        Application:

            <<: *ApplicationDefaults

            Organizations:

                - *Org1



Organizations:



    - &OrdererOrg

        Name: OrdererOrg

        ID: OrdererMSP

        MSPDir: crypto-config/ordererOrganizations/example.com/msp

        AdminPrincipal: Role.MEMBER



    - &Org1

        Name: Org1

        ID: Org1MSP

        MSPDir: crypto-config/peerOrganizations/org1.example.com/msp

        AdminPrincipal: Role.MEMBER

        AnchorPeers:

            - Host: peer0.org1.example.com

              Port: 7051



Orderer: &OrdererDefaults

    OrdererType: solo



    Addresses:

        - orderer.example.com:7050

    BatchTimeout: 2s

    BatchSize:

        MaxMessageCount: 10

        AbsoluteMaxBytes: 98 MB

        PreferredMaxBytes: 512 KB

        

    Kafka:

        Brokers:

            - 127.0.0.1:9092



    Organizations:



Application: &ApplicationDefaults

    Organizations:

Once you made the modifications, run the following inside the composer folder in order to create the certificates for all the peers.

1
2
3
4
5
6
7
8
9
cd "$(dirname "$0")"

cryptogen generate --config=./crypto-config.yaml

export FABRIC_CFG_PATH=$PWD

configtxgen -profile ComposerOrdererGenesis -outputBlock ./composer-genesis.block

configtxgen -profile ComposerChannel -outputCreateChannelTx ./composer-channel.tx -channelID composerchannel

This creates all the certificates and the key under crypto-config folder. We will be using this to configure our Docker image’s environment variables.

Configuring Docker Services

In the docker-compose.yml we have added the following services.

  • ca.org1.example.com
  • orderer.example.com
  • peer0.org1.example.com
  • couchdb
  • peer1.org1.example.com
  • couchdb1

Here the peer0.org1.example.com uses couchdb as the world state database and peer1.org1.example.com uses couchdb1 as world state database.

In order to configure the Certificate Authority, we’ll be using the certificates that have been generated newly. In the command section of ca.org1.example.com make sure to use the proper private key file. It will be located under composer/crypto-config/peerOrganizations/

org1.example.com/ca/ Once you’ve updated it you’re good to go.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
version: '2'

services:

ca.org1.example.com:

image: hyperledger/fabric-ca:$ARCH-1.0.4

environment:

  - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server

  - FABRIC_CA_SERVER_CA_NAME=ca.org1.example.com

#      - FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/org1.example.com-cert.pem

#      - FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/a22daf356b2aab5792ea53e35f66fccef1d7f1aa2b3a2b92dbfbf96a448ea26a_sk



ports:

  - "7054:7054"

command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/d4e3285d47260c640643feda80dd0f4ae76378f0047f1cfba3efca6555600b43_sk -b admin:adminpw -d'

volumes:

  - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config

container_name: ca.org1.example.com



orderer.example.com:

container_name: orderer.example.com

image: hyperledger/fabric-orderer:$ARCH-1.0.4

environment:

  - ORDERER_GENERAL_LOGLEVEL=debug

  - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0

  - ORDERER_GENERAL_GENESISMETHOD=file

  - ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/configtx/composer-genesis.block

  - ORDERER_GENERAL_LOCALMSPID=OrdererMSP

  - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp/orderer/msp

working_dir: /opt/gopath/src/github.com/hyperledger/fabric

command: orderer

ports:

  - 7050:7050

volumes:

    - ./:/etc/hyperledger/configtx

    - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/etc/hyperledger/msp/orderer/msp



peer0.org1.example.com:

container_name: peer0.org1.example.com

image: hyperledger/fabric-peer:$ARCH-1.0.4

environment:

  - CORE_LOGGING_PEER=debug

  - CORE_CHAINCODE_LOGGING_LEVEL=DEBUG

  - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

  - CORE_PEER_ID=peer0.org1.example.com

  - CORE_PEER_ADDRESS=peer0.org1.example.com:7051

  - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=composer_default

  - CORE_PEER_LOCALMSPID=Org1MSP

  - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

  - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

  - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984

working_dir: /opt/gopath/src/github.com/hyperledger/fabric

command: peer node start --peer-defaultchain=false

ports:

  - 7051:7051

  - 7053:7053

volumes:

    - /var/run/:/host/var/run/

    - ./:/etc/hyperledger/configtx

    - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/peer/msp

    - ./crypto-config/peerOrganizations/org1.example.com/users:/etc/hyperledger/msp/users

depends_on:

  - orderer.example.com

  - couchdb


couchdb:

container_name: couchdb

image: hyperledger/fabric-couchdb:$ARCH-1.0.4

ports:

  - 5984:5984

environment:

  DB_URL: http://localhost:5984/member_db


peer1.org1.example.com:

container_name: peer1.org1.example.com

image: hyperledger/fabric-peer:$ARCH-1.0.4

environment:

  - CORE_LOGGING_PEER=debug

  - CORE_CHAINCODE_LOGGING_LEVEL=DEBUG

  - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

  - CORE_PEER_ID=peer1.org1.example.com

  - CORE_PEER_ADDRESS=peer1.org1.example.com:7051

  - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=composer_default

  - CORE_PEER_LOCALMSPID=Org1MSP

  - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

  - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

  - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb1:5984

working_dir: /opt/gopath/src/github.com/hyperledger/fabric

command: peer node start --peer-defaultchain=false

ports:

  - 8051:7051

  - 8053:7053

volumes:

    - /var/run/:/host/var/run/

    - ./:/etc/hyperledger/configtx

    - ./crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/peer/msp

    - ./crypto-config/peerOrganizations/org1.example.com/users:/etc/hyperledger/msp/users

depends_on:

  - orderer.example.com

  - couchdb1



couchdb1:

container_name: couchdb1

image: hyperledger/fabric-couchdb:$ARCH-1.0.4

ports:

  - 6984:5984

environment:

  DB_URL: http://localhost:6984/member_db

Similarly we’ll create a second docker compose file for Peer 2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
version: '2'

services:

  peer2.org1.example.com:

    container_name: peer2.org1.example.com

    image: hyperledger/fabric-peer:$ARCH-1.0.4

    environment:

      - CORE_LOGGING_PEER=debug

      - CORE_CHAINCODE_LOGGING_LEVEL=DEBUG

      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock

      - CORE_PEER_ID=peer2.org1.example.com

      - CORE_PEER_ADDRESS=peer2.org1.example.com:7051

      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=composer_default

      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB

      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb2:5984

    working_dir: /opt/gopath/src/github.com/hyperledger/fabric

    command: peer node start --peer-defaultchain=false

    ports:

      - 9051:7051

      - 9053:7053

    volumes:

        - /var/run/:/host/var/run/

        - ./:/etc/hyperledger/configtx

        - ./crypto-config/peerOrganizations/org1.example.com/peers/peer2.org1.example.com/msp:/etc/hyperledger/peer/msp

        - ./crypto-config/peerOrganizations/org1.example.com/users:/etc/hyperledger/msp/users

    depends_on:

      - couchdb2



  couchdb2:

    container_name: couchdb2

    image: hyperledger/fabric-couchdb:$ARCH-1.0.4

    ports:

      - 7984:5984

    environment:

      DB_URL: http://localhost:7984/member_db

Configuring the scripts

Now we’re ready to run the Fabric network. We’ll be using the fabric-dev-server’s scripts as the base script with a few modifications as mentioned below.

In the startFabric.sh file, by default the configuration for the first peer (peer0.org1.example.com) to join the channel is provided. Now we need to join the second peer (peer1.org1.example.com) to the same channel.

In order to do that we need to fetch the channel block in the second peer and then use that .block file to join the peer. The following code is used to join the peers to the channel in the network.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
# Create the channel

docker exec peer0.org1.example.com peer channel create -o orderer.example.com:7050 -c composerchannel -f /etc/hyperledger/configtx/composer-channel.tx


# Join peer0.org1.example.com to the channel.

docker exec -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b composerchannel.block


# Create the channel

docker exec -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer1.org1.example.com peer channel fetch config -o orderer.example.com:7050 -c composerchannel

# docker exec peer1.org1.example.com peer channel create -o orderer.example.com:7050 -c composerchannel -f /etc/hyperledger/configtx/composer-channel.tx


# Join peer1.org1.example.com to the channel.

docker exec -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer1.org1.example.com peer channel join -b composerchannel_config.block

In the second machine, we’ll be using the same concept of fetching the channel block and joining the channel with the block file.

1
2
3
docker exec -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer2.org1.example.com peer channel fetch config -o orderer.example.com:7050 -c composerchannel

docker exec -e "CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/users/Admin@org1.example.com/msp" peer2.org1.example.com peer channel join -b composerchannel_config.block

Peer Admin Card Creation

Now we need to update the script to create the peer admin card for the network. With the default script createPeerAdminCard.sh we’ll add update the connection profile configuration to add the new peers.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
cat << EOF > /tmp/.connection.json

{

    "name": "hlfv1",

    "type": "hlfv1",

    "orderers": \[

       { "url" : "grpc://localhost:7050" }

    \],

    "ca": { 

        "url": "http://localhost:7054", 

        "name": "ca.org1.example.com"

    },

    "peers": \[

        {

            "requestURL": "grpc://localhost:7051",

            "eventURL": "grpc://localhost:7053"

        }, {

            "requestURL": "grpc://localhost:8051",

            "eventURL": "grpc://localhost:8053"

        }, {

            "requestURL": "grpc://<Peer2-IP>:9051",

            "eventURL": "grpc://<Peer2-IP>:9053"

        }

    \],

    "channel": "composerchannel",

    "mspID": "Org1MSP",

    "timeout": 300

}

Also you need to update the PRIVATE_KEY path with the corresponding path to the private key of map keystore.

1
PRIVATE_KEY="${DIR}"/composer/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/<PRIVATE_KEY_NAME>

This is how your script should look,

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
#!/bin/bash



# Exit on first error

set -e

# Grab the current directory

DIR="$( cd "$( dirname "${BASH_SOURCE\[0\]}" )" && pwd )"



echo

# check that the composer command exists at a version >v0.14

if hash composer 2>/dev/null; then

    composer --version | awk -F. '{if ($2<15) exit 1}'

    if \[ $? -eq 1 \]; then

        echo 'Sorry, Use createConnectionProfile for versions before v0.15.0' 

        exit 1

    else

        echo Using composer-cli at $(composer --version)

    fi

else

    echo 'Need to have composer-cli installed at v0.15 or greater'

    exit 1

fi

# need to get the certificate 



cat << EOF > /tmp/.connection.json

{

    "name": "hlfv1",

    "type": "hlfv1",

    "orderers": \[

       { "url" : "grpc://localhost:7050" }

    \],

    "ca": { 

        "url": "http://localhost:7054", 

        "name": "ca.org1.example.com"

    },

    "peers": \[

        {

            "requestURL": "grpc://localhost:7051",

            "eventURL": "grpc://localhost:7053"

        }, {

            "requestURL": "grpc://localhost:8051",

            "eventURL": "grpc://localhost:8053"

        }, {

            "requestURL": "grpc://192.168.31.12:9051",

            "eventURL": "grpc://192.168.31.12:9053"

        }

    \],

    "channel": "composerchannel",

    "mspID": "Org1MSP",

    "timeout": 300

}

EOF



PRIVATE_KEY="${DIR}"/composer/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/7fe58742a0b6d1102c74293808f1736dea010d3451f9e1a804c0b86ecf90baa0_sk

CERT="${DIR}"/composer/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem



if composer card list -n PeerAdmin@hlfv1 > /dev/null; then

    composer card delete -n PeerAdmin@hlfv1

fi

composer card create -p /tmp/.connection.json -u PeerAdmin -c "${CERT}" -k "${PRIVATE_KEY}" -r PeerAdmin -r ChannelAdmin --file /tmp/PeerAdmin@hlfv1.card

composer card import --file /tmp/PeerAdmin@hlfv1.card 



rm -rf /tmp/.connection.json



echo "Hyperledger Composer PeerAdmin card has been imported"

composer card list

That’s it, everything is set and ready to go. Now lets run the following scripts to start the Hyperledger Fabric network on the first machine.

1
./teardownFabric.sh && ./startFabric.sh && ./createPeerAdminCard.sh

Run the following command on the second machine,

1
./startFabric-Peer2.sh

If everything is working properly, you’ll notice clean logs and zero errors. Try running docker ps to see all of the services that are running on each of the machines.

In the first machine there are 6 services running.

And in the second machine there are two services running.

When you notice the logs, the peers syncs whenever you create asset of submit transactions. The peer0 will be getting the first transaction submit request and then the orderer distributes to other peers maintaining all the peers in sync.

Checkout this repo for the entire source code of the server : https://github.com/varun-raj/fabric-dev-servers-multipeer


Awesome illustrations by @vectorpocket

Share article on

Comments and Discussions

Skcript


Stay Updated with Our Newsletter
SIGN UP