Hyperledger Fabric & Blockchain Explorer Setup

Before we continue I’ve uploaded a script to perform this startup here: https://github.com/robevansuk/hyperledger-blockchain-explorer. It assumes you have the prerequisites installed already (binaries/docker containers/fabric-samples), and that you have successfully spun up the first-network sample already.

Fabric sample / First network setup + Blockchain Explorer Setup

Some notes I’ve made on setting up the blockchain explorer since the documentation is a little unspecific for my liking and this may help others. I tried checking out repos manually and running containers that should have been “ready to go” but had no luck. Hence I’m starting from scratch to gain the context required to understand how to install everything from beginning to end.

For reference I’m following documentation here:

https://hyperledger-fabric.readthedocs.io/en/release-1.4/build_network.html

The repositories that I’ve attempted to run (and failed with as standalone clones) are:

https://github.com/hyperledger/blockchain-explorer
https://github.com/hyperledger/fabric-samples

hint: use the curl command below under: “Generate Hyperledger Fabric First Network”

And docker containers:

https://github.com/osswangxining/hyperledger-explorer
https://github.com/osswangxining/hyperledger-explorer-postgresql

I could not get the above working so set about getting up and running directly with the github repository. I then produced this page as the documentation on the github repo and other sites is next to impossible to follow when all you want is a step by step guide to getting started.

Hyperledger Fabric First Network setup dependencies:

 brew install postgresql
 brew install jq
 brew install node@8
 brew link --force --overwrite node@8          << this is just to ensure I had the right version and no old versions were used

You need postgres above so you can connect to the docker container running postgres internally so you can verify the setup actually happened as expected.

Verify you have in fact installed the correct bits of software:

> which psql
/usr/local/Cellar/postgresql/11.3/bin/psql
> psql --version
psql (PostgreSQL) 11.3
> which jq
/usr/local/bin/jq
> jq --version
jq-1.6
> which node
/usr/local/bin/node
> node --version
v8.16.0

Good. Everything is in place.

If you haven’t got these dependencies set up you may need to force some removal and re-installation using brew commands or a suitable alternative. I use Brew on a Mac.

Generate Hyperledger Fabric First Network:

> cd ~
> curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s

This pulls down everything necessary for the next command (see output)
– all the docker images
– all the binaries necessary to install everything
– the fabric samples github repo.

Important: You will also end up on a release branch. At the time of writing it is v.1.4.1 (release 1.4). This is important as there are compatibility issues that will be an issue later on with generating the network and getting peers to join the channel.

cd ~/fabric-samples/first-network
./byfn.sh generate

Generate does not start the network it only generates the json configuration files for a network to be spun up. Scroll down to see next command to start the network.

OUTPUT should be similar if everything goes well.

./byfn.sh generate
Generating certs and genesis block for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] Y
proceeding ...
~/fabric-samples/first-network/../bin/cryptogen

##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ res=0
+ set +x

~/fabric-samples/first-network/../bin/configtxgen
##########################################################
######### Generating Orderer Genesis block ##############
##########################################################
CONSENSUS_TYPE=solo
+ '[' solo == solo ']'
+ configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2019-06-12 09:37:17.306 BST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-06-12 09:37:17.359 BST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: solo
2019-06-12 09:37:17.359 BST [common.tools.configtxgen.localconfig] Load -> INFO 003 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.414 BST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 004 orderer type: solo
2019-06-12 09:37:17.414 BST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 005 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.416 BST [common.tools.configtxgen] doOutputBlock -> INFO 006 Generating genesis block
2019-06-12 09:37:17.417 BST [common.tools.configtxgen] doOutputBlock -> INFO 007 Writing genesis block
+ res=0
+ set +x

