27 September, 2018

Implementing a Blockchain-Supply Chain Proof-of-Concept with Hyperledger Composer

It is now time to focus on the more practical aspects of the design and implementation of a proof-of-concept (PoC) using Hyperledger Composer.

Pedro Costa

Software Engineer

Implementing a Blockchain-Supply Chain Proof-of-Concept with Hyperledger Composer

This is the second article of a 2-part series, detailing the problems in the supply chain, how blockchain can be applied to fix them, and providing a proof-of-concept implementation example.

Part 1 — The need for a Blockchain ready Supply Chain Management System

Part 2 — Implementation of a proof-of-concept using Hyperledger Composer

This article was written as part of a Master Thesis titled “Supply Chain Management with Blockchain Technologies” which can be accessed here (direct download).

The previous article explained why supply chains may benefit from blockchain and introduced the Composer framework. It is now time to focus on the more practical aspects of the design and implementation of a proof-of-concept (PoC) using Hyperledger Composer.

A. Architecture of a Composer Project

We left the Fabric implementation details out of the way and focused on Composer, which has everything you need to get started.

Our implementation, as simple as it gets, is divided into 4 main parts:

Architecture of a Composer Project Architecture of a Composer Project

  • Model — The file that defines all the system objects and transactions. All the network participants, assets and transactions are included.

  • Scripts — The behavior for the defined transactions, whenever they are called.

  • Queries — A file with defined queries for retrieving information out of the system.

  • Access Control — A set of rules that will help define who can access the information, and what type of access they have.

    In order to build a fully working system with multiple machines, peers and organizations, there are some additional Fabric configuration files that have to be altered. This tutorial, from the official Composer documentation, explains this matter more thoroughly.

This PoC was built using Composer 0.19.5 (10th May, 2018).

B. Design and Implementation of the PoC

What follows is the proposed design for our system. The aim of such a design is to implement some interesting features and satisfy some of the supply chain requirements, as was mentioned in the previous article:

More information. Easier synchronization. A scalable structure.

But we are not only sticking to these general guidelines. This system focuses on information tracking and synchronization, but also on security and finance (to a lesser extent).

B.1 Model


The first step towards designing the system was to define who the users are, in order to model the participants. The logical separation for the participant type:

  • Auditor — the participant that represents a real-life auditor that can verify and check all the movements on the supply chain

  • Supply chain member — the main participant of the network, the supply chain members are the actual users that will be interacting with each other; Sub-types were also designed, having in mind that they may exhibit different behaviours, and different access rules can be written based on the sub-type: Supplier, Manufacturer, Distributor, Retailer and Customer

    The reason the admin does not appear here is that the admin of a business network does not need a defined user type to be able to invoke transactions. Instead, they only need their composer identity card, which in no way needs to be tied to a modeled participant.


Another integral component of the system are the assets. If traceability of products is to be achieved, these products need to be modeled as assets, so that the network can register which ones exist, their status, and any changes that happen.

The proposed assets in this model were:

  • Commodity — represents the goods being exchanged, which are included in a shipment and have a status

  • Shipment Batch — the shipment batch contains a variety of commodities, has a point of origin and destination (which might connect to another shipment). It is also associated to a contract, which dictates who the buyer of the shipped goods is.

  • Contract — the contract represents the sale and associated goods, listing the buyer, seller, payment amount and expected arrival location and time. These items, like the payment, will be respected through smart contracts, and fraud detection techniques can also be used: for instance, if the item arrives in a location different from the final location, something might be up.


A lot of transactions were defined, so if you want to check them all out, it is better if you read the corresponding section of the thesis (6.3.1) or check out the project at Github.

The first part of the defined transactions were the CRUD transactions. Some are already defined by default by Composer, but they can always be overwritten. In this project, we felt the need to define some custom CRUD transactions, such as deleting or updating a commodity, as well as updating a shipment.

/** * Transfer holdership of assets to another person and update the status of the shipment */ transaction UpdateShipment extends ShipmentTransaction{ o ShipmentStatus status o Location newLocation o String message → supplyChainMember newHolder optional }

The reason for defining these was to later make the definition of the access control rules a lot easier.

The above transaction is an example taken from the PoC, which defines that, when updating a shipment, a status, a new location, a message and, optionally, a new holder for the shipment must be defined.

Other custom transactions included, for instance, the creation of shipments and contracts, reporting damaged goods, transforming commodities and temperature readings. These are all important features that could be used in a real system.

B.2 Script

A quick recap: both participants and assets are modeled as objects (just like in OO programming) and have their own registries, where they are stored.

Transactions are different, in that, even thought they are also modeled as objects, their registry is immutable. The modeled transactions are actually a way of representing the invocation of the transactional scripts with certain parameters. These scripts will play around with the participant and asset registries, to alter the data in a meaningful way (for instance, we could invoke a transaction that would alter the status of a commodity).

Composer Playground — Transaction Registry Composer Playground — Transaction Registry

Therefore, every single transaction model object has a transactional script associated. There are 2 parts involved in invoking a script:

1. Specifying the transaction and parameters — The transaction parameters must match the data fields of the transaction model. If we want to call the UpdateShipment transaction, we must provide a status, new location, message and, optionally, a reference to the participant that is the new holder for this transaction.

