Develop a Hyperledger Fabric 1.4.x application with Convector Suite

Aboubakar Koïta
24 min readMay 15, 2019

--

This article aims to show how to develop a Hyperledger Fabric 1.4.x application. But it will start with a brief introduction on what blockchain is and the difference between public and enterprise blockchain. It will then briefly describe Hyperledger Fabric and finally show step by step the development of an example of Hyperledger Fabric application using the TypeScript framework Convector.

Source code of the Fabric project studied in the article is available on GitHub: https://github.com/akoita/start-with-convector

Introduction

I was fascinated three years ago when I discovered Bitcoin and the technological trend that emerged from it, i.e. the blockchain. The formalization of the blockchain concept was motivated by the interest that some people perceived in its application outside the original context of creating a decentralized digital currency. It has been found that the blockchain has a potential application in any context where actors need to transmit “value” to each other without going through the service of a trusted third party.

After a few years of euphoria about the transformation potential of blockchain, it seems that expectations, although still high, have become more measured, now that the first initiatives are facing the reality of blockchain adoption. Those who believe in this technology advocate patience and compare it to its current state with the Internet in the early 1990s.

Outside Bitcoin, there are hundreds of blockchain platforms today. A very large number of these blockchains are only intended to implement crypto currencies. Others will allow the creation of Dapps (Decentralized Application) while implementing a native crypto currency. With Bitcoin, the application of the blockchain for the creation of digital money seems validated (but of course it can be improved, especially with the problem of energy consumption). This is in itself a feat with enormous potential impact on the economy and societies. But other unanimous applications outside crypto currencies such as identity, tokenization, supply chain or document certification are already being adopted. It even seems that the discovery and validation of relevant blockchain use cases is one of the most important challenges facing this technology.

The blockchain is an exciting subject of study, it requires a non-trivial combination of economics, mathematics, cryptography and distributed systems. The idea of its application is highly ingenious, namely the observation that actors working together but not trusting each other can still trust the data they share thanks to guarantees of immutability and protection against fraudulent modifications of this data. These guarantees can have a huge impact in terms of time savings and process simplification for these actors.

Blockchain in the enterprise

After getting interested in Bitcoin and Ethereum, I became interested in enterprise blockchain. At first suspicious or even outright detractors of Bitcoin, the world of finance and enterprise in general eventually opened up to the adoption of the blockchain. And since then, there has been an important categorization of blockchains: that of so-called public or permissionless blockchains and so-called private or consortium or permissioned or enterprise blockchains. This categorization may have other variations or names such as open or closed blockchains.

Bitcoin and Ethereum are two examples of public blockchains (permissionless), their access is anonymous and authorized to any user. This unrestricted accessibility is a good thing, because it makes it easier to carry out transactions between individuals without them having to know each other beforehand. But in companies, users’ identities must be known and their access to the applications must be explicitly controlled. In addition, the two above-mentioned blockchains have a very low transactional throughput (inherent to most public blockchains) that is inappropriate to the needs of companies.

Enterprise blockchains are blockchains that meet the requirements of enterprises. Two Open Source platforms that are currently stand out for their maturity and notoriety in meeting enterprise blockchain constraints are Corda and Hyperledger Fabric. Corda was particularly focused on the world of finance when it was created and is managed by the R3 consortium, which includes most of the major financial groups in the world. It seems that over time its scope of application has expanded. Hyperledger Fabric is a project of the umbrella project Hyperledger managed by the Linux Foundation and also supported by a large consortium including major world-class players in several fields. Unlike Corda(at its beginnings), Hyperledger does not target a particular field of application. Another project worth mentioning is the Enterprise Ethereum Alliance. This project is supported by a large consortium interested in using Ethereum within the company. Its actions include setting standards in this direction.

Hyperledger Fabric