#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2019-06-12 09:37:17.450 BST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-06-12 09:37:17.502 BST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.554 BST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-06-12 09:37:17.554 BST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.554 BST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx
2019-06-12 09:37:17.558 BST [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 006 Writing new channel tx
+ res=0
+ set +x

#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2019-06-12 09:37:17.595 BST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-06-12 09:37:17.647 BST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.700 BST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-06-12 09:37:17.700 BST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.700 BST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-06-12 09:37:17.700 BST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

#################################################################
####### Generating anchor peer update for Org2MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2019-06-12 09:37:17.733 BST [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-06-12 09:37:17.788 BST [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.844 BST [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-06-12 09:37:17.844 BST [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /Users/robevans/dev/fabric-samples/first-network/configtx.yaml
2019-06-12 09:37:17.844 BST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-06-12 09:37:17.844 BST [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

fabric-samples/basic-network/connection.json | config.json

You should ensure the postgresql connectivity details are correct. Mine are:

{
 "name": "basic-network",
 "version": "1.0.0",
 "client": {
 "organization": "Org1",
 "connection": {
 "timeout": {
   "peer": {
       "endorser": "300"
     },
      "orderer": "300"
     }
   }
 },
 "channels": {
   "mychannel": {
      "orderers": [
        "orderer.example.com"
     ],
     "peers": {
       "peer0.org1.example.com": {}
     }
   }
 },
 "organizations": {
   "Org1": {
     "mspid": "Org1MSP",
     "peers": [
       "peer0.org1.example.com"
     ],
     "certificateAuthorities": [
       "ca.example.com"
     ]
   }
 },
 "orderers": {
   "orderer.example.com": {
     "url": "grpc://localhost:7050"
   }
 },
 "peers": {
   "peer0.org1.example.com": {
     "url": "grpc://localhost:7051"
   }
 },
 "certificateAuthorities": {
   "ca.example.com": {
     "url": "http://localhost:7054",
     "caName": "ca.example.com"
   }
 },
 "host": "127.0.0.1",
 "port": "8080",
 "channel": "mychannel",
 "keyValueStore": "/tmp/fabric-client-kvs",
 "eventWaitTime": "30000",
 "pg": {
   "host": "127.0.0.1",
   "port": "5432",
   "database": "fabricexplorer",
   "username": "hppoc",
   "passwd": "password"
 }
}

Starting the Hyperledger Fabric First Network Example:

./byfn.sh up

The network should start up with similar output to below:

~/dev/fabric-samples/first-network ((v1.4.1)): ./byfn.sh up
Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] Y
proceeding ...
LOCAL_VERSION=1.4.1
DOCKER_IMAGE_VERSION=1.4.1
Creating network "net_byfn" with the default driver
Creating volume "net_orderer.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating peer1.org2.example.com ... done
Creating peer0.org2.example.com ... done
Creating orderer.example.com    ... done
Creating peer0.org1.example.com ... done
Creating peer1.org1.example.com ... done
Creating cli                    ... done
CONTAINER ID        IMAGE                                           COMMAND                  CREATED              STATUS                          PORTS                      NAMES
61990e4f64dd        hyperledger/fabric-tools:latest                 "/bin/bash"              1 second ago         Up Less than a second                                      cli
55eb17e7892b        hyperledger/fabric-peer:latest                  "peer node start"        3 seconds ago        Up Less than a second           0.0.0.0:8051->8051/tcp     peer1.org1.example.com
d7290b0be519        hyperledger/fabric-orderer:latest               "orderer"                3 seconds ago        Up 1 second                     0.0.0.0:7050->7050/tcp     orderer.example.com
a615cfd86dec        hyperledger/fabric-peer:latest                  "peer node start"        3 seconds ago        Up 1 second                     0.0.0.0:7051->7051/tcp     peer0.org1.example.com
a2161d614307        hyperledger/fabric-peer:latest                  "peer node start"        3 seconds ago        Up 1 second                     0.0.0.0:9051->9051/tcp     peer0.org2.example.com
04d5d49e5ec0        hyperledger/fabric-peer:latest                  "peer node start"        3 seconds ago        Up 1 second                     0.0.0.0:10051->10051/tcp   peer1.org2.example.com
7dbc15bd8701        osswangxining/hyperledger-explorer              "node main.js"           About a minute ago   Exited (1) 58 seconds ago                                  adoring_banzai
5200c4284ba0        osswangxining/hyperledger-explorer              "node main.js"           About a minute ago   Exited (1) About a minute ago                              vigorous_kowalevski
61c608c47e4e        osswangxining/hyperledger-explorer              "node main.js"           15 minutes ago       Exited (1) 15 minutes ago                                  admiring_hertz
ff274c8c9409        osswangxining/hyperledger-explorer              "node main.js"           15 minutes ago       Exited (1) 15 minutes ago                                  focused_neumann
27f05786e967        osswangxining/hyperledger-explorer              "node main.js"           18 minutes ago       Exited (1) 18 minutes ago                                  wizardly_kepler
8716b16b0683        osswangxining/hyperledger-explorer              "node main.js"           29 minutes ago       Exited (1) 29 minutes ago                                  reverent_hypatia
91d96be6ae11        osswangxining/hyperledger-explorer              "node main.js"           41 minutes ago       Exited (1) 41 minutes ago                                  dreamy_galois
d25be524459a        osswangxining/hyperledger-explorer              "node main.js"           42 minutes ago       Exited (1) 42 minutes ago                                  wizardly_lumiere
96ec9d436d31        osswangxining/hyperledger-explorer              "node main.js"           42 minutes ago       Exited (1) 42 minutes ago                                  epic_franklin
5bcddf0d923f        osswangxining/hyperledger-explorer              "node main.js"           44 minutes ago       Exited (1) 44 minutes ago                                  vigorous_cray
5bf6177bac67        osswangxining/hyperledger-explorer-postgresql   "docker-entrypoint.s…"   About an hour ago    Up About an hour                0.0.0.0:6432->5432/tcp     relaxed_feistel

 ____    _____      _      ____    _____ 
/ ___|  |_   _|    / \    |  _ \  |_   _|
\___ \    | |     / _ \   | |_) |   | | 
 ___) |   | |    / ___ \  |  _ <    | | 
