Welcome back to the unofficial guide to AWS’s Hyperledger Fabric template. In the first part of this series we focused on the set up of a AWS host provisioned through the official AWS template.

As a quick refresher let’s recap the goals of this blog series. By following these step-by-step instructions, you will be able to accomplish the following:

Leverage AWS’s Hyperledger Fabric template to provision infrastructure for 3 organizations with 1 peer each joining the consortium network. Find your way around the AWS-hosted cloud host plus the basics of the Fabric command line interface. Run multiple instances of IBM’s Marbles decentralized application demo against a consortium network.

In this article we will learn how to navigate identity without Fabric Certificate Authorities (not provisioned in AWS template), deploy chaincodes (Fabric-speak for smart contracts), and prepare the network to run multiple instances of Marbles against it to ultimately deploy and showcase how decentralized applications, such as IBM’s Marbles, work end-to-end in a consortium network.

Architectural illustration of Marbles dapp from https://github.com/IBM-Blockchain/marbles

Part 2: Deploy Marbles dapps into consortium network

Before we jump right in please be sure to complete all steps of the first part of this blog series end-to-end. The following steps are a prerequisite for Part 2 to work properly.

Step 1: Setup workspace

One caveat of the AWS Hyperledger Fabric template is that it omits the provisioning of Certificate Authorities (CAs) to issue certificates for all members of respective organizations on the fly. Instead, it pre-generates the certificates and secret keys using tooling bundled with Fabric. Please note that while pre-generated keys are a convenient option to get a Fabric network running quickly it is not recommended to be used in production. One single person or entity can’t ever be in possession of all organizations’ private keys.

Before we go fetch the crypto material from the AWS cloud host, let’s set up our local workspace. We chose to run multiple instances of the Marbles dapp on a local MacBook Pro with Boot2Docker running in a VirtualBox VM which is why we want the crypto material (certificates + secret keys for orgs) locally. To make this more convenient we’ve created a demo repo for everyone to download that will streamline the set up process.

You can either clone into the repo using git directly or grab a ZIP archive from dapphero-marbles-demo’s release page (please note git submodules won’t be part of the zip package). The repo requires two prerequisites, 1.) Docker + docker-compose and, 2.) a working node.js/npm environment. We’re using node v8.9.1 but any stable release greater should work too. We’ve ran this demo successfully on macOS and a few different flavors of Linux including AWS, Ubuntu, and Boot2Docker (on macOS). We have not tested this process on Windows yet. Please leave us a note if you are running into issues on Windows.

~ $ git clone https://github.com/dapphero/dapphero-marbles-demo.git ./demo

~ $ cd ~/demo

~ $ git submodule init && git submodule update

~/demo $ npm install .

~/demo $ docker pull dapphero/dapphero-marbles-demo:latest

The last two steps, where both npm and docker will install dependencies, might take a minute to complete. The time it takes to download the dependencies will greatly pay off as it will enable us to easily launch multiple instances of the Marbles dapp.

Step 2: Fetch crypto material from AWS cloud host

Let’s setup an entry in /etc/hosts to use a hostname rather than an IP address in subsequent steps. Use nano to append a line to the end of the file where 123.123.123.123 represents the IP address of your AWS cloud host. Use CTRL+X and confirm the file location and changes.

~/demo $ sudo nano /etc/hosts



123.123.123.123 host.example.com

Just like we’ve successfully ssh’d into the Fabric host the last time, we want to copy the crypto material using the scp command. Again, thanks to the decentralized nature of the application it won’t matter if you copy the file onto a local work station, a bastion host, or another Fabric-unrelated cloud host as long as inbound access to the Fabric host is whitelisted in the EC2 Security Group.

scp -i yourkey.pem -r ec2-user@host.example.com:/etc/fabric/crypto-config ./

>ca.example.com-cert.pem 100% 818 22.4KB/s 00:00

>28cb9daa1244b8223963dfdf55014a5c25c3ecca60887a129154233416fd64d9_sk 100% 241 6.4KB/s 00:00