The development of Hyperledger Fabric was initiated by Digital Asset and IBM, the latter then entrusted it to the Linux Foundation where it now operates as part of the umbrella project Hyperledger. Hyperledger provides an ecosystem of solutions for the use of blockchain technologies. The main features of Hyperledger Fabric are:

  • Modularity and configurability: Fabric has a modular and configurable architecture, which facilitates its evolution and makes it adaptable and optimized for a wide variety of uses: banking, finance, insurance, health, human resources, supply chain and even multimedia streaming.
  • Writing smart contracts in general purpose programming languages: Fabric is the first distributed ledger platform that has enabled smart contracts to be written in common programming languages such as Java, Go and Node.js.
  • Permissioned: Fabric allows to control the access of participants who must have known identities in the system.
  • Pluggable consensus protocol: Fabric supports the activation of different consensus protocols, the choice is left to the users according to the context. In a context where all participants are part of the same company, a simple consensus protocol such as the Fault-Tolerant Crash can be adopted to avoid unjustified performance penalties. And in a context where the actors are more decentralized, it will then be appropriate to use the appropriate consensus protocol such as the Byzantine Fault Tolerant (BFT).
  • Consensus protocol without currency mining: The absence of an incentive factor for consensus building by crypto currency mining simplifies the functioning of consensus building, and therefore the functioning of the entire platform.
  • Performance and scalability: Fabric supports a high transaction rate and can scale significantly.

Composition of a Hyperledger Fabric network

Unlike Bitcoin or Ethereum, Hyperledger Fabric is not a blockchain, it is rather a platform allowing the deployment of a blockchain controlled by a certain number of participants(organizations), hence the categorization as enterprise blockchain platform. Figure 1 illustrates the components of a Hyperledger Fabric network formed between three organizations (R1, R2, R3):

  • Ledgers (L1, L2, L3) that record immutable transactions.
  • Endorsing peers(P1, P2, P3) that execute and “approve” transactions by running the smart contracts (S5, S6) they host.
  • Validator peers (P1, P2, P3) that validate and add transactions “approved” by endorser nodes in the ledger.
  • Orderers nodes (only one in the example, O4) that order the transactions “approved” by the endorsers nodes and send them to the validator nodes.
  • Certification authorities, one per organization in our example (CA1, CA2, CA3, CA4) that provide the cryptographic identities associated with network components and users.
  • The Fabric channels (C1, C2) and their configurations (cc1, cc2), which determine the sub-networks (R1, R2) and (R2, R3) that the organizations of the network can form to share transactions exclusively between them.
Figure 1 Components of a Fabric network ©https://hyperledger-fabric.readthedocs.io/en/release-1.3/network/network.html

Deploying a blockchain network consists in deploying these components with the right access and transaction validation policies.

Develop a Hyperledger Fabric application

The logic of a Fabric application is coded in the components called chaincodes, known as smart contracts in the general terminology of blockchains. Developing a Fabric application therefore consists in implementing in chaincodes the instructions for reading or updating the data shared between network members. Fabric currently supports writing chaincodes in Go, Java and Node.js.

Two types of clients allow you to interact with a Fabric network: the command line and the SDKs. The command line will typically be used for administration and testing purposes. SDKs have been developed for client applications that must interact with Fabric, for administration purposes if necessary, but above all to invoke smart contracts. Two SDKs are currently available: Node.js and Java. SDKs for Go and Python are under development.

Hyperledger Composer (put in standby)

Hyperledger Composer is a framework of the Hyperledger ecosystem that simplifies and accelerates the development of a Fabric application, although the initial goal of the project was to simplify and accelerate application development for all other blockchain platforms in the Hyperledger ecosystem. After starting to study Fabric and Composer, a month later I discovered an announcement from the lead developer of Composer announcing that the project was put on standby, because in short the project team did not like the direction taken by the project.

This was obviously not a joy, because even if a Fabric application can be developed just with the chaincodes API and an SDK, it must be said that Composer simplified and accelerated enormously the start-up of a Fabric application. It was therefore with real pleasure that I discovered at the same time the existence of Convector, which had the same objective of simplifying and accelerating the development of Fabric applications.

Development of a Hyperledger Fabric application with Convector

Convector Suite is a suite of Open Source tools that makes it easy and fast to develop applications for enterprise blockchains. The suite is composed of three products:

What is the added value of a framework like Convector Smart Contracts? Convector is the result of the efforts made by the start-up company WorldSibu to facilitate Hyperledger application development process, following the experience it acquired while developing with Fabric. By using Convector, we benefit from the fruit of their long experience in the use of Hyperledger Fabric.

In what follows, we will use Convector to develop an example of Hyperledger Fabric application.

The source code of the final version of the application is on GitHub: https://github.com/akoita/start-with-convector

Development environment

The tutorial has been developed on Ubuntu 16.0.4.1 64-bit desktop installed on VMWare Workstation 15 Player installed on Windows 10 Pro. But it should work in any environment supporting Hyperledger Fabric and Convector.

Prerequisites

  • Node.js : 8.14.1
  • Docker: 18.09.5
  • Docker-compose: 1.23.1