|____/    |_|   /_/   \_\ |_| \_\   |_| 
Build your first network (BYFN) end-to-end test
Channel name : mychannel
Creating channel...
+ peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x

2019-06-12 09:58:16.426 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:16.463 UTC [cli.common] readBlock -> INFO 002 Received block: 0

===================== Channel 'mychannel' created ===================== 
Having all peers join the channel...
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-06-12 09:58:16.555 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:16.595 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org1 joined channel 'mychannel' ===================== 
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-06-12 09:58:19.691 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:19.727 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org1 joined channel 'mychannel' ===================== 
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-06-12 09:58:22.820 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:22.866 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org2 joined channel 'mychannel' ===================== 
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-06-12 09:58:25.955 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:25.992 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org2 joined channel 'mychannel' ===================== 
Updating anchor peers for org1...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2019-06-12 09:58:29.089 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:29.105 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org1MSP' on channel 'mychannel' ===================== 
Updating anchor peers for org2...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2019-06-12 09:58:32.213 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-06-12 09:58:32.231 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org2MSP' on channel 'mychannel' ===================== 
Installing chaincode on peer0.org1...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2019-06-12 09:58:35.341 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-06-12 09:58:35.341 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-06-12 09:58:36.068 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
===================== Chaincode is installed on peer0.org1 ===================== 
Install chaincode on peer0.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2019-06-12 09:58:36.165 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-06-12 09:58:36.165 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-06-12 09:58:36.344 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
===================== Chaincode is installed on peer0.org2 ===================== 
Instantiating chaincode on peer0.org2...
+ peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')'
+ res=0
+ set +x
2019-06-12 09:58:36.447 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-06-12 09:58:36.447 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' ===================== 
Querying chaincode on peer0.org1...
===================== Querying on peer0.org1 on channel 'mychannel'... ===================== 
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Attempting to Query peer0.org1 ...3 secs
+ res=0
+ set +x
100
===================== Query successful on peer0.org1 on channel 'mychannel' ===================== 
Sending invoke transaction on peer0.org1 peer0.org2...
+ peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
+ res=0
+ set +x
2019-06-12 09:59:07.451 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 
===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' ===================== 
Installing chaincode on peer1.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2019-06-12 09:59:07.552 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-06-12 09:59:07.552 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-06-12 09:59:07.745 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
===================== Chaincode is installed on peer1.org2 ===================== 
Querying chaincode on peer1.org2...
===================== Querying on peer1.org2 on channel 'mychannel'... ===================== 
Attempting to Query peer1.org2 ...3 secs
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
+ res=0
+ set +x
90
===================== Query successful on peer1.org2 on channel 'mychannel' ===================== 
========= All GOOD, BYFN execution completed =========== 
 _____   _   _   ____   