>ca.example.com-cert.pem 100% 818 25.9KB/s 00:00

>

>d61c6c5b094c60ef58775c546121ed8bd8e374325fed5ace65dbd7359ad0e984_sk 100% 241 6.7KB/s 00:00

[...] ~/demo $>ca.example.com-cert.pem 100% 818 22.4KB/s 00:00>28cb9daa1244b8223963dfdf55014a5c25c3ecca60887a129154233416fd64d9_sk 100% 241 6.4KB/s 00:00>ca.example.com-cert.pem 100% 818 25.9KB/s 00:00 Admin@example.com -cert.pem 100% 769 21.2KB/s 00:00>d61c6c5b094c60ef58775c546121ed8bd8e374325fed5ace65dbd7359ad0e984_sk 100% 241 6.7KB/s 00:00[...]

Irrespective where the Marbles dapp will run a subset of the crypto material is required to make it work. The scp command above will kick off the copy process that will trace files individually and likely will take some time to complete.

The local directory ./crypto-config is quite extensive and should resemble the directory tree below. It is safe to skip the rather complex details about the directory’s structure for now. The official documentation is a great resource to satisfy curiosity about Membership Service Providers (MSPs).

~/demo $ tree -d -L 3 crypto-config

crypto-config

├── ordererOrganizations

│ └── example.com

│ ├── ca

│ ├── msp

│ ├── orderers

│ ├── tlsca

│ └── users

└── peerOrganizations

├── org1.example.com

│ ├── ca

│ ├── msp

│ ├── peers

│ ├── tlsca

│ └── users

├── [...repeats for org2., org3.]

Step 3: Pre-populate Fabric clients key/value stores

In a production-grade Hyperledger Fabric network identities would likely exclusively be issued by Fabric Certificate Authorities (CAs) individually controlled by their respective organization. The AWS Hyperledger Fabric template omits the provisioning of CAs. Unfortunately, the Marbles dapp requires to enroll, authenticate, and produce signatures for user identities. We will employ a nifty workaround using the Fabric Client SDK for node.js to spare ourselves re-writing large parts of the Marbles codebase to work without CAs. While this will teach us about the inner workings of APIs linking certificates (crypto material) and Fabric’s client SDK and protocol stack we do not recommend to put this workaround into a production environment.

The convenience program index.js bundled in the repo will essentially loop through all available orgs in the Fabric network, load relevant certificates and secret keys into an instance of the Fabric client, query the org’s host for available channels, and leverage the client’s local cache to persist the org’s admin identity into a pre-set directory. Later we will launch instances of Marbles with volume mounts of respective orgs persisted identity cache for the Fabric client to bootstrap from. The client’s filesystem cache acts as poor man’s API to hook up containers with identities without going through Fabric CAs. This is somewhat elegant because it won’t require us to change Marbles code to read identities directly from the pre-generated crypto material and keeps it isolated amongst Marbles dapp instances.

~/demo $ ./index.js dappinstances/marbles/config/blockchain_creds_tls.json crypto-config ./dappinstances/.hfc-key-store/

Prepopulating key/value store for

Prepopulating key/value store for

