Blockchain - Group home

Developing a R3 Corda Enterprise network on IBM Cloud Hyper Protect Virtual Servers

  

Introduction

Design principles that govern R3’s Corda Enterprise blockchain platform are security, resiliency and scalability – with the performance needed by enterprise workloads. It’s natural for Corda Enterprise users to want to run their Corda workloads on infrastructure governed by those same design principles. It’s this natural synergy that led to the collaboration between IBM Systems and R3 to bring Corda Enterprise to LinuxONE – which has a long history of delivering secure, resilient and scalable infrastructure to the world’s most demanding and mission critical workloads. The IBM LinuxONE Hyper Protect Digital Asset Platform provides technical assurance your R3 Corda Enterprise workload and digital assets are protected from insider and outsider threats, while at-rest, in-transit, and in use.

In this tutorial you will learn how to begin your journey of protecting your R3 Corda application by building a development R3 Corda Enterprise network in our IBM Cloud Hyper Protect Virtual Server.

This tutorial utilizes the Ping-Pong CorDapp as a sample application. The application passes simple messages amongst nodes in the network. Additional samples from the R3 Corda Open Source community may be utilized. Please note that not all samples have been updated to use Java 11.

Learning objectives

When you've completed this tutorial, you will understand how to:

  • Deploy a Hyper Protect Virtual Server
  • Build a sample CorDapp for a R3 Corda network
  • Deploy R3 Corda nodes on a Hyper Protect Virtual Server
  • Run a sample transaction

Prerequisites

To complete this tutorial, you will need:

Estimated time

It should take you 2 hours to complete this tutorial.

Steps

  1. Create Hyper Protect Virtual Servers
  2. Build a sample R3 Corda Enterprise CorDapp
  3. Creating your R3 Corda Enterprise development network
  4. Starting your Notary and Party A nodes
  5. Starting your Party B node
  6. Testing it all out by pinging a node

1. Create Hyper Protect Virtual Servers

In this step, I will show you how to install the Hyper Protect Virtual Servers plugin for the IBM Cloud CLI and order two Hyper Protect Virtual Server instances.

A. From your command line terminal, establish a connection to IBM Cloud and login:

ibmcloud login

B. Install the Hyper Protect Virtual Servers plugin for the stand-alone IBM Cloud CLI:

ibmcloud plugin install hpvs

C. Use the Hyper Protect Virtual Servers plugin to create your first server using the following parameters:

  • name: R3 Corda Enterprise Server one
  • plan: free
  • location: The location ID to deploy your Hyper Protect Virtual Server instance to. To list available locations, run the 'ibmcloud catalog service hpvs' command.
  • ssh-path: The location of your SSH public key file.
ibmcloud hpvs instance-create "R3 Corda Enterprise Server one" free <location> --ssh-path <path-to-ssh-public-key>

Check the provisioning status regularly with the command you get as a response and wait until the instance becomes available.

D. We will be splitting your Corda network across two Hyper Protect Virtual Server instances, so go ahead and create your second server. Note: It is recommended to create your second server in a different location.

ibmcloud hpvs instance-create "R3 Corda Enterprise Server two" free <location> --ssh-path <path-to-ssh-public-key>


E.
Use the ibmcloud hpvs instances command to identify the public IP addresses for the instances you have created.

Instance Public IP Address
R3 Corda Enterprise Server one
R3 Corda Enterprise Server two

2. Build a sample R3 Corda Enterprise CorDapp

In this step, I will show you how to build your R3 Corda Enterprise CorDapp.

A. The Beta Program artifacts of Corda Enterprise are available from the login account on Egnyte that you receive when you register as a Beta Program customer. The artifacts are in a .tar file. Transmit the file to your first IBM Cloud Hyper Protect Virtual Server.

scp <path>/CE4.6.1-BETA-JDK11.tar.gz root@<r3_corda_enterprise_server_one_public_ip>:~

B. Login to R3 Corda Enterprise Server one:

ssh -o ServerAliveInterval=120 -i <path-to-ssh-private-key> root@<r3_corda_enterprise_server_one_public_ip>

C. On your R3 Corda Enterprise Server one, expand your Corda Enterprise bundle into your local repository:

mkdir ~/.m2
tar zxvf ~/CE4.6.1-BETA-JDK11.tar.gz -C ~/.m2

D. In this demo we have chosen to use AdoptOpenJDK11 with Eclipse OpenJ9 as our JVM. Perform the following set of commands to install it:

sudo apt update && sudo apt install -y wget apt-transport-https gnupg
wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -
echo "deb [arch=$(dpkg --print-architecture)] https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/ $(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) main" | sudo tee /etc/apt/sources.list.d/adoptopenjdk.list
sudo apt update && sudo apt install -y --allow-unauthenticated adoptopenjdk-11-openj9

E. Now lets select a sample CorDapp to test with. We have chosen the Ping Pong application for this tutorial. Complete the following steps to assemble the JAR file:

sudo apt install -y git unzip docker.io gpg jq
mkdir ~/src
pushd ~/src
git clone https://github.com/corda/samples-kotlin.git -b jdk11
popd
pushd ~/src/samples-kotlin/Basic/pingpong
./gradlew assemble
popd