| ____| | \ | | |  _ \ 
|  _|   |  \| | | | | | 
| |___  | |\  | | |_| | 
|_____| |_| \_| |____/ 

The network that spins up appears to come from:

~/fabric-samples/first-network/base/docker-compose-base.yaml

which exposes the following ports:

  • for the peers: 7051, 8051, 9051, 10051
  • for the orderer: 7050
docker network ls

NETWORK ID          NAME                DRIVER              SCOPE
28490685536a        basic               bridge              local
5b3cfe5b39ad        bridge              bridge              local
ba251977f977        core_basic          bridge              local
95432027740c        core_default        bridge              local
32fb8d2feb51        core_example.com    bridge              local
693e57479383        host                host                local
8baa8d9b9faa        net_byfn            bridge              local
d0f303133495        none                null                local

All nodes should be on the net_byfn network. You can confirm this by inspecting the individual docker containers – feel free to skip this step if you aren’t experiencing any issues.

docker inspect $(docker ps -a | grep hyperledger/fabric-peer:latest | head -n1 | cut -f1 -d" ") | grep Net

            "NetworkMode": "net_byfn",
        "NetworkSettings": {
            "Networks": {
                    "NetworkID": "8baa8d9b9faa...",

For some reason I noticed at this point I was on a branch that was not master. So ensure you’re still on the github master branch.

Assuming you’re on the fabric-samples master branch, you should see a bunch of connection-org[1-3].yaml/json files which we will modify and use as a part of the blocklchain-explorer start up procedure.

At this point everything appears to have been spun up successfully, but there are no clear instructions on how you can invoke a transaction on the network and connect the blockchain-explorer to see what activity is going on.

Some things to note: byfn.sh generate script generated not only config but a /wallet user Id. This is necessary to communicate with the peers so ensure you’re using the correct credentials for your network. If you spun up another network and are attempting to connect to it with the wrong certificates/pems, you’re going to find you can’t get the blockchain explorer spun up without lots of confusing errors.

TROUBLE SHOOTING

The blockchain-explorer application has a /logs dir. These are very useful for debugging issues so be sure to check them first.

You may get postgres connectivity issues. If so you can try using your local username, rather than hppoc, or perhaps the IP address of the docker container needs amending. With

 docker inspect [docker-containerId] | grep IPAddress

you can attempt to access the docker container postgres is running in directly via its IP rather than using localhost. Ensure you’re also using the correct port and the port is mapped for the docker container/local host set up you are running against.

Start Hyperledger Blockchain Explorer

First setup the DB.

Ensure the correct postgres config is in this file: blockchain-explorer/app/explorerconfig.json as its a dependency for the createdb.sh script called next…

Execute the script createdb.sh located in:

.~/blockchain-explorer/app/persistence/fabric/postgreSQL/db/createdb.sh
Copying ENV variables into temp file...
USER="hppoc"
DATABASE="fabricexplorer"
PASSWD='password'
Executing SQL scripts, OS=darwin18
CREATE ROLE
psql:./explorerpg.sql:7: NOTICE:  database "fabricexplorer" does not exist, skipping
DROP DATABASE
CREATE DATABASE
You are now connected to database "fabricexplorer" as user "robevans".
psql:./explorerpg.sql:15: NOTICE:  table "blocks" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
psql:./explorerpg.sql:35: NOTICE:  table "chaincodes" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
ALTER SEQUENCE
psql:./explorerpg.sql:54: NOTICE:  table "peer_ref_chaincode" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
psql:./explorerpg.sql:70: NOTICE:  table "channel" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
ALTER SEQUENCE
psql:./explorerpg.sql:94: NOTICE:  table "peer" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
psql:./explorerpg.sql:114: NOTICE:  table "peer_ref_channel" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
psql:./explorerpg.sql:130: NOTICE:  table "orderer" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
psql:./explorerpg.sql:147: NOTICE:  table "transactions" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
ALTER SEQUENCE
psql:./explorerpg.sql:178: NOTICE:  table "write_lock" does not exist, skipping
DROP TABLE
CREATE TABLE
ALTER TABLE
ALTER SEQUENCE
psql:./explorerpg.sql:187: NOTICE:  index "blocks_blocknum_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:191: NOTICE:  index "blocks_channel_genesis_hash_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:195: NOTICE:  index "blocks_createdt_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:199: NOTICE:  index "transaction_txhash_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:203: NOTICE:  index "transaction_channel_genesis_hash_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:207: NOTICE:  index "transaction_createdt_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:211: NOTICE:  index "transaction_blockid_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:215: NOTICE:  index "transaction_chaincode_proposal_input_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:220: NOTICE:  index "channel_channel_genesis_hash_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
psql:./explorerpg.sql:224: NOTICE:  index "channel_channel_hash_idx" does not exist, skipping
DROP INDEX
CREATE INDEX
GRANT
You are now connected to database "fabricexplorer" as user "robevans".

You can verify the db is set up by logging in to the fabricexplorer db and entering \dt 

psql fabricexplorer
psql (11.3)
Type "help" for help.
fabricexplorer=# \dt
              List of relations
 Schema |        Name        | Type  | Owner 
--------+--------------------+-------+-------
 public | blocks             | table | hppoc
 public | chaincodes         | table | hppoc
 public | channel            | table | hppoc
 public | orderer            | table | hppoc
 public | peer               | table | hppoc
 public | peer_ref_chaincode | table | hppoc
 public | peer_ref_channel   | table | hppoc
 public | transactions       | table | hppoc
 public | write_lock         | table | hppoc

Good, the database exists. There are some indexes also present but not shown here. CTRL-D to exit.

Next… we must install the dependencies required to run the blockchain explorer web application on our local machine.

cd blockchain-explorer
npm install

A directory should now be in your blockchain-explorer dir: /node_modules

You can run the tests by navigating to blockchain-explorer/app/test and executing: npm install; npm build; npm run test

I had a small issue here in that the blockchain-explorer/app/explorerconfig.json wasn’t being picked up by blockchain-explorer/app/test/postgrespgtest.js – so I manually hard coded in my local db setup:

const options = {
testdb: 'pgtestdb',
messages: false,
connection: {
host: 'localhost',
port: '5432',
user: 'postgres',
password: ''
}
};

This then gave me 100% test pass.

 npm run test

> hyperledger-explorer-test@0.3.9 test ~/blockchain-explorer/app/test
> nyc mocha *.js --exit



 GET /api/block/:channel_genesis_hash/:number
 ✓ should return block 

 GET /api/blockactivity/:channel_genesis_hash
 ✓ should return blockactivity 

 GET /api/blockAndTxList/:channel/:blocknum
 ✓ should return blockandtx 

 GET /api/blocksByHour/:channel_genesis_hash/:day
 ✓ should return blockbyhour 

 GET /api/blocksByMinute/:channel_genesis_hash/:hour
 ✓ should return blockbyminute 

 GET /api/block/transactions/:channel_genesis_hash/:number
 ✓ should return blocktransaction 

 GET /api/chaincode/:channel
 ✓ should return chaincode 

 GET /api/changeChannel/:channelName
 ✓ should return changedchannel 

 GET /api/channels/
 ✓ should return channels 

 GET /api/channels/info
 ✓ should return channelsinfo 

 GET /api/curChannel
 ✓ should return currentchannel 

 dateUtils().toUTCmilliseconds
 ✓ dateUtils.toUTCmilliseconds should be not null

 POST /auth/enroll/
 ✓ should return enroll 

 POST /auth/login
 ✓ should return login 

 GET /auth/networklist
 ✓ should return networklist 

 GET /api/peer/channel
 ✓ should return peers 

 Test explorerpg.sql for DDL statements syntax verification
 ✓ should read the file explorerpg.sql for ddl statements 
TAP version 13
# Test Results
# Test completed and Temporary database deleted
 ✓ should execute statements successfully in explorerpg.sql file 

 POST /auth/register/
 ✓ should return register 

 GET api/status/:channel_genesis_hash
(node:55197) UnhandledPromiseRejectionWarning: error: role "postgres" does not exist
 at Connection.parseE (~/blockchain-explorer/app/test/node_modules/pg/lib/connection.js:553:11)
 at Connection.parseMessage (/Users/robevans/dev/blockchain-explorer/app/test/node_modules/pg/lib/connection.js:378:19)
 at Socket.<anonymous> (/Users/robevans/dev/blockchain-explorer/app/test/node_modules/pg/lib/connection.js:119:22)
 at emitOne (events.js:116:13)
 at Socket.emit (events.js:211:7)
 at addChunk (_stream_readable.js:263:12)
 at readableAddChunk (_stream_readable.js:250:11)
 at Socket.Readable.push (_stream_readable.js:208:10)
 at TCP.onread (net.js:601:20)
(node:55197) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:55197) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
 ✓ should return channel status

 getLogger()
 ✓ should getLogger()

 GET /api/transaction/:channel_genesis_hash/:txid
 ✓ should return transaction 

 GET /api/txByHour/:channel_genesis_hash/:day
 ✓ should return txbyhour 

 GET /api/txByMinute/:channel_genesis/:hour
 ✓ should return txbyminute 

 GET /api/txByOrg/:channel
 ✓ should return txbyorg 


 25 passing (69ms)


1..0
# tests 0
# pass 0

# ok

---------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files | 99.73 | 97.37 | 98.29 | 99.73 | |
 block.js | 100 | 100 | 100 | 100 | |
 blockactivity.js | 100 | 100 | 100 | 100 | |
 blockandtx.js | 100 | 100 | 100 | 100 | |
 blocksbyhour.js | 100 | 100 | 100 | 100 | |
 blocksbyminute.js | 100 | 100 | 100 | 100 | |
 blocktransaction.js | 100 | 100 | 100 | 100 | |
 chaincode.js | 100 | 100 | 100 | 100 | |
 changechannel.js | 100 | 100 | 100 | 100 | |
 channels.js | 100 | 100 | 100 | 100 | |
 channelsinfo.js | 100 | 100 | 100 | 100 | |
 currentchannel.js | 100 | 100 | 100 | 100 | |
 dateutil.js | 100 | 100 | 100 | 100 | |
 enroll.js | 100 | 100 | 100 | 100 | |
 login.js | 100 | 100 | 100 | 100 | |
 networklist.js | 100 | 100 | 100 | 100 | |
 peer.js | 100 | 100 | 100 | 100 | |
 postgrespgtest.js | 97.14 | 96.67 | 80 | 97.06 | 110,113 |
 register.js | 100 | 100 | 100 | 100 | |
 status.js | 100 | 100 | 100 | 100 | |
 transaction.js | 100 | 100 | 100 | 100 | |
 txbyhour.js | 100 | 100 | 100 | 100 | |
 txbyminute.js | 100 | 100 | 100 | 100 | |
 txbyorg.js | 100 | 100 | 100 | 100 | |
---------------------|----------|----------|----------|----------|-------------------|

Running the Hyperledger Fabric Blockchain Explorer Client

You must now update:

  • the private key path in: blockchain-explorer/connection-profile/first-network.json
  • the other paths to point to the fabric-sample dir (see bottom of this page for my configs)

To populate the database and run the hyperledger blockchain-explorer invoke the start.sh script in the root of the blockchain-explorer project:

cd blockchain-explorer
./start.sh

output:

./start.sh 
**********************************************************************
************** Hyperledger Explorer **********************************
**********************************************************************
* Check the log [logs/console/console-2019-06-19.log] for any error *
**********************************************************************

If all has gone well, your postgres database should be populated with the network config data, and the client ready to access at localhost:8080.

Be sure to check the blockchain-explorer/logs/console logs for errors. Mine had no major errors. And looks as follows:

false 'ssl-certs' '~/blockchain-explorer/ssl-certs'
postgres://hppoc:password@127.0.0.1:5432/fabricexplorer
******* Initialization started for hyperledger fabric platform ******, { 'first-network': 
   { name: 'first-network',
     profile: './connection-profile/first-network.json' } }
 client_configs.name  first-network  client_configs.profile  ./connection-profile/first-network.json
FabricUtils.createFabricClient 
config.client.tlsEnable  true
FabricConfig, this.config.channels  mychannel
initializeChannelFromDiscover  mychannel
 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 

Channel genesis hash for channel [mychannel] >> 05dd9691868acc6ad129ac93d2f63deb592c7ab73f9ab3de92362a148042fbde
FabricUtils.createDetachClient 


Please open web browser to access :http://localhost:8080/


pid is 10665


postgres://hppoc:password@127.0.0.1:5432/fabricexplorer

Sync process is started for the network : [first-network] and client : [first-network]
config.client.tlsEnable  true
FabricConfig, this.config.channels  mychannel
(node:10685) DeprecationWarning: grpc.load: Use the @grpc/proto-loader module with grpc.loadPackageDefinition instead
An identity for the admin user: admin already exists in the wallet
initializeChannelFromDiscover  mychannel
 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 

Channel genesis hash for channel [mychannel] >> 05dd9691868acc6ad129ac93d2f63deb592c7ab73f9ab3de92362a148042fbde
SyncServices.synchNetworkConfigToDB client  first-network  channel_name  mychannel
initializeChannelFromDiscover  mychannel
 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 

insertNewOrderers discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050


Synchronizer pid is 10685


saveTransaction  true
block_row.blocknum  4
status  true
saveTransaction  true
... 
   MORE POPULATING THE POSTGRES DB
...
block_row.blocknum  3
status  true
initializeChannelFromDiscover  mychannel
initializeChannelFromDiscover  mychannel
initializeChannelFromDiscover  mychannel
 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 

initializeChannelFromDiscover  mychannel
initializeChannelFromDiscover  mychannel
 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }
