This tutorial shows you how to connect a Transport Layer Security (TLS)-enabled Hyperledger Fabric Network using Fabric Java SDK. It provides basic instructions for getting started interacting with a TLS-enabled network. It also explains how to use TLS certificates and provide them in Fabric Java SDK API requests so that clients can send requests over a secured layer.

Background

The Linux Foundation’s Hyperledger Fabric is a permissioned network that provides a platform for distributed ledger solutions underpinned by a modular architecture delivering high degrees of confidentiality, resiliency, flexibility, and scalability.

In blockchain solutions, the blockchain network works as a back end while an application front-end communicates with the network using an SDK. To set up communications between the front and back ends, the Hyperledger Fabric community offers a number of SDKs for a wide variety of programming languages. This tutorial will focus on Fabric Java SDK.

Hyperledger Fabric supports both secure and non-secure communication between nodes. The non-secure communication method is covered in the code pattern Create and deploy a blockchain network using Hyperledger Fabric SDK for Java. The secure method is achieved using Transport Layer Security (TLS).

Learning objectives

Client applications usually connect to a Hyperledger Fabric network through SDK APIs. There is a difference between the way the SDK calls the Hyperledger Fabric network when the network is secured using TLS and when the network is not secured. This tutorial will focus on the former situation — you will learn how to use Fabric Java SDK to enable client applications to interact with Hyperledger Fabric networks that are secured by enabling TLS.

Prerequisites

Before you start this tutorial, you will need:

  • Familiarity with blockchain technology and Hyperledger Fabric
  • To set up a Hyperledger Fabric network
  • Chaincode that is deployed and instantiated

Estimated time

It should take you about 30 minutes to complete this tutorial.

Steps

  1. Get the Hyperledger Fabric network details
  2. Enroll the admin
  3. Register and enroll the users
  4. Invoke the chaincode
  5. Query the chaincode

1. Get the Hyperledger Fabric network details

For the SDK to connect and perform operations on the Hyperledger Fabric network, you need network details like the URLs for peer, ca, orderer, channel name, pem certificates for ca, orderer (as it is TLS enabled), and chaincode details. The network can be set up in different ways. Here’s where you can find the network configuration details for each case:

  • IBM Blockchain Platform — The IBM Blockchain Platform provides the network configuration details as a connection profile (in JSON). You can get the network details from the connection profile.
  • Network setup using Docker Compose — Get the appropriate certificates from the crypto-config directory, along with other network details like IP and port which are defined in the configuration (yaml) file.
  • Network setup using Kubernetes — Copy the certificates (crypto-config) from the Kubernetes pod to your local system, get the public IP of the Kubernetes cluster and other network configuration details from configuration (yaml) files.

2. Enroll the admin

When the Hyperledger Fabric network was originally launched, an admin user was registered with the certificate authority (CA). Now you need to send an enroll call to the CA server to retrieve the enrollment certificate (eCert) for the admin. The client application needs this certificate in order to form a user object for the admin. You will then use this admin object to register and enroll a new user.

  1. Create an instance of the org.hyperledger.fabric_ca.sdk.HFCAClient class. This requires the CA URL, name, and pem certificate.

    Note: You can either use the pem cert file content as a string directly, or parse that file location and get the content.

    String caUrl = "https://xxx-org1-ca.aus01.blockchain.ibm.com:31011"; // ensure that port is of CA
    String caName = "org1CA";
    String pemStr = "-----BEGIN CERTIFICATE-----\r\n****\r\n-----END CERTIFICATE-----\r\n";
    
    Properties properties = new Properties();
    properties.put("pemBytes", pemStr.getBytes());
    
    HFCAClient hfcaClient = HFCAClient.createNewInstance(caName, caUrl, properties);
    
  2. Use the default crypto suite:

    CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
    hfcaClient.setCryptoSuite(cryptoSuite);
    

    The admin user enrollment requires certain user details. We have created a class called UserContext which holds those user details. You can refer to this class code in the code repository provided, along with the code pattern mentioned above.

  3. Set the UserContext:

    UserContext adminUserContext = new UserContext();
    adminUserContext.setName("admin"); // admin username
    adminUserContext.setAffiliation("org1"); // affiliation
    adminUserContext.setMspId("org1"); // org1 mspid
    
  4. Call the enroll API and set the enrollment in the UserContext object. It requires an admin user name and password:

    Enrollment adminEnrollment = hfcaClient.enroll("admin", "xxxxxxx"); //pass admin username and password
    adminUserContext.setEnrollment(adminEnrollment);
    
  5. This admin user context, with the enrollment set, will be used in subsequent user registration and enrollment. The admin user context should be stored to a local file system so that subsequent calls can use the admin user context.

    Util.writeUserContext(adminUserContext); // save admin context to local file system
    

3. Register and enroll the users