3. Creating your R3 Corda Enterprise development network

Now that you have a CorDapp, its time to start building your R3 Corda Enterprise network. In this step I will show you how to create your R3 Corda Enterprise nodes.

As part of this step we will need to lay out which nodes will reside on which server. I have chosen to install the nodes as follows:

R3 Corda Enterprise Server one

  • R3 Corda Enterprise Notary node
  • R3 Corda Enterprise Party A node

R3 Corda Enterprise Server two

  • R3 Corda Enterprise Party B node

A. On R3 Corda Enterprise Server one create a working directory structure for setting up your R3 nodes.

mkdir -p ~/src/bootstrap/

B. Create your Notary node configuration file:

  • Change HPVS_IP1 to the Public IP address for R3 Corda Enterprise Server one
  • We are bootstrapping this node in development mode. This tutorial is not intended for production use.
  • Change other values as you see fit.
tee -a ~/src/bootstrap/notary_node.conf < END
p2pAddress = "HPVS_IP1:10002"
rpcSettings {
    address: "0.0.0.0:10003"
    adminAddress: "127.0.0.1:10004"
}
notary { 
    validating=true
}
sshd {
  port = 60003
}
rpcUsers : [
  {
    password : "secret",
    permissions : [
      "ALL"
    ]
    user : "user"
  }
]
custom = {
  jvmArgs = [ "-Xgc:concurrentScavenge" ]
}
useOpenSsl = true
myLegalName = "O=Notary,L=Dallas,S=Texas,C=US"
keyStorePassword: "secret"
trustStorePassword: "secret"
devMode: true
END

C. Create your node configuration file for Party A:

  • Change HPVS_IP1 to the Public IP address for R3 Corda Enterprise Server one
  • We are bootstrapping this node in development mode. This tutorial is not intended for production use.
  • Change other values as you see fit.
tee -a ~/src/bootstrap/partyA_node.conf < END
devMode=true
myLegalName="O=PartyA,L=Dallas,S=Texas,C=US"
p2pAddress="HPVS_IP1:10005"
rpcSettings {
    address="0.0.0.0:10006"
    adminAddress="0.0.0.0:10007"
}
security {
    authService {
        dataSource {
            type=INMEMORY
            users=[
                {
                    password=test
                    permissions=[
                        ALL
                    ]
                    user=user1
                }
            ]
        }
    }
}
sshd {
  port = 60006
}
END

D. Create your node configuration file for Party B:

  • Change HPVS_IP2 to the Public IP address for R3 Corda Enterprise Server two
  • We are bootstrapping this node in development mode. This tutorial is not intended for production use.
  • Change other values as you see fit.
tee -a ~/src/bootstrap/partyB_node.conf < END
devMode=true
myLegalName="O=PartyB,L=Dallas,S=Texas,C=US"
p2pAddress="HPVS_IP2:10008"
rpcSettings {
    address="0.0.0.0:10009"
    adminAddress="127.0.0.1:10010"
}
security {
    authService {
        dataSource {
            type=INMEMORY
            users=[
                {
                    password=test
                    permissions=[
                        ALL
                    ]
                    user=user1
                }
            ]
        }
    }
}
sshd {
  port = 60009
}
END

D. Copy in your CorDapp from step 2:

cp ~/src/samples-kotlin/Basic/pingpong/workflows-kotlin/build/libs/workflows-kotlin-0.1.jar ~/src/bootstrap

E. Bootstrap your R3 Corda Enterprise network:

java -jar ~/.m2/repository/com/r3/corda/corda-tools-network-bootstrapper/4.6.1-BETA1_JDK11/corda-tools-network-bootstrapper-4.6.1-BETA1_JDK11.jar --dir ~/src/bootstrap

4. Starting your Notary and Party A nodes

Now that you have a bootstrapped configuration we can run your first Corda Enterprise network. In this step I will show you how to start two of your three R3 Corda Enterprise nodes.

A. Create a corda user and setup the directory structure:

sudo adduser --system --no-create-home --group corda
sudo mkdir -p /opt/corda/notary
sudo mkdir -p /opt/corda/partyA
sudo cp -r ~/src/bootstrap/notary/* /opt/corda/notary/
sudo cp -r ~/src/bootstrap/partyA/* /opt/corda/partyA/
sudo chown --recursive corda:corda /opt/corda

B. Create a systemd service for the notary

sudo tee -a /etc/systemd/system/corda-notary.service << END
[Unit]
Description=Corda Node - Notary
Requires=network.target

[Service]
Type=simple
User=corda
WorkingDirectory=/opt/corda/notary
ExecStart=/usr/bin/java -jar /opt/corda/notary/corda.jar -n -b /opt/corda/notary
Restart=on-failure
Environment="CAPSULE_CACHE_DIR=./capsule"

[Install]
WantedBy=multi-user.target
END

C. Create a systemd service for Party A

sudo tee -a /etc/systemd/system/corda-partya.service << END
[Unit]
Description=Corda Node - Party A
Requires=network.target

[Service]
Type=simple
User=corda
WorkingDirectory=/opt/corda/partyA
ExecStart=/usr/bin/java -jar /opt/corda/partyA/corda.jar -n -b /opt/corda/partyA
Restart=on-failure
Environment="CAPSULE_CACHE_DIR=./capsule"

[Install]
WantedBy=multi-user.target
END

D. Start the Corda network nodes

sudo systemctl daemon-reload
sudo systemctl enable --now corda-notary
sudo systemctl enable --now corda-partya

E. Bundle up the partyB files for deployment on R3 Corda Enterprise Server two

tar czvhf /root/src/bootstrap/partyB.tgz -C /root/src/bootstrap/partyB .

F. Logoff of the Hyper Protect Server instance and transfer the partyB.tgz file to your local system.

scp root@<r3_corda_enterprise_server_one_public_ip>:~/src/bootstrap/partyB.tgz <path>/partyB.tgz

5. Starting your Party B node

In this step I will show you how to start your last R3 Corda Enterprise node.

A. Transfer the partyB.tgz file from your local system to R3 Corda Enterprise Server two:

scp  <path>/partyB.tgz root@<r3_corda_enterprise_server_two_public_ip>:~/partyB.tgz

B. Login to R3 Corda Enterprise Server two:

ssh -o ServerAliveInterval=120 -i <path-to-ssh-private-key> root@<r3_corda_enterprise_server_two_public_ip>

C. Repeat the following set of commands to install AdoptOpenJDK11 with Eclipse OpenJ9 as the JVM on server two:

sudo apt update && sudo apt install -y wget apt-transport-https gnupg
wget -qO - https://adoptopenjdk.jfrog.io/adoptopenjdk/api/gpg/key/public | sudo apt-key add -
echo "deb [arch=$(dpkg --print-architecture)] https://adoptopenjdk.jfrog.io/adoptopenjdk/deb/ $(cat /etc/os-release | grep UBUNTU_CODENAME | cut -d = -f 2) main" | sudo tee /etc/apt/sources.list.d/adoptopenjdk.list
sudo apt update && sudo apt install -y --allow-unauthenticated adoptopenjdk-11-openj9

D. Create a corda user and setup the directory structure:

sudo adduser --system --no-create-home --group corda
sudo mkdir -p /opt/corda/partyB
sudo tar zxvf ~/partyB.tgz -C /opt/corda/partyB/
sudo chown --recursive corda:corda /opt/corda

E. Create a systemd service for Party B

sudo tee -a /etc/systemd/system/corda-partyb.service << END
[Unit]
Description=Corda Node - Party B
Requires=network.target

[Service]
Type=simple
User=corda
WorkingDirectory=/opt/corda/partyB
ExecStart=/usr/bin/java -jar /opt/corda/partyB/corda.jar -n -b /opt/corda/partyB
Restart=on-failure
Environment="CAPSULE_CACHE_DIR=./capsule"

[Install]
WantedBy=multi-user.target
END

F. Start the Corda network node for Party B:

sudo systemctl daemon-reload
sudo systemctl enable --now corda-partyb

6. Testing it all out by pinging a node

Now that we have a R3 Corda Enterprise network running on two nodes in development mode, lets test it out.

A. Let's watch the logs on Party B while are performing our test:

tail -f /opt/corda/partyB/logs/details-node-*.log

B. Open a new terminal window on your local machine and connect into the shell for PartyA. Refer to the information you provided in step 3C:

  • SSH port: 60006
  • SSH userid: user1
  • password: test
ssh user1@<r3_corda_enterprise_server_one_public_ip> -p 60006

C. Run the following command from PartyA's shell:

start ping counterparty: PartyB

D. In the window where you are watching the logs from Party B, you should see messages similar to:

[TRACE] 2021-05-26T21:16:57,616Z Message(action=receive;flowId=null;size=2145;id=N-R--6345692555653902422-962551194441449941-1-0;platformVersion=8;from=O=PartyA, L=Dallas, ST=Texas, C=US) {}


...


[TRACE] 2021-05-26T21:16:57,710Z Message(action=send;flowId=5fc61c6c-85ee-4059-ba54-83b62f69bf27;size=936;id=N-D--6345692555653902422-962551194441449941-4-0;to=NodeAddress(queueName=internal.peers.DLB3gW6oU5PSCtALT7Akn36hLWkwGNcwjK38D6rGbZvkkN)) {fiber-id=10000009, flow-id=5fc61c6c-85ee-4059-ba54-83b62f69bf27, invocation_id=e16db05c-8cb7-4f6a-9bff-60f1be304c42, invocation_timestamp=2021-05-26T21:16:57.618438030Z, origin=O=PartyA, L=Dallas, ST=Texas, C=US, session_id=e16db05c-8cb7-4f6a-9bff-60f1be304c42, session_timestamp=2021-05-26T21:16:57.618438030Z, thread-id=221}

Summary

In this tutorial, you have learned how you can run a R3 Corda Enterprise network from the Hyper Protect Virtual Servers service. You can now continue on your learning by creating one of your Corda nodes as a protected application using a custom image from the Hyper Protect Virtual Servers service.