Convector Suite products versions

The versions of Convector Suite products that will be installed or used in the tutorial are(other newer versions can also work):

  • Convector-CLI : 1.1.3
  • Convector : 1.3.0
  • Hurley: 1.0.4

Creating the project

As we have explained, in the Convector Suite, Convector CLI is the tool for building a Convector project. It is therefore necessary to start by installing it:

npm i -g @worldsibu/convector-cli

Then create the Convector project:

conv new  start-with-convector -c participant

This command means: creates a new Convector project in the start-with-convector folder and initializes it with the chaincode participant. This command will therefore create a Node.sj project with the necessary configuration to develop, test and deploy smart contracts with Convector with Hurley.

After we rename the directory to our convenience and install the dependencies as follows:

mv startWithConvector start-with-convectorcd start-with-convectornpm i

The generated project uses lerna, a Node.js tool to facilitate the build of several modules in different packages of the same project. The convention of Convector is to create the different modules of the project in the packages folder. The chaincode participant will therefore be created in this package in the participant-cc (cc stands for chaincode) folder. The generated project has the structure shown in Figure 2.

Figure 2 Structure of the project generated by Convector CLI

Smart contracts: Model-Controller pattern

We had talked about the functioning of a Fabric application that could be summarized as reading and updating assets shared between participants by invoking smart contracts or chaincodes.

Fabric actually provides an API called fabric-shim that defines the interface of the chaincodes. This API is available in several languages, currently Java, Node.js, Go and perhaps soon in Python. A chaincode must implement the interface defined in fabric-shim in order to be executed by Fabric. A chaincode will have access to the fabric-shim API to read and write assets in Fabric when invoked. This basic operation is quite enough to create a Fabric application, but in a real project, we quickly realize the need to create an abstraction layer over the shim API to facilitate the development of large-scale smart contracts. This is why a high-level interface called fabric-contract-api has been defined above fabric-shim. fabric-contract-api is only available in Node.js at this time, but it should be available soon in Java and other languages.

To a much greater degree, Hyperledger Composer was supposed to be the reference tool for developing blockchain applications above the low-level layers of the platforms of the Hyperledger ecosystem. As we said, Composer has been put on standby because it is not going in the right direction.

Convector assumes that the basic API for developing and invoking smart contracts is not easily suited to the development of a large application.

WorldSibu, the startup that created Convector, explains in this article that they had to develop different tools internally to improve their Fabric application development processes. It was the results of this work that led to the Convector Suite that they decided to make Open Source for the Fabric community.

Convector Smart-Contracts, the framework of the Convector Suite for writing smart contracts, offers the Model-Controller pattern to simplify the development of smart contracts. So, let’s look at the content of the packages/participant-cc/src directory of the project without further delay. This directory contains the model and the controller that correspond respectively to the asset and the smart contract in a Convector application. Let’s start by examining the model in the Figure 3.

Convector model

Figure 3 Participant Model

A Convector model is a class that inherits the abstract class ConvectorModel. Two attributes are special in a Convector model. First the id attribute, already declared in the abstract class ConvectorModel. Convector requires that a valid model define the value of this attribute. Then the type attribute, declared as abstract in the ConvectorModel class. This attribute must be “implemented” in the model class. The value of this attribute is used to discriminate asset schemas present in the ledger when they are in JSON format. Reason why the type attribute must be declared as a TypeScript constant (readonly).

All other attributes of the Participant model are normal attributes. Note the different attribute decorators provided by Convector. These decorators are used to trigger validation checks on the attributes concerned during construction, transmission or saving.

  • ReadOnly: indicates that if the value of the attribute has already been defined, it should no longer be possible to modify it.
  • Required: indicates that the value of the attribute must be defined
  • Validate: allows you to specify a validation scheme of the type of the attribute using the Yup library.

Let’s make the Participant model more interesting by modifying it as shown in Figure 4. The Participant model now includes the name of the organization’s MSP (Membership Service Provider) and the fingerprint of the X.509 certificate associated to the participant.

The ConvectorModel class provides methods for saving and reading models. But these actions must be triggered in the controller. Let’s now look at the controller code generated by Convector-CLI in Figure 5.

Figure 4 Include identity information in the template

Convector Controller

Figure 5 Convector controller generated by Convecot-CLI

A Convector controller is a class annotated with the @Controller decorator and which extends the abstract class ConvectorController. It implements the transactional logic of the Fabric application.