2. Calling the transaction — Upon specifying the parameters and pressing submit, the script that is connected to the transaction model will execute. The UpdateShipment script takes as arguments the data fields previously inserted and runs the coded logic: checking whether the new holder field was filled, checking if that holder is registered in the blockchain, checking if the shipment is registered in the blockchain and finally, updating the shipment object with the relevant data inserted.

Composer Playground — Submitting a transaction Composer Playground — Submitting a transaction

There were a lot of transaction objects modeled, and each one has a script, there are also a lot of scripts. As such, an extensive description of what each script does would be overly complicated. If you want to check them all out, it is better if you check out the project at Github.

B.3 Queries

Composer has predefined access points to query the basic information about participants, assets and transactions. Anything else requires custom queries defined in a file.

Query Elements

As it uses non-relational databases, Composer has a custom query language, similar to SQL, but with some limitations. The queries are pretty straight forward to code. They are a basic SELECT type of query, with the specification of what object we want to select, followed by a WHERE kind of statement, where certain conditions like equality, inequality, CONTAINS among a few others can be used.

Query List

Some queries were defined, but for a real system, a lot more custom queries would have to be written. The following were the most useful and straight forward queries that the system needed.

Supply chain - most useful and straight forward queries Supply chain - most useful and straight forward queries


Since the DB is non-relational, retrieving associated data is not directly possible. Imagine the following situation: you have a commodity which references a participant (the owner of the commodity). Normally, in a relational DB, with the Commodity table having a reference to the Participant table, it would be possible to join both tables and retrieve a participant associated with a commodity in 1 step.

However… this is not possible in 1 step/query on this system. Instead, the commodity would have to be retrieved first, and then, by accessing the ID that references the participant, a new query to get the participant would have to be executed.

Query number 12, getCommodityOwner, represents exactly this case. Even though the query is named getCommodityOwner, it actually retrieves the Commodity, which has a reference to the Owner.

Relational vs Non-Relational query Relational vs Non-Relational query

A second major problem is demonstrated in the above image. A non-relational DB leads the references to be unidirectional, instead of bi-directional like in a relational DB.

Originally, the shipment had a commodity and an owner. The shipment’s owner, logically, should also be the owner of the commodity. However, having a unidirectional connection, it was impossible to link the Commodity to the Owner. In order to do this, it was necessary to purposefully alter the model and add the owner reference in the commodity object (represented by the green arrow).

Certain queries will be impossible to write, unless you adapt your model specifically for it!

B.4 Access Control

The access control rules include a set of rules defined for CRUD actions:

  • Allowing supply chain members to access only information pertinent to the shipments and commodities they own or have business with.

  • Allowing admins to do anything

  • Allowing auditors to read anything.

    The objective is to maintain system integrity and maintain a security standard, for what content can be accessed by each participant of the system. For this PoC, and because of lacking time, the access control rules were not tested and defined thoroughly.


Defining a small PoC with the basic functionalities is not hard at all with Composer, although we could find a few topics that could be improved in the future:

  • Design - There is still a long way to go in terms of design. Our PoC was far from a complete product, although it seemed to do fine in terms of what we wanted to achieve (product traceability, security, synchronization). The way the registries work, with the transactions registry being immutable, was easy to understand and work with. Overall, Composer was also easy to use and understand, by just reading their documentation.

  • Limitations of Composer: the query language - This is one of our main concerns with Composer. The choice of DB system and the query language used lead to the impossibility of certain queries unless the model is reformulated to take these into account. These reformulations are something might not be desired or otherwise might lead to inconsistencies.

  • Limitations of Composer: the REST server and Composer API - The default composer rest server is a bit limited and could have some more configuration options. It automatically creates a REST API with the queries created, as well as all the transactions defined, but anything more complex requires a custom REST server to be written.

    Note: As of Composer 0.19.9, generating and building a custom REST server is now easier!

    Overall, the Composer tool still needs to evolve a bit more before it is used in more serious projects. The fact that it still requires a lot of configuration for the Fabric peers is also off-putting and hard to understand.

Software Development



Supply Chain

Blockchain Technology


Join our newsletter

Be part of our community and stay up to date with the latest blog posts.


Join our newsletter

Be part of our community and stay up to date with the latest blog posts.


You might also like...

Go back to blogNext
How to support a list of uploads as input with Absinthe GraphQL


26 July, 2022

How to support a list of uploads as input with Absinthe GraphQL

As you might guess, in our day-to-day, we write GraphQL queries and mutations for Phoenix applications using Absinthe to be able to create, read, update and delete records.

Nuno Marinho

Software Engineer

Flutter Navigator 2.0 Made Easy with Auto Router - Coletiv Blog


04 January, 2022

Flutter Navigator 2.0 Made Easy with Auto Router

If you are a Flutter developer you might have heard about or even tried the “new” way of navigating with Navigator 2.0, which might be one of the most controversial APIs I have seen.

António Valente

Software Engineer

Enabling PostgreSQL cron jobs on AWS RDS - Coletiv Blog


04 November, 2021

Enabling PostgreSQL cron jobs on AWS RDS

A database cron job is a process for scheduling a procedure or command on your database to automate repetitive tasks. By default, cron jobs are disabled on PostgreSQL instances. Here is how you can enable them on Amazon Web Services (AWS) RDS console.

Nuno Marinho

Software Engineer

Go back to blogNext