Hyperledger Composer
Introduction to Hyperledger Composer
Updated: 03 September 2023
Overview
A business Network, defined in a Business Network Archive .bna
File
- Models
- Logic
- Queries
- Access Control
In order to update a network, we simply upload the Archive .bna
file to the network, this can either be done from the command line or from the Blockchain UI if using IBM Cloud
Models
Models are files that define Assets, Participants and Transactions using the Hyperledger Composer Modelling Language
Models are defined in .cto
files, and are written using the Hyperledger Composer Modelling Language
CTO Language
A .cto
file is composed of the following elements
- A single namespace, all resource definitions are part of this namespace
- A set of resource definitions
- Assets
- Transactions
- Participants
- Events
- Optional import declarations than import resources from other namespaces
Namespaces
Resources are organized by namespaces, this is defined by first line in a .cto
file which can be as follows
1namespace org.example.mynetwork
All other resources defined in the same file will be part of this namespace
Classes
A resource definition has the following properties
- A namespace (defined by the namespace of its parent file)
1namespace org.example.mynetwork
- A name and identifying field
1/**2 * A vehicle asset.3 */4asset Vehicle identified by vin {5 o String vin6}
- Optional supertype
- Any additional properties
1/**2 * A car asset. A car is related to a list of parts3 */4asset Car extends Vehicle {5 o String model6 --> Part[] Parts7}
- An optional Abstract declaration to state that the type cannot be created but can only be extended
1/**2 * An abstract Vehicle asset.3 */4abstract asset Vehicle identified by vin {5 o String vin6}
- A set of relationships to other Composer types
1/**2 * A Field asset. A Field is related to a list of animals3 */4asset Field identified by fieldId {5 o String fieldId6 o String name7 --> Animal[] animals8}
Enums
Enumerables can be defined as follows
1/**2 * An enumerated type3 */4enum ProductType {5 o DAIRY6 o BEEF7 o VEGETABLES8}
And can be used in another class as a type
1participant Farmer identified by farmerId {2 o String farmerId3 o ProductType primaryProduct4}
Concepts
Concepts are abstract classes that are not assets, participants or transactions. They are contained by another resource and do not have an identifier and cannot be directly stored in registries or referenced in relationships
For example we can define a concept as follows
1abstract concept Address {2 o String street3 o String city default ="Winchester"4 o String country default = "UK"5 o Integer[] counts optional6}7
8concept UnitedStatesAddress extends Address {9 o String zipcode10}
And then use it in a class definition
1participant Farmer identified by farmerId {2 o String farmerId3 o UnitedStatesAddress address4 o ProductType primaryProduct5}
Primitive Types
Composer has a few primitive types, namely
- String
- Double
- Integer
- Long
- DateTime
- Boolean
Arrays
Arrays can simply be defined with []
1o Integer[] integerArray
1--> Animal[] myAnimals
Relationships
A relationship is a tuple composed of
- Namespace being referenced
- Type being referenced
- Identifier instance being referenced
For example
1org.example.Vehicle#23451
Field Validation
Attributes may include a default value, string fields may include a regex validation, numerical values may include a range, these can be seen below
1asset Vehicle extends Base {2 // An asset contains Fields, each of which can have an optional default value3 o String reg default="ABC123"4 // A numeric field can have a range validation expression5 o Integer year default=2016 range=[1990,] optional // model year must be 1990 or higher6 o Integer[] integerArray7 o String V5cID regex=/^[A-z][A-z][0-9]{7}/8 o String LeaseContractID9 o Boolean scrapped default=false10 --> Participant owner //relationship to a Participant, with the field named 'owner'.11 --> Participant[] previousOwners optional // Nary relationship12 o Customer customer13}
Imports
We can also import a type from a different namespace with the following
1import org.example.MyAsset2import org.example2.*
Example
We can define a trading network consisting of the following models
- Asset
- Name: Commodity
- ID: Trading Symbol
- Attributes
- Trading Symbol
- Description
- Main Exchange
- Quantity
- Owner (Trader Participant)
- Participant
- Name: Trader
- ID: TradeID
- First Name
- Last Name
- Transaction
- Name: Trade
- Commodity (Commodity Asset)
- New Owner (Trader Participant)
The model file for the above network can be defined as follows
models.cto
1namespace org.example.mynetwork2asset Commodity identified by tradingSymbol {3 o String tradingSymbol4 o String description5 o String mainExchange6 o Double quantity7 --> Trader owner8}9participant Trader identified by tradeId {10 o String tradeId11 o String firstName12 o String lastName13}14transaction Trade {15 --> Commodity commodity16 --> Trader newOwner17}
Logic
Logic is defined in Script Files .js
which define transaction logic
Example
The logic for a transaction can be defined by a javascript function, in this example, for example, if a transaction occurs in which a Commodity changes Ownership from one Owner to a New Owner, the function can be defined as follows
trade.js
1/**2 * Track the trade of a commodity from one trader to another3 * @param {org.example.mynetwork.Trade} trade - the trade to be processed4 * @transaction5 */6async function tradeCommodity(trade) {7 // Assign the commodity owner to the new owner8 trade.commodity.owner = trade.newOwner9
10 // Persist updated asset in asset registry11 let assetRegistry = await getAssetRegistry('org.example.mynetwork.Commodity')12 await assetRegistry.update(trade.commodity)13}
Queries
Queries are defined in Query File .qry
file, note that a single .bna
file can only have one query
Access Control
Access Control Files .acl
define what permissions different users have, a single network can only have one access control file
Example
Access control files look like the following
1/**2 * Access control rules for tutorial-network3 */4rule Default {5 description: "Allow all participants access to all resources"6 participant: "ANY"7 operation: ALL8 resource: "org.example.mynetwork.*"9 action: ALLOW10}11
12rule SystemACL {13 description: "System ACL to permit all access"14 participant: "ANY"15 operation: ALL16 resource: "org.hyperledger.composer.system.**"17 action: ALLOW18}
Deployment
We can package our code into a .bna
file by running the following command in our directory
1composer archive create -t dir -n .
We then make use of a PeerAdmin
identity card that contains the necessary credential and use this to install the .bna
to the network
1composer network install --card PeerAdmin@hlfv1 --archiveFile tutorial-network@0.0.1.bna