...
initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 

 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 

insertNewOrderers discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050
insertNewOrderers discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050
insertNewOrderers discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050
insertNewOrderers discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050
initializeChannelFromDiscover  mychannel
initializeChannelFromDiscover  mychannel
initializeChannelFromDiscover  mychannel
initializeChannelFromDiscover  mychannel
 FabricClient.discover_results  endpoint  { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol  grpcs  requesturl  grpcs://orderer.example.com:7050 
...
SyncPlatform initialize()-- @ Wed Jun 19 2019

Sync process is started for the network : [first-network] and client : [first-network]
config.client.tlsEnable true
FabricConfig, this.config.channels mychannel
An identity for the admin user: admin already exists in the wallet
initializeChannelFromDiscover mychannel
 FabricClient.discover_results endpoint { host: 'orderer.example.com', port: 7050 }

initializeChannelFromDiscover.discoveryProtocol grpcs requesturl grpcs://orderer.example.com:7050 
...
etc.

To ensure the hyperledger blockchain-explorer is running

ps -ef | grep blockchain-explorer
501 11972 11952   0  3:32pm ttys006    0:02.34 /usr/local/Cellar/node@8/8.16.0/bin/node /Users/robevans/blockchain-explorer/sync.js first-network first-network 1

 If you don’t see something similar to the above for the ps -ef command, check the logs to see what’s gone wrong. 

All the necessary configs I’ve used are below.

Troubleshooting

Check the blockchain-explorer/logs/console dir for error messages in the logs. Check the terminal output as well. This will provide some hints.

If you get ECONNREFUSED this is telling you the application postgres config is bad. My config files are below:

blockchain-explorer/app/explorerconfig.json

{
 "persistence": "postgreSQL",
 "platforms": ["fabric"],
 "postgreSQL": {
 "host": "127.0.0.1",
 "port": "5432",
 "database": "fabricexplorer",
 "username": "hppoc",
 "passwd": "password"
 },
 "sync": {
 "type": "local",
 "platform": "fabric",
 "blocksSyncTime": "1"
 },
 "jwt": {
 "secret": "a secret phrase!!",
 "expiresIn": "2h"
 }
}

note here that the value of key persistence is postgreSQL and there is a corresponding key with the exact same value. This is vital for the config to work as there is some code that uses the value of the persistence key to lookup the database configuration for storing the network config.

The value for platforms is also important and should remain as is – there are other keys that use fabric as the value as this is a key in the source code.

blockchain-explorer/app/platform/fabric/config.json

{
 "network-configs": {
  "first-network": {
   "name": "first-network",
   "profile": "./connection-profile/first-network.json"
  }
 },
 "license": "Apache-2.0"
}

I found on several attempts that I would start the application and would occasionally see the login page flash up for a split second, then I’d see a blank page. If you get a blank page, try refreshing with the developer tools open and see if you get any output on the browser console. I saw something along the lines of:

networkList undefined

On closer inspection of the source code I found this was due to the fact that the config wasn’t being picked up from the json key network-configs in the config above.

blockchain-explorer/app/platform/fabric/connection-profile

{
 "name": "first-network",
 "version": "1.0.0",
 "license": "Apache-2.0",
 "client": {
  "tlsEnable": true,
  "adminUser": "admin",
  "adminPassword": "adminpw",
  "enableAuthentication": false,
  "organization": "Org1",
  "connection": {
   "timeout": {
    "peer": {
     "endorser": "300"
    },
    "orderer": "300"
   }
  }
 },
 "channels": {
  "mychannel": {
   "peers": {
    "peer0.org1.example.com": {}
   },
   "connection": {
    "timeout": {
     "peer": {
      "endorser": "6000",
      "eventHub": "6000",
      "eventReg": "6000"
     }
    }
   }
  }
 },
 "organizations": {
  "Org1MSP": {
   "mspid": "Org1MSP",
   "fullpath": true,
   "adminPrivateKey": {
    "path": "~/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/c2a6da108fa12c85accf58fda5078f4a89c7d93dbb46dda31b9af8272ae7c8af_sk"
   },
   "signedCert": {
    "path": "~/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/Admin@org1.example.com-cert.pem"
   }
  }
 },
 "peers": {
  "peer0.org1.example.com": {
   "tlsCACerts": {
    "path": "~/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
   },
   "url": "grpcs://localhost:7051",
   "eventUrl": "grpcs://localhost:7053",
   "grpcOptions": {
    "ssl-target-name-override": "peer0.org1.example.com"
   }
  }
 }
}