If we want to simplify things, we will say that the controller corresponds to the smart contract, but this is not quite the case. Instead, we will follow the terminology of fabric-contract-api and consider that a Convector controller is at the same level of abstraction as a contract. So, if we consider that the terms chaincodes and smart contract are synonyms in Fabric terminology, we can consider that a smart contract is composed of one or more contracts. Therefore, a Convector controller can be considered as a contract of a smart contract that may include several others.

The controller’s interaction points in the blockchain are the methods with @Invokable decorator. The parameters of methods with @Invokable decorator can be decorated with @Param decorator to specify the validation scheme of the parameter type.

Following the modification of the model, we will also modify the controller as shown in Figure 6.

Figure 6 Modification of the controller to manage the identities of participants

This change allows you to use the ParticipantController to register participants with their digital certificate information. Let’s take a closer look at the important actions performed in the ParticipantController class.

Request a model in the legder from its identifier

In the getParticipantById method, declared at line 14, we try to request a participant’s model from its identifier:

const participant = await Participant.getOne(id);

This instruction will effectively return the model that exists in the ledger and has the ID passed as an argument. But be careful, this method will still return a non-null value even if the identifier does not match any data existing in the ledger. Therefore, the result of this instruction must be systematically checked as follows:

// a non-null or defined result doesn't mean that it is valid, the following check must still be done
if (!participant || !participant.id) {

Retrieve information on the caller’s cryptographic identity

The register operation registers the user who calls it by creating a Participant model containing information related to the user’s cryptographic identity: the organization’s MSP and the fingerprint of its certificate. The caller’s MSP is retrieved from line 36:

participant.msp = this.tx.identity.getMSPID();

The fingerprint of the certificate is retrieved from line 37:

participant.x509Fingerprint = this.sender;

The changeIdentity operation updates the fingerprint of the certificate associated with a Participant model. But this operation requires that the caller’s certificate has the admin attribute and that it is issued in the same organization as the user whose account he is trying to update. The instructions for these checks are:

Saving a Convector model

Still in the register operation, we ask to save the new model in the ledger as follows:

await participant.save();

An important remark, even if this instruction may look like an ordinary persistence invocation instruction, it should be remembered that its effect is very different, precisely because we are in a blockchain and all modifications in a blockchain follow the established consensus workflow. The workflow of a transaction in Fabric is described in detail in various places in the official documentation, such as here, for example.

This save instruction is valid for creating a new model or updating an existing model after modifying it.

Unit test, adapters and controller client

Given the complexity of a real Fabric environment, even a simple one, having the ability to automate the execution of unit tests is a very important feature. This is good because Convector encourages and facilitates the creation of unit tests on controllers. Convector generates a basic unit test for each controller generated, that of the ParticipantController is illustrated in Figure 7.

Figure 7 Basic unit test generated by Convector-CLI

Since we have modified the model and the controller generated by Convector-CLI, this test should be in error and should not compile. We will therefore adapt it to test the changes we have made, as shown in Figure 8.

Let us examine the essential information present in the unit test code.

Convector Adapters

The code teaches us something very interesting in Convector’s architecture, it is the presence of adapters. Line 16 shows the declaration of a MockControllerAdapter adapter. This adapter allows to interact with the controllers running in the context of fabric-shim mock environment. Convector currently has other adapters to use depending on the context:

  • BrowserControllerAdapter: allows you to simulate the execution of a Fabric application in a browser. Very useful for making demos or fast prototypes.
  • FabricControllerAdapter: the adapter that allows Convector to interact with controllers running in a real Fabric blockchain.
  • InChaincodeAdapter: the most recent, allows to perform inter-chaincode invocations.

Other very important information, in lines 17 and 57 of the listing, the declaration and definition of the ConvectorControllerClient controller client. Just with these two lines, Convector allows us to interact with the blockchain by invoking the methods of our controller exposed by the ConvectorControllerClient client.

Line 59 shows how the MockControllerAdapter is initialized: by indicating the name of the controller class and the path of the chaincode directory (packages/participant-cc).

Test fixture: false certificates

As test fixture, we have the two constants fakeParticipantCert and fakeAdminCert which correspond respectively to an X.509 certificate without privilege and an X.509 certificate with the admin attribute. Line 66 configures the adapter with the fakeParticipantCert certificate as the caller’s certificate.

Now let’s start looking at the unit tests code.

“should create a participant”

The purpose of this unit test is to verify that a participant can be created correctly:

  1. On line 71, we record a new participant,
  2. On line 72, we retrieve the participant from his id
  3. On line 77, we check that the recovered participant contains the expected information.

“should fail to create a participant with an existing id”

The purpose of this unit test is to verify that an error is launched when trying to create a participant with an identifier belonging to a participant existing in the ledger:

  1. Line 88: we register the participant
  2. Line 89: we retrieve the participant from the ledger
  3. Line 94: we check that the recovered participant contains the expected information.
  4. Line 102: we try to create a new participant and check that the operation fails with the expected error message.

“should fail to change the active identity of a participant because the caller is not admin”

This unit test ensures that it is not possible to change the identity of a participant if the caller’s identity does not have the admin attribute:

  1. Line 114: Participant record
  2. Line 128: While the caller’s cryptographic identity does not have an admin attribute, an attempt is made to modify a participant’s fingerprint and verify that the operation fails with the expected error message.

"should change the active identity of a participant"

This unit test verifies that a caller whose identity has the admin attribute can modify the identity associated with a participant:

  1. Line 140: Participant record
  2. Line 155: Change the caller’s identity with a certificate with the admin attribute
  3. Line 156: Change the participant’s fingerprint
  4. Line 165: Verify that the participant’s fingerprint has been updated.

Multi-controllers, rich queries and CouchDB indexes

You will have noticed that our application is composed of a single controller, which is rarely the case for real applications. We will therefore see how to manage several controllers in Convector and take the opportunity to see an example of a rich query to request the ledger when it is configured with CouchDB as the implementation of the World State.

Creating a new controller

Let’s use Convector-CLI to add a new controller, for example AssetController, to allow the creation and reading of assets:

conv generate chaincode asset

This command will generate a new chaincode package packages/asset-cc containing the controller, a model and a unit test, as after the initialization of a project. Note that we could have created our controller in the packages/participant-cc directory, in other words, we have quite the choice to create as many controllers and models as we want in the same chaincode package,even if these choices do not have exactly the same consequences in terms of project configuration. And we will immediately face the first consequence.

Since this new package will depend on the resources of the participant-cc package, we must declare this dependency in its package.json file. This can be done with the lerna tool as follows:

npx lerna add participant-cc --scope asset-cc

We will modify the files generated by default again, an asset will have a name, a value, a state and an owner, as shown in figure 9. Note in line 14 the definition of the Yup schema for validating the AssetState enumeration. We have also added methods to facilitate the construction of an asset by following the builder builder pattern.

Figure 9 Asset Model

Let’s look at the AssetController class in Figure 10.

Figure 10 AssetController Controller

The AssetController has five operations, let’s look at them.

Operation createAsset

This operation allows you to create an asset. It performs the following actions:

  1. Lines 36, 37: check that there is no existing asset with the same id.
  2. Lines 42.43: Verify that the participant designated as owner of the new asset exists.
  3. Line 47: Create the asset with the arguments provided. The asset is created in the AssetState.Open report.

Operation closeAsset

This operation puts an asset in the AssetState.Closed state. To do this, it performs the following actions:

  1. Line 58: Retrieve the asset with the id provided.
  2. Line 63: If the asset is already in the Closed state, raise an exception.
  3. Line 67.68: Verify that the identity of the caller is the same as the identity of the owner of the asset.
  4. Line 87: Update the status of the asset at Closed and save the change in the blockchain.

Operation getAssetById

This operation requests and returns an asset from its identifier.

GetAllOpenAsset and getAllClosedAsset operations: rich query

These two operations use a rich query, as mentioned in the introduction to the section, to select and return assets that are in the Open or Closed state. Both operations call the same getAllAssetInState method with just different arguments. The getAllAssetInState method builds the following rich query:

108     const query = {
109 selector: {
110 $and: [{ type: Asset.TYPE }, { state: state }]
111 },
112 use_index: ["_design/indexAssetNameDoc", "indexAssetName"],
113 sort: [{ name: "asc" }]
114 };

As a reminder, this request only works if CouchDB is used as the ledger’s World State implementation solution. Currently, in addition to CouchDB, Fabric also supports LevelDB as a World State management solution, but LevelDB is just a key/value storage solution that does not support rich queries.

Returning to the query, it is structured in JSON and has three fields in our example:

  • the selector whose value is the selection criteria
  • the specification of the index to be used for the query
  • the sorting specification: whose value is the field on which all the results must be sorted and the direction of sorting.

The request allows to select in the ledger all objects whose “type” field has the value Asset.TYPE and whose “state” field has the value of the AssetState enumeration passed as a parameter. The query then states that the results will have to be sorted upward according to the name of the selected assets.

The use of indexes is not always mandatory, although it is strongly recommended for performance optimization. But because our request includes a sorting specification, CouchDB requires the availability of a suitable index. We can specify the index to use in the query, as in our example, otherwise we can just create it and let CouchDB determine and use the appropriate index from the available indexes.

Convector documentation provides a solution for integrating indexes into a Convector project so that they are packaged and deployed correctly in the blockchain. The solution is to put all the indexes in the indexes directory at the root of the project, modify the “script” section of the package.json file at the root of the project as follows:

  • Add a new command that will copy the indexes into the directory expected by Fabric, which is “META-INF/statedb/couchdb/indexes”:
"copy:indexes": "f () { mkdir -p ./chaincode-$1/META-INF/statedb/couchdb/indexes; cp -a ./indexes/ ./chaincode-$1/META-INF/statedb/couchdb/indexes; }; f"
  • Call this new command at the end of the “cc:package” command to trigger the copy of the indexes into the appropriate directory of the deployment package:
; npm run copy:indexes -- $1;

The index in question has been defined in the file indexes/indexAssetName.json, note that the name of the file is not important, just the content, which is:

In the index definition, the ddoc, name and type fields are metadata for CouchDB. It is in the index.fields list that we specify the index field(s) of our JSON object. This index definition is intended to cause an index to be created on the name field of JSON objects in CouchDB.

Deployment and invocation in Fabric with Hurley

We understood how to implement a smart contract with Convector and test it individually. We will now see how to deploy and invoke a Convector application in a Fabric blockchain with Hurley, another product of the Convector Suite. It is not yet a deployment in a production environment, but the Fabric environment is very real.

Let’s start by installing Hurley with npm:

npm i -g @worldsibu/hurley

By being in the root directory of the project, deploy a Fabric development network with Hurley:

npm run env:restart

This command will launch a set of docker containers corresponding to the Fabric network nodes, as shown in the screenshot in Figure 11. The default network configuration used by Hurley is composed of two organizations, org1 and org2, with one peer node, one CA node and one CouchDB node per organization, and one orderer node. The various configuration files and network artifacts are created by default in $HOME/hyperledger-fabric-network. Hurley supports options that allow you to specify different configuration settings than the default ones.

Figure 11 Docker containers in the Fabric network

Before we can deploy our Convector application with Hurley, it is necessary to provide different information:

  • the cryptographic identity to be used to install the chaincode in the blockchain,
  • the name of the channel that will be created,
  • the topology of the Fabric network where the application will be deployed (networkprofile)

Convector-CLi generates two configuration files during each chaincode initialization. These configuration files are at the root of the project and are called org*. <chaincode>.config.json. So, in our project, we have the file org1.asset.config.json whose content is illustrated in figure 12.

Figure 12 Deployment information for Hurley

In addition to the information we have mentioned, we see that the configuration file also contains controllers and policy sections. In the controllers list, we must list all the controllers of the project that must be part of the chaincode to be deployed. The policy section defines the endorsement policies of the chaincode, which consist in specifying the approvals required for a transaction to be validated and added to the ledger.

The AssetController controller is already mentioned in the config.json file, we will keep it. If you remember correctly, we added the participant-cc module as a dependency to the asset-cc module by modifying its package.json file. For the creation of the deployment package, we must still mention this dependency in the config.json file, otherwise the dependency will not be included in the deployment package. In general, it is necessary to mention in the config.json file the list of all controllers that must be deployed together, whether or not there is a direct dependency between them, as explained in Convector documentation.

Thus, by adding the ParticipantController controller to the config.json file, it becomes:

Figure 13 Adding the ParticipantController controller to the org1.asset.config.json file

Note that we might as well have chosen to deploy from the org1.participant.config.json configuration file by updating it or from any other file as long as it contains the appropriate information. Nevertheless, the configuration files generated by Convector-CLI have a naming pattern that is exploited in different scripts in the package.json file, as we will see.

We can now deploy the chaincode in this Fabric network as follows:

npm run cc:start -- asset

Important: If during the following manipulations you encounter unexpected errors, do not hesitate to reset the environment by starting from scratch as follows:

hurl clean; hurl new

The cc:start command which is defined in the package.json file will actually invoke two other commands also defined in package.json : the cc:package command to build the chaincode deployment package, and the cc:install command to deploy the package in the blockchain created previously by Hurley.

When the chaincode is deployed, it can be used to create a few participants:

hurl invoke asset participant_register ptcp1 Damienhurl invoke asset participant_register ptcp2 Booba

Note that the first invocation will take time because it will cause the instantiation of the chaincode. The following invocations will be much faster.

The invocation syntax of an operation of a Convector-JS based chaincode with Hurley is(see Hurley doc):

hurl invoke <chaincode> <contract>_operation [args]

Let’s verify that the two participants were created by requesting them from their id:

vmware@ubuntu:~/dev/start-with-convector$hurl invoke asset participant_getParticipantById ptcp1[hurley] - ptcp1[hurley] - Sending transaction as user1 in org org1...[hurley] - Transaction sent! VALID  SUCCESS e59513ffe16890f5393d39737c20d5f66cc97e22614006a3efa0a06cb7a4d21e[hurley] - Result: {"_id":"ptcp1","_msp":"org1MSP","_name":"Damien","_type":"io.worldsibu.participant","_x509Fingerprint":"35:DF:BD:D5:32:60:97:26:34:06:6D:56:3C:2A:02:04:18:56:18:74"}vmware@ubuntu:~/dev/start-with-convector$hurl invoke asset participant_getParticipantById ptcp2[hurley] - ptcp2[hurley] - Sending transaction as user1 in org org1...[hurley] - Transaction sent! VALID  SUCCESS 8b698468adcc6e3e80362ad4b9ba16d60241659d5786b758ac6897d0d0b9bce9[hurley] - Result: {"_id":"ptcp2","_msp":"org1MSP","_name":"Booba","_type":"io.worldsibu.participant","_x509Fingerprint":"35:DF:BD:D5:32:60:97:26:34:06:6D:56:3C:2A:02:04:18:56:18:74"}

Let’s now create some assets:

ASSET1_PARAMS='{"id":"as1","ownerId":"ptcp1","value":"Asset1Value","name":"Asset1Name"}'ASSET2_PARAMS='{"id":"as2","ownerId":"ptcp1","value":"Asset2Value","name":"Asset2Name"}'ASSET3_PARAMS='{"id":"as3","ownerId":"ptcp2","value":"Asset3Value","name":"Asset3Name"}'ASSET4_PARAMS='{"id":"as4","ownerId":"ptcp2","value":"Asset4Value","name":"Asset4Name"}'hurl invoke asset asset_createAsset $ASSET1_PARAMShurl invoke asset asset_createAsset $ASSET2_PARAMShurl invoke asset asset_createAsset $ASSET3_PARAMShurl invoke asset asset_createAsset $ASSET4_PARAMS

Let’s request the list of all assets in the Open state:

vmware@ubuntu:~/dev/start-with-convector$hurl invoke asset asset_getAllOpenAsset[hurley] - Sending transaction as user1 in org org1...[hurley] - Transaction sent! VALID  SUCCESS eb087c4f24410664dad7a30422555c7b853d63570afb519575908f65b1215bc4[hurley] - Result: [{"_id":"as1","_name":"Asset1Name","_ownerId":"ptcp1","_state":"Open","_type":"io.worldsibu.asset","_value":"Asset1Value"},{"_id":"as2","_name":"Asset2Name","_ownerId":"ptcp1","_state":"Open","_type":"io.worldsibu.asset","_value":"Asset2Value"},{"_id":"as3","_name":"Asset3Name","_ownerId":"ptcp2","_state":"Open","_type":"io.worldsibu.asset","_value":"Asset3Value"},{"_id":"as4","_name":"Asset4Name","_ownerId":"ptcp2","_state":"Open","_type":"io.worldsibu.asset","_value":"Asset4Value"}]

Let’s request the list of Closed assets:

vmware@ubuntu:~/dev/start-with-convector$hurl invoke asset asset_getAllClosedAsset[hurley] - Sending transaction as user1 in org org1...[hurley] - Transaction sent! VALID  SUCCESS 715b6fb98a5f450d4b8f74a38099f9d65f31a6c030187de29fab19258456e695[hurley] - Result: []

Let’s close two assets and request again the list of Closed assets:

hurl invoke asset asset_closeAsset as1vmware@ubuntu:~/dev/start-with-convector$hurl invoke asset asset_closeAsset as2vmware@ubuntu:~/dev/start-with-convector$hurl invoke asset asset_getAllClosedAsset[hurley] - Sending transaction as user1 in org org1...[hurley] - Transaction sent! VALID  SUCCESS 89c5b273fb362e7a015922fbaecf0f497e95e1ba4e9fe48e0cdf66a8a3f5b903[hurley] - Result: [{"_id":"as1","_name":"Asset1Name","_ownerId":"ptcp1","_state":"Closed","_type":"io.worldsibu.asset","_value":"Asset1Value"},{"_id":"as2","_name":"Asset2Name","_ownerId":"ptcp1","_state":"Closed","_type":"io.worldsibu.asset","_value":"Asset2Value"}]

The tutorial ends here. It goes without saying that we have not been exhaustive on all the possibilities or limitations of Convector which continues to evolve, just as Hyperledger Fabric that is preparing a major release, version 2.0. I advise you to go to the addresses mentioned in the references to learn more about Hyperledger Fabric and Convector.

In the course of our learning, the next major evolution of our application will be to add a REST layer to expose blockchain access to other applications and deploy it in a typical production environment.

In a next article, I will do another tutorial with a slightly more advanced application example focusing on the analysis and design phase of the application, and this time addressing the addition of the REST layer and perhaps the deployment process in a typical production environment.

References

Source code of the tutorial Fabric project: https://github.com/akoita/start-with-convector

Hyperledger Fabric documentation: https://hyperledger-fabric.readthedocs.io/en/latest/index.html

Hyperledger Fabric Wiki: https://wiki.hyperledger.org/display/fabric

“Convector: Writing an Open Source Development” by Diego Barahona: https://www.hyperledger.org/blog/2019/03/14/convector-writing-an-open-source-development-framework

Convector Suite web site: https://worldsibu.tech/

Convector documentation: https://docs.worldsibu.com/collection/6-convector

Examples of Convector applications: https://github.com/worldsibu/convector

Hyperledger Fabric, “Basic workflow of transaction endorsement”: https://hyperledger-fabric.readthedocs.io/en/release-1.4/arch-deep-dive.html#basic-workflow-of-transaction-endorsement

“Testing and debugging a Convector Smart Contract” by Walter Montes : https://medium.com/worldsibu/testing-and-debugging-a-convector-smart-contract-aa02c84e7ecc

Freeze of Hyperledger Composer by Simon Stone: https://lists.hyperledger.org/g/composer/message/125

“Demystifying Hyperledger Fabric ordering and decentralization” by Arnaud Le Hors: https://developer.ibm.com/articles/blockchain-hyperledger-fabric-ordering-decentralization

“Does Hyperledger Fabric perform at scale? “ by Christopher Ferris: https://www.ibm.com/blogs/blockchain/2019/04/does-hyperledger-fabric-perform-at-scale

“Smart Contracts” by Nick Szabo: http://www.fon.hum.uva.nl/rob/Courses/InformationInSpeech/CDROM/Literature/LOTwinterschool2006/szabo.best.vwh.net/smart.contracts.html

“Bitcoin: A Peer-to-Peer Electronic Cash System” by Satoshi Nakamoto: https://bitcoin.org/bitcoin.pdf

“How the Tech Behind Bitcoin Will Change Your Life” by Don Tapscott and Alex Tapscott: http://time.com/4320254/blockchain-tech-behind-bitcoin/

“The Truth About Blockchain” by Marco Iansiti and Karim R. Lakhani: https://hbr.org/2017/01/the-truth-about-blockchain

“ Here’s Why Blockchains Will Change the World” by Don Tapscott and Alex Tapscott: http://fortune.com/2016/05/08/why-blockchains-will-change-the-world/

“On Public and Private Blockchains” by Vitalik Buterin: https://blog.ethereum.org/2015/08/07/on-public-and-private-blockchains/

“Blockchain, often seen as tech’s next big thing, struggles to get traction” by Kyt Dotson and Paul Gillin: https://siliconangle.com/2018/12/09/blockchain-often-seen-techs-next-big-thing-struggles-get-traction

“What is Tokenomics”: https://blockgeeks.com/guides/what-is-tokenomics/

Yup, “A JavaScript object schema validator and object parser”: https://github.com/jquense/yup

Builder pattern: https://en.wikipedia.org/wiki/Builder_pattern

Convector, “Tutorial — Advanced — CouchDB”: https://docs.worldsibu.com/article/101-tutorial-advanced-couchdb

Lerna, “A tool for managing JavaScript projects with multiple packages: https://github.com/lerna/lerna

--

--