[ { username: '

peers: '[{"clientCert":null,"_options":{"grpc.ssl_target_name_override":"peer0.org1.example.com","grpc.default_authority":"peer0.org1.example.com","request-timeout":300000,"grpc.max_receive_message_length":-1,"grpc.max_send_message_length":-1,"grpc.primary_user_agent":"grpc-node/1.10.1"},"_url":"grpcs://host.example.com:7051","_endpoint":{"creds":{},"addr":"host.example.com:7051"},"_request_timeout":300000,"_endorserClient":{"$channel":{}},"_roles":{},"_name":"peer0.org1.example.com"}]',

channels: '{"channels":[{"channel_id":"mychannel"}]}' },

[...repeats for org2., org3.]

All set. Key value store populated. Prepopulating key/value store for Admin@org1.example.com located at 'dappinstances/.hfc-key-store/org1'.Prepopulating key/value store for Admin@org2.example.com located at 'dappinstances/.hfc-key-store/org2'.Prepopulating key/value store for Admin@org3.example.com located at 'dappinstances/.hfc-key-store/org3'.[ { username: ' Admin@org1.example.com ',peers: '[{"clientCert":null,"_options":{"grpc.ssl_target_name_override":"peer0.org1.example.com","grpc.default_authority":"peer0.org1.example.com","request-timeout":300000,"grpc.max_receive_message_length":-1,"grpc.max_send_message_length":-1,"grpc.primary_user_agent":"grpc-node/1.10.1"},"_url":"grpcs://host.example.com:7051","_endpoint":{"creds":{},"addr":"host.example.com:7051"},"_request_timeout":300000,"_endorserClient":{"$channel":{}},"_roles":{},"_name":"peer0.org1.example.com"}]',channels: '{"channels":[{"channel_id":"mychannel"}]}' },[...repeats for org2., org3.]All set. Key value store populated.

We will know this process completed successfully when the terminal prints “All set. Key value store populated.”. In the event of an error please make sure the ./crypto-config directory is not empty and the git submodule was properly initialized for ./dappinstances/marbles/config/blockchain_creds_tls.json to be available. You’ll be left with below’s directory tree where every orgX directory includes a file for user, public, and private key.

~/demo $ tree -d dappinstances/.hfc-key-store

dappinstances/.hfc-key-store

├── org1

├── org2

└── org3 3 directories

For now we will move on with the deployment of the Marbles dapp. However, in the third blog post of this multipart series we will take a closer look at how this workaround works.

Step 4: Launch Marbles dapp containers for orgs

Now we are ready to launch a container per org to serve the Marbles app. Please note that a working docker environment is required to do this successfully. We suggest to take a look at the official Docker compose documentation if you have not set it up yet.

~/demo $ cd dappinstances/

dappinstances $ export AWS_HOST=54.191.108.209 # (IP of AWS host)

dappinstances $ export IMAGE_NAME=dapphero/dapphero-marbles-demo:latest

dappinstances $ docker-compose up -d

dappinstances $ docker-compose ps

Name Command State Ports

---------------------------------------------------------------------------

dappinstances_marbles_org1_1 node app.js Up 0.0.0.0:3001->3001/tcp

dappinstances_marbles_org2_1 node app.js Up 0.0.0.0:3002->3001/tcp

dappinstances_marbles_org3_1 node app.js Up 0.0.0.0:3003->3001/tcp

Once the docker-compose command completes you should be left with three running containers. Please note that they are not fully operational yet as we will still have to install the Marbles chaincodes in all orgs’ peers and instantiate the chaincode, i.e. call the constructor for the channel used by the Marbles dapp.

Step 5: Install chaincodes in all orgs hosts

Since every org’s container was launched with its respective certificates and private keys of the admin identity in the Fabric clients cache, we can leverage the container to execute Fabric-level operational tasks, such as installing and instantiating the chaincodes in all org’s remote Fabric peers.

docker-compose exec marbles_org1 bash

root@db8b68c7e8c1:/marbles# ls -l /marbles/config/crypto/kvs

total 12

-rw-r--r-- 1 node staff 1061 Jun 5 22:48

-rw-r--r-- 1 node staff 246 Jun 5 22:48 cfc92a1d9b49c1b1d7acd805fdf88a198f37d9aa3ea92cea9439812eb321a4ed-priv

-rw-r--r-- 1 node staff 182 Jun 5 22:48 cfc92a1d9b49c1b1d7acd805fdf88a198f37d9aa3ea92cea9439812eb321a4ed-pub dappinstances $root@db8b68c7e8c1:/marbles#total 12-rw-r--r-- 1 node staff 1061 Jun 5 22:48 Admin@org1.example.com -rw-r--r-- 1 node staff 246 Jun 5 22:48 cfc92a1d9b49c1b1d7acd805fdf88a198f37d9aa3ea92cea9439812eb321a4ed-priv-rw-r--r-- 1 node staff 182 Jun 5 22:48 cfc92a1d9b49c1b1d7acd805fdf88a198f37d9aa3ea92cea9439812eb321a4ed-pub

We exit the container shell with CTRL+D and proceed with the installation of chaincodes on all peers. Run following commands in the ./demo/dappinstances directory. Please expect the command’s output will be a lot more elaborate than what’s below.

dappinstances $ docker-compose exec marbles_org1 bash -c "cd scripts && node install_chaincode.js marbles_tls_org1.json"

[...]

info: Install done. Errors: nope

---------------------------------------

dappinstances $ docker-compose exec marbles_org2 bash -c "cd scripts && node install_chaincode.js marbles_tls_org2.json"

[...]

info: Install done. Errors: nope

---------------------------------------

dappinstances $ docker-compose exec marbles_org3 bash -c "cd scripts && node install_chaincode.js marbles_tls_org3.json"

[...]

info: Install done. Errors: nope

---------------------------------------

If the chaincode was installed before an error message will indicate it already exists. It’s safe to run the command multiple times as every successive attempt will just fail to complete.

Step 6: Instantiate chaincode in channel

Now we can move on to instantiate the chaincode for the pre-provisioned channel mychannel that comes with the AWS Hyperledger Fabric template. We do this through one of the orgs’ containers since the AWS template configured mychannel to grant any of the tree orgs the right to instantiate chaincodes in this channel. In the next, third blog post, we will look under the hood of what install and instantiate means for chaincodes.

dappinstances $ docker-compose exec marbles_org1 bash -c "cd scripts && node instantiate_chaincode.js marbles_tls_org1.json"

[...]

debug: [fcw] Successfully obtained transaction endorsement

debug: [fcw] Successfully ordered instantiate endorsement.

---------------------------------------

info: Instantiate done. Errors: nope

---------------------------------------

Step 7: Marbles decentralized application-level set up

Now that Fabric network infrastructure (peers), channels (ledger), and chaincodes (smart contract) are read to roll we only need to finish the Marbles dapp setup as part of the application. We open three browser tabs with an instance of Marbles each where the hostname “localhost” points at the host running the docker containers (it’s a VirtualBox IP 192.168.99.100 address on our MacBook Pro).

Marbles dapp setup wizard and basic usage

Please be sure to include http:// as a lot of browsers default to https:// for consumer protection reasons. The Marbles decentralized web application served per tab should resemble the screencast above. Please be sure to follow the wizard’s sequence of steps for each tab (i.e. org) in your browser:

Login with “admin” — the identity is statically bound to the org’s respective admin (e.g. Admin@org1.example.com); even when the name’s changed. Click the “start” button in the wizard’s “Hi” modal. The wizard will drop into step 3 where it is not properly connected to ledger and channel as we launched the container and app before we completed the chain code setup. We will click the “Try Again” button to properly connect the Marbles to channel and ledger. The process won’t take longer than a few seconds. Once successfully completed we will close the wizard as the following steps are optional to e.g. create more marbles. Happy Marbles trading! We can drag and drop marbles from the top panel representing the authenticated org’s identity in every tab. Attempts to do the reverse will be rejected by the chaincode logic.

Congrats! We managed to deploy multiple instances of the Marbles dapp and you are now ready to not just trade them but also track the provenance of every marble on the decentralized ledger throughout its lifecycle.

Summary and what’s next

In this blog post we learnt how to deploy Marbles using the crypto material (certificates and private keys) pre-generated by AWS Hyperledger Fabric template. We managed to workaround the fact that the template omits the setup of Certificate Authorities that would allow Marble to dynamically enroll identities without the need to copy files off the AWS cloud host. The workaround we employed essentially replicates the Fabric client SDK’s cache for certificates and private keys per Marbles container and Fabric client respectively.

While in this blog post we swiftly walked through the steps to get multiple Marbles dapps up and running in the next post we want take a closer look some of the curious details of the Fabric client, operational tasks such as installing/instantiating chaincodes, and how Marbles specifically configures & utilizes chaincodes and caveats worth noting.

As always, we are looking forward to your feedback and questions in the comments below or through Dapphero’s contact form.