To perform various operations on the network, you should not use the admin user since the admin has all the privileges. New users need to be registered and enrolled to perform various operations.

  1. Register a new user:

    UserContext userContext = new UserContext();
    userContext.setName(name);
    userContext.setAffiliation("org1");
    userContext.setMspId("org1");
    
    RegistrationRequest rr = new RegistrationRequest("user1", "org1");
    String enrollmentSecret = hfcaClient.register(rr, adminUserContext);
    
  2. Enroll the user:

    Enrollment enrollment = hfcaClient.enroll(userContext.getName(), enrollmentSecret);
    userContext.setEnrollment(enrollment);
    Util.writeUserContext(userContext);
    

    Note: Once a user is registered, you cannot register again with the same user name.

4. Invoke the chaincode

To update or query the ledger in a proposal transaction, you need to invoke the chaincode. To do this, you need the function name that is defined in the chaincode and its arguments. In addition, the user context is also required to perform the invoke operation. This is the same user context that was saved in the “Register and enroll the users” section above.

  1. Read the user context that was saved:

    UserContext adminUserContext = Util.readUserContext("org1", "admin");
    CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
    HFClient hfClient = HFClient.createNewInstance();
    hfClient.setCryptoSuite(cryptoSuite);
    hfClient.setUserContext(adminUserContext);
    
  2. Create the peer, eventhub, and orderer references. Note that you need to read the corresponding pem certificates.

     String peer_name = "org1-peer1";
     String peer_url = "grpcs://xxxxx-org1-peer1.aus01.blockchain.ibm.com:xxxxx"; // Ensure that port is of peer1
     String pemStr = "-----BEGIN CERTIFICATE-----\r\nxxxxxx\r\n";
    
     Properties peer_properties = new Properties();
     peer_properties.put("pemBytes", pemStr.getBytes());
     peer_properties.setProperty("sslProvider", "openSSL");
     peer_properties.setProperty("negotiationType", "TLS");
    
     Peer peer = hfClient.newPeer(peer_name, peer_url, peer_properties);
    
     String event_url = "grpcs://xxxxxx-org1-peer1.xxxx.blockchain.ibm.com:31003"; // ensure that port is of event hub
     EventHub eventHub = hfClient.newEventHub(peer_name, event_url, peer_properties);
    
     String orderer_name = "orderer";
     String orderer_url = "grpcs://xxxxx-orderer.xxxx.blockchain.ibm.com:31001"; // ensure that port is of orderer
     String pemStr1 = "-----BEGIN CERTIFICATE-----\r\nxxxxx\r\n-----END CERTIFICATE-----\r\n";
    
     Properties orderer_properties = new Properties();
     orderer_properties.put("pemBytes", pemStr1.getBytes());
     orderer_properties.setProperty("sslProvider", "openSSL");
     orderer_properties.setProperty("negotiationType", "TLS");
     Orderer orderer = hfClient.newOrderer(orderer_name, orderer_url, orderer_properties);
    
  3. Initialize the channel:

     Channel channel = hfClient.newChannel(CHANNEL_NAME);
    
     channel.addPeer(peer);
     channel.addEventHub(eventHub);
     channel.addOrderer(orderer);
     channel.initialize();
    
  4. Prepare the transaction proposal and send it to the endorsers:

     TransactionProposalRequest request = hfClient.newTransactionProposalRequest();
     String cc = "carauction"; // Chaincode name
     ChaincodeID ccid = ChaincodeID.newBuilder().setName(cc).build();
    
     request.setChaincodeID(ccid);
     request.setFcn("initLedger"); // Chaincode invoke funtion name
     String[] arguments = { "N4", "Provider", "28-01-2019", "Food", "1000", "04-02-2019" }; // Arguments that Chaincode function takes
     request.setArgs(arguments);
     request.setProposalWaitTime(3000);
     Collection<ProposalResponse> responses = channel.sendTransactionProposal(request);
     for (ProposalResponse res : responses) {
       // Process response from transaction proposal
     }
    
  5. Send the transaction to the orderer:

     CompletableFuture<TransactionEvent> cf = channel.sendTransaction(responses);
    

5. Query the chaincode

Blockchain transactions that are committed can be queried.

  1. Perform the same steps for channel initialization as explained in the “Invoke the chaincode” section above.

  2. Prepare the transaction proposal and send it to the peer:

    QueryByChaincodeRequest queryRequest = hfClient.newQueryProposalRequest();
    queryRequest.setChaincodeID(ccid); // ChaincodeId object as created in Invoke block
    queryRequest.setFcn("query"); // Chaincode function name for querying the blocks
    
    String[] arguments = { "all"}; // Arguments that the above functions take
    if (arguments != null)
     queryRequest.setArgs(arguments);
    
    // Query the chaincode  
    Collection<ProposalResponse> queryResponse = channel.queryByChaincode(queryRequest);
    
    for (ProposalResponse pres : queryResponse) {
     // process the response here
    }
    

Summary

In this tutorial, you learned how to use Java SDK APIs with a TLS-enabled Hyperledger Fabric Network. To work with a TLS-enabled Fabric network, you need to use the appropriate pem certificates for the various components as those certificates provide authentication for interactions between the components. This tutorial has shown you how to enroll admins, register and enroll users, and invoke and query chaincode. You should now be able to develop an integration layer to build blockchain applications. While the instructions provided here are for the Java SDK, you can use other methods to develop an integration layer. You can find more details here.