Вы находитесь на странице: 1из 174

ETHEREUM, HYPERLEDGER BURROW, COMPOSER , SAWTOOTH

Introduction: Smart Contract Development (Courtesy Block Geeks)

This is a guest post by KC TAM on Using Various Tools for Smart Contract Development: Remix, Web3 on
TestRPC.

I recently read a good article on Blockgeeks, in which Ameer is trying to put everything about coding Decentralized
Applications into one masterpiece. What a very ambitious and great work it is! Of which there are several
components, and I would like to elaborate a bit on some of these tools, and how they can be used for contract
development.

This series of article is not for Smart Contract 101 or Ethereum platform. You definitely can find a lot of good
material in Blockgeeks. But I am sure by going through this, you will grab some ideas on these tools and hope this
helps when you are working on the Smart Contract with Solidity.

I will first make a quick description of the Smart Contract I have chosen. And later deploy this contract in four
environments. Here is a quick summary of the four environments we are showing here.

A Simplified Flow of Contract Compilation and Deployment


The Sample Smart Contract: Revenue Sharing

This application is taken from the Smart Contract in Chapter 4: Ethereum Accounts from the book “Blockchain
Applications a Hands-On Approach” by A. Bahga and V. Madisetti. It has been modified to match some
requirement on the latest release of Solidity.

This application is called Revenue Sharing. In short, a list of addresses is given when the contract is deployed.
Anyone can send a certain amount of money (here it is ethers or ether’s denomination) and this amount of money is
equally distributed to the addresses on the list. It is a rather simple Solidity contract.

Here is the Solidity of the Smart Contract.

pragma solidity ^0.4.8;

contract RevenueSharing {
address public creator;
mapping(uint => address) public shareholders;
uint public numShareholders;

event Disburse(uint _amount, uint _numShareholders);

function RevenueSharing(address[] addresses) {


creator = msg.sender;
numShareholders = addresses.length;
for (uint i=0; i< addresses.length; i++) {
shareholders[i] = addresses[i];
}
}

function shareRevenue() payable returns (bool success) {


uint amount = msg.value / numShareholders;
for (uint i=0; i<numShareholders; i++) {
if (!shareholders[i].send(amount)) revert();
}
Disburse(msg.value, numShareholders);
return true;
}

function kill() {
if (msg.sender == creator) selfdestruct(creator);
}
}

Some quick points about this contract


The contract is named RevenueSharing.

Function RevenueSharing() has the same name of the contract itself. It is the constructor, and only called once when
the contract is deployed. We see in this contract an array of addresses is supplied, and this array of addresses are
stored in another array called shareholders.

Function shareRevenue() is the only main function in this contact. When executing this function with an amount of
ethers (in msg.value), the amount is divided into the number of shareholders (numShareholders), and each address
in the shareholder array will get the portion. We will execute this function in our demo.

Function kill() is used for removing the contract. We will not use this function in the demo.

Note that all variables are defined with public. This helps us to observe more detail in the contract. In real life, we
should be careful when making variables or functions public due to security consideration.

Remix
Overview
Remix is a suite of tools to interact with the Ethereum blockchain in order to debug transactions (directly quoted
from here). There is an IDE version (Remix IDE) and an online version, which we will use here.
There are many tools inside Remix, but the following tools are of our interests,

 Solidity Compiler. which generates a lot of useful information that we will use in another environment
 Runtime Environment. Remix provides three:
 Injected Web3: to provider such as Mist or MetaMask
 Web3 Provider: to local host through ipc
 JavaScript VM: a simulated environment

Among the runtime environments, we are using JavaScript VM. In the JavaScript VM, Remix comes with five
Ethereum accounts, each of which is deposited with 100 ethers. This is good enough for testing our smart contract.
Also, mining is not required as it is done automatically.

You can easily access Remix from any browser (url: http://remix.ethereuem.org). This is a screenshot of Remix.

The screen is divided into several areas.

 Area for Smart Contract: we are pasting the Solidity code of contract here.
 Area of Compilation and Runtime: in Compilation tag, here show any compilation errors or warnings. in Run
tag, we deploy the contract and execute contract functions.
 Area of Transaction Logs: all transaction detail can be observed here.

Compile the Contract


We paste the Smart Contract code in Remix.
We notice that the code is automatically compiled, and there are some warnings. As they are not critical errors, we
are safe to moving forward.

If we click Details, we will see a lot of information for this contract. Among them they are,

 Bytecode
 ABI
 Web3 Deploy

They are needed when deploying this contract in another environment. We will refer this back later.

As we see no errors after compilation, we can run this contract onto Remix JavaScript environment.

Deploy the Contract

1. A Glimpse inside Run Tag


It is how it looks like inside the Run tag.

From the Environment, choose JavaScript VM.

After selecting JavaScript VM, we will see some accounts are populated in Account fields.

And as said, each of which are pre-deposited 100 ethers, just for testing. As we will use these accounts later, we can
copy them first.

The Gas limit is to specify how much gas we can spend on any transaction. As we are in test environment, we do
not worry this too much. I have tried some big contract deployment and the default gas limit is not adequate.
Anyway, it can be increased to whatever value when needed.

The Value part is where we send the amount of ethers during contract deployment and executing a function. In our
case, we do not put any value in contract deployment, but put some ethers when executing the function. See below
for more detail.
2. Deploy the Contract

Now we see the contract RevenueSharing is already selected (we have only one contract in our code). We will use
Create button to deploy this contract onto the JavaScript VM.

Something is required, as hinted in the input area: “address[] addresses”, when the contract is deployed. Remember
this contract requires a list of addresses as sharing targets? For demo purpose, we will use the 3rd, 4th and 5th
addresses listed above as the address list. So paste this beside the Create button:

Now make sure we have selected

 Environment: JavaScript VM
 Account: the first account when deploying this contract (begins with 0xca3…)
 Paste the address array above beside Create button

By pressing Create we will see the following happens.

3. After the Contract is Deployed


The contract is now deployed in JavaScript VM (memory), and the contract address is shown (0x692…). We do not
use this address in our demo. That address can be referred in other cases when needed.

Also, we see the variables marked as “public” is now shown, they are,

 shareholders
 numShareholders
 creator

And two functions we have defined in this contract,

 shareRevenue()
 kill()

Before everything, we observe that the account balance is reduced by a small amount of ethers. The difference
(417,626 weis, 1 wei = 10-18 ether) is the cost of deploying this contract. In real life, it is the real ethers deducted
from your account when you deploy a contract.

Interacting with Deployed Contract


1. Check Variables

We can first check the variables by pressing the variable buttons. Here we examine the numShareholders and
creator. For shareholders, as it is an array, we need to specify an index (0, 1 or 2), corresponding to the addresses we
put when the contract is deployed (created).

All the variables are as what we expect.

2. Execute shareRevenue() Function

Now we execute shareRevenue(). We use the first account to deposit 30 ethers when executing this function (This is
only for this function. In many cases this is not required.). According to the contract logic, the 30 ethers are to be
distributed among the account list, that is, the 3rd, 4th and 5th account in our account list. As of now, the balance of
each of them is still 100 ethers.

We use the same place to execute the function. Here we make sure to,

 in Account field, choose the first account (begins with 0xca3…)


 place 30 ethers in the Value
Then press shareRevenue.

After the function is executed, we examine the balance of each accounts, and see if it is executed according to our
design.

First, we see 30 ethers are deducted from 1st account, and all the three accounts on the list now have 110 ethers. So
the 30 ethers deducted from 1st account is now distributed among the three accounts. This part works perfects
according to the contract.

Also, if we closely examine the balance of 1st account, some additional amount of ethers is deducted. The
difference is 47,776 wei, which is the cost for this transaction. Every transaction, execution of function, or
deployment of contract costs you some amount of ethers.
Transaction Log
We have not touched the transaction log during our test, but everything is kept in log, even the inquiry of a variable.
Let us take a look on detail from two selected logs.

1. Contract Deployment

We can see who has deployed this contract, the contract address, and the transaction cost required to deploy it.

2. Execution of shareRevenue() function


Again we see it as a transaction cost. In shareRevenue(), there is a return boolean value and we see the “decoded
out” there is a “true” return. Also, we have an event for successful distribution and we see it inside “logs”.

Summary
This is how Remix helps in testing the code we develop. It comes with very handy features and intuitive user
interface. In next article we will use another environment, testrpc, to work on the same contract and see how it
works.

The Best Tools for Smart Contract Development Part


2: Web3 on TestRPC

Overview

TestRPC is a simulation of an Ethereum blockchain, which comes with 10 pre-defined Ethereum accounts and
supports mnemonics (that is, one can generate the same set of accounts with the same set of mnemonics). It does not
come with a User Interface as Remix, and we need node console plus the web3 library to interact with this
blockchain.

Preparation
The demo is done through command line or terminal. Use a terminal tool that supports screen spliting. I am using
iTerm2 on my Mac.

Install node and npm: please refer here for installation on your platform.

Remark: I recently found that when installing web3 with npm, the 1.0.0 beta version is installed, where the
commands used before (based on 0.20.4) do not work. Therefore we instead specify the version of web3.

All commands below are in version 0.20.0.

Open a terminal and split the screen into two. The left side is the node console, where we will work most of our
time. The right side is where we run the TestRPC.

Start TestRPC
On the right side, start the TestRPC

Here we have some observation

 TestRPC is a node application simulating an Ethereum blockchain in memory.


 10 accounts are pre-defined.
 These accounts are generated through mnemonic, and are different every time when TestRPC is started. To
keep the same set of accounts, we can use the mnemonic shown above as parameters when running
TestRPC.
 Also, the RPC is opened on localhost:8545. Web3 is accessing the blockchain through this.
We will not touch on this part anymore, assuming everything is working fine in this Ethereum blockchain. Now we
more focus on the node console (left side). During the test, we keep seeing commands and logs issued to the
blockchain displayed on the TestRPC side.

Web3 object

We need to instruct node console we are using web3 and pointing the blockchain web3 is interfacing.

which is exactly the accounts created in TestRPC.

A Handy Function Showing Balance

I have found a handy function (link) that can show balance for all accounts. Here is the function.
Simply copy-n-paste this function into node console. Now we can call the function checkAllBalances() at any time,
and it will show up the balance of all accounts in ether. Note that this function will be gone after we quit the node
console, but we can add it back at any time needed.

Deploy the Contract

1. Compiling the Contract

Now everything is ready. We can deploy our Revenue Sharing contract.


We need to reopen the Remix as we are leveraging the compiler on Remix. After we paste the contract code in
Remix, it is automatically compiled. Here we are using the result of contract deployment.

Click Detail on Compile Tag, and there is a lot of information there.

Among the information, three are of our interests: bytecode, ABI and Web3Deploy
The bytecode is the binary version of our contract after compilation and the instruction set to be run in Ethereum
Virtual Machine (EVM), and the ABI (application binary interface) is the interface we are interacting with the
contract bytecode.

Remix is kind enough to prepare the code in Web3Deploy, in which the bytecode and ABI are already included in
the commands. Therefore we just need to use the Web3Deploy part.

2. Deploy the Contract

First, as required by the contract, we need to define a list of target accounts. For demo purpose, the three accounts
starting from the second account are used, that is, from eth.accounts[1] to eth.accounts[3].
Then we follow what Web3Deploy suggests.

Create a class for revenue-sharing contract based on the ABI. Simply copy that line from Web3Deploy.

node console
> var revenuesharingContract =
web3.eth.contract([{"constant":true,"inputs":[],"name":"creator","outputs":[{
"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":
"function"},{"constant":false,"inputs":[],"name":"kill","outputs":[],"payable
":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"i
nputs":[],"name":"numShareholders","outputs":[{"name":"","type":"uint256"}],"
payable":false,"stateMutability":"view","type":"function"},{"constant":true,"
inputs":[{"name":"","type":"uint256"}],"name":"shareholders","outputs":[{"nam
e":"","type":"address"}],"payable":false,"stateMutability":"view","type":"fun
ction"},{"constant":false,"inputs":[],"name":"shareRevenue","outputs":[{"name
":"success","type":"bool"}],"payable":true,"stateMutability":"payable","type"
:"function"},{"inputs":[{"name":"addresses","type":"address[]"}],"payable":fa
lse,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"
inputs":[{"indexed":false,"name":"_amount","type":"uint256"},{"indexed":false
,"name":"_numShareholders","type":"uint256"}],"name":"Disburse","type":"event
"}]);

Now deploy the contract with the bytecode, plus the necessary information. Again, we can copy that line from
Web3Deploy. The deployed contract is an object called revenuesharing.

node console
> var revenuesharing = revenuesharingContract.new(
addresses,
{
from: web3.eth.accounts[0],
data:
'0x6060604052341561000f57600080fd5b60405161049d38038061049d833981016040528080518201919050506000336000806101000a81548
173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550815160028
1905550600090505b81518110156100f957818181518110151561009157fe5b90602001906020020151600160008381526020019081526020016
0002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373fffffffffffffffffffffffffffffffffffffff
f160217905550808060010191505061007a565b50506103938061010a6000396000f30060606040526004361061006d576000357c01000000000
00000000000000000000000000000000000000000000000900463ffffffff16806302d05d3f1461007257806341c0e1b5146100c757806368eca
613146100dc578063ab377daa14610105578063e579a0bd14610168575b600080fd5b341561007d57600080fd5b61008561018a565b604051808
273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910
390f35b34156100d257600080fd5b6100da6101af565b005b34156100e757600080fd5b6100ef610240565b60405180828152602001915050604
05180910390f35b341561011057600080fd5b6101266004808035906020019091905050610246565b604051808273fffffffffffffffffffffff
fffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610170610279565b604
051808215151515815260200191505060405180910390f35b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1
681565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673fffffffffffffffffffffffffffffffffffffff
f163373ffffffffffffffffffffffffffffffffffffffff16141561023e576000809054906101000a900473fffffffffffffffffffffffffffff
fffffffffff1673ffffffffffffffffffffffffffffffffffffffff16ff5b565b60025481565b600160205280600052604060002060009150549
06101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008060006002543481151561028b57fe5b049150600090505b6
0025481101561031d576001600082815260200190815260200160002060009054906101000a900473fffffffffffffffffffffffffffffffffff
fffff1673ffffffffffffffffffffffffffffffffffffffff166108fc839081150290604051600060405180830381858888f1935050505015156
1031057600080fd5b8080600101915050610293565b7f9c26340b8d01b4e039192edfd25f4a56ed070d45afe866b8685658b1ed3cd74d3460025
4604051808381526020018281526020019250505060405180910390a1600192505050905600a165627a7a72305820f0e717ba935e00c43896cc9
266a85af91a519061c044503be0a52b93f721d1610029',
gas: '4700000'
}, function (e, contract){
console.log(e, contract);
if (typeof contract.address !== 'undefined') {
console.log('Contract mined! address: ' + contract.address + '
transactionHash: ' + contract.transactionHash);
}
})

We will see (almost immediately) that the contract is mined.

Now we can use the object revenuesharing to interact with this deployed contract.

Interacting with Deployed Contract

The deployed contract is accessed through the object revenuesharing.

1. Examine the public variables


We can examine those variables marked as “public”.

2. Execute the shareRevenue() function

Before we execute the shareRevenue() function, let’s take a look on the balance.

Note that some amount is deducted in accounts[0], who has deployed the contract. The amount of ether paid for the
deployment is 417,626 weis. You can check it is the exact transaction cost when we did this in Remix.

Now we execute the function.

node console
> revenuesharing.shareRevenue({from: web3.eth.accounts[0], value:
web3.toWei(30), gas: 4700000});

Here we are calling the function shareRevenue(), and specifying that it is executed by accounts[0], with 30 ethers
(toWei is a function in web3 is used to convert 30 ethers to wei, as wei is the unit accepted in the command). We
also put the gas we allow to spend (It’s way more than required but we will get refund after execution).

After the transaction is executed, we can check the balance again.


We have achieved what we wish: 30 ethers are deducted from accounts[0] and distributed among accounts[1] to
accounts[3] (now each of them has 110 ethers). Beside, some amount is paid for executing this transaction. It is
47,776 weis, again, matching what we observed in Remix.

Summary
We have successfully done the same thing on TestRPC. The overall flow is almost the same as that in Remix,
except that we have to work on node console and web3 to interact with the blockchain in TestRPC. Next time we
will do almost the same thing on a private Ethereum blockchain.

Author: KC TAM

KC began his blockchain journey just a few months ago. His interest is to dig out more detail “how things work”,
and share with others what he has learnt.’LinkedIn: https://www.linkedin.com/in/ktam1/
One of the projects you will inevitably stumble upon when you visit blockchain conferences and follow blockchain
news is Hyperledger of the Linux Foundation. But while it is relatively straight forward to understand
what cryptocurrencies like Bitcoin and even Ethereum are, it is more difficult to get your head around the
Hyperledger initiative. But if you do, you’ll find some exciting projects for non-currency, industrial blockchain
applications.

What is Hyperledger?
Let’s start with what Hyperledger is not: Not a company. Not a cryptocurrency. Not a blockchain. Hyperledger is
rather something like a hub for open industrial blockchain development. On its website Hyperledger explains:

“Hyperledger is an open source collaborative effort created to advance cross-industry blockchain


technologies. It is a global collaboration, hosted by The Linux Foundation, including leaders in finance,
banking, Internet of Things, supply chains, manufacturing, and Technology.”

Hyperledger does not support Bitcoin or any other cryptocurrency. But the platform is thrilled by blockchain
technology. Not since the Web itself, the website tells, “has a technology promised broader and more fundamental
revolution than blockchain technology.” Blockchains has the potential to “build a new generation of transactional
applications that establishes trust, accountability, and transparency at their core while streamlining business
processes and legal constraints.”

So we have a lot of promises – and we have Hyperledger. With it, the Linux Foundation aims to create an
environment in which communities of software developer and companies meet and coordinate to build blockchain
frameworks. The Linux Foundation founded the platform in December 2015. In February 2016 it announced the
first founding members, in March 2016 ten more members joined.

Today Hyperledger has an impressive list of more than 100 members. The list covers a wide scope of well know
industry leaders. It includes mobility tech giants like Airbus and Daimler, IT-companies like IBM, Fujitsu, SAP,
Huawei, Nokia, Intel and Samsung, financial institutions like Deutsche Börse, American Express, J.P. Morgan,
BBVA, BNP Paribas and Well Fargo, as well as Blockchain startups like Blockstream, Netki, Lykke, Factom, bloq
and Consensys. A lot of the world’s largest companies in Tech and Finance meet at Hyperledger with some of the
hottest blockchain startups.

Start Your Free Trial Today


Free Trial

Something like the executive government of Hyperledger is the committee of leaders. It consists of more than 10
executives, most with decades of experience in Open Source and tight connections to several industries. You’ll find
leaders of the Apache Foundation and the W3C Consortium as well as engineers from IBM and more. Some of
Hyperledgers’s members, like Richard Brown and Tamas Blumer, already worked with Blockchain for years. For its
members, Hyperledger does not only provide technical knowledge and software frameworks but also various
contacts to industries and developers.

Relatively early in the history of Hyperledger, the project had to make an important decision. Executive Director
Brian Behlendorf was asked if there will be an “Hyperledger Coin”, a monetary unit running on the Hyperledger
blockchains. Behlendorf answered that the Hyperledger Project itself will never build its own cryptocurrency.

“You’ll never see a Hyperledger coin,” he said, “By not pushing a currency, we avoid so many political
challenges of having to maintain a globally consistent currency.”

This decision strongly shaped the strategic goals of Hyperledger to build industrial applications of blockchain
technology and sharply separating it from the get-rich schemes usually evolving from currency based blockchains.
This might be more boring, but also more straightforward to the technology.
Further, a “charter” outlines the goals of Hyperledger, like a mission guide. According to it, the platform aims to
“create an enterprise-grade, open source distributed ledger framework and code base” and create, promote and
maintain an open infrastructure.

This is somehow telling, but somehow vague. It outlines some kind of program, but doesn’t answer the big,
important questions: What do all these world leading companies and leaders do at Hyperledger? What projects are
they pushing forward? Who participates?

Projects
The “umbrella strategy” of Hyperledger incubates and promotes a range of business blockchain technologies,
framework, libraries, interfaces, and application. Currently, Hyperledger is the host of the following projects:

 Hyperledger Sawtooth: This is a modular blockchain suite developed by Intel, which uses a new consensus
algorithm called Proof of Elapsed Time (PoeT).
 Hyperledger Iroha: Iroha is a project of a couple of Japanese companies to create an easy to incorporate
the framework for a blockchain.

 Hyperledger Fabric: This project is lead by IBM. Fabric is a plug and plays implementation of blockchain
technology designed as a foundation to develop high-scaling blockchain applications with a flexible degree
of permissions.

 Hyperledger Burrow: This project develops a permissible smart contract machine along the specification of
Ethereum.

Beside these framework projects, Hyperledger has several tool projects aiming to make the access to and
development of blockchains easier and more effective. This is Cello, a blockchain as-a-service deployment model,
Composer, a tool for building blockchain business networks, an Explorer to view, query and deploy transactions and
associated data on blockchains, and Indy, a collection of tools, libraries and further components for digital identities
rooted on blockchains.

Hyperledger obviously engages in a wide scope of non-monetary blockchain projects. But this rough view on these
projects must remain dissatisfying, as the short descriptions don’t go far beyond keywords. So we take a closer look
at the two most prominent projects: Sawtooth and Fabric. Both projects are created by large companies – Intel and
IBM – and given to Hyperledger as open source code. With Hyperledger the companies continue pushing their
blockchain projects forward, while everybody else is invited to contribute.
Intel’s Sawtooth
Sawtooth Lake is Intel’s modular blockchain suite. It is written in Python and designed for use cases in many fields
from IoT to Financials. The dominant characteristics of Sawtooth Lake are that it supports both permissioned and
permissionless application and deployments and that its uses a newly developed consensus algorithm called Proof of
Elapsed Time (PoET).

PoET uses new secure CPU instruction, which is more and more available in new processors like Intel builds. With
these instructions, PoET ensures a safe and random selection of a so-called “leader”. This can be compared with
Bitcoin mining, in which the miners compete for a one-time access to write the blockchain. Other than Bitcoin’s
proof algorithm, PoET doesn’t need specialized mining hardware.

To become a leader, every “validator” – which equals to a node or a miner – needs to use the secure CPU
instruction to request a wait time. The validator with the shortest wait time will be elected as a leader. Like every
good mining, algorithm PoET works like a lottery with the price to get write access to the blockchain.

Other than with cryptocurrencies there is no reward for the leader. It is just part of running the software. So there
will be no energy-burning competition like in cryptocurrencies. Every node simply can use its CPU – as long as it is
a new model and, maybe, from Intel – to participate in the leader selection for no costs. What is mining in Bitcoin,
is simply a non-intrusive part of the software in Sawtooth Lake.
Another innovation of Sawtooth Lake is the building and propagation of transactions. A client builds transactions
and submits it to the validators. This wrap the transactions they get inside of a batch and commit them to the state
altogether. This is a similar, but not identical process as when cryptocurrency miners wrap transactions to a block.
With this batching Sawtooth solves the problem of securely validating transactions which depend on each other.

To date, Sawtooth is tested in several applications. It is tested to record the journey of seafood from the ocean to the
table, using IoT sensors, and track ownership, possession, and parameters through the whole supply chain, from the
fisherman to the supermarket. The buyer can access a complete and trustless record of the whole live chain of the
seafood. This use case in supply chain and product history is increasingly discussed for Blockchains.

Sawtooth is also tested to streamline the process of transferring bonds. The developers created a user interface to
track and transfer bonds. With this users can manage a whole portfolio of bonds on the blockchain. Another use
case of Sawtooth currently tested are digital assets. The developers built a platform for managing digital asset
ownership on the Sawtooth blockchain, which could be able to manage a wide scope of digital assets. The
connecting dot between this application of Sawtooth seems to be the marketplace for digital assets of any kind
which is built in the blockchain and already has a graphical interface for users.

While these tests are ongoing and Sawtooths enjoys a wide industry interest, the project seems to get less traction
than IBM’s contribution to Hyperledger.

Fabric
Maybe the most interesting project in the Hyperledger family is IBM’s Fabric. Rather than a single blockchain
Fabric is a base for the development of blockchain based solutions with a modular architecture. With Fabric
different components of Blockchains, like consensus and membership services can become plug-and-play. Fabric is
designed to provide a framework with which enterprises can put together their own, individual blockchain network
that can quickly scale to more than 1,000 transactions per second.
What is Fabric and how does it work? The framework is implemented in Go. It is made for enabling consortium
blockchains with different degrees of permissions. Fabric heavily relies on a smart contract system called
Chaincode, which every peer of the networks runs in Docker containers. An overview of Fabric’s technology can be
found in the manual.

While not completely and generally permissioned, Fabric allows enterprises to make parts of the blockchain, if not
all, permissioned. Participants usually need to register to get the permission to join and issue transactions on a
Fabric based blockchain. To use resources more efficiently, Fabric has fewer nodes than a public chain and
computes data massively in parallel, which makes Fabric scale much better than public blockchains. Also its basic
architecture supports confidential data, giving its members more privacy as they find on a public blockchain.

Maybe most important is the separation between so-called “Endorsers” and “Consensus Nodes”. If you are familiar
with cryptocurrencies like Bitcoin you will recognize the separation between miners and nodes. The Endorsers have
the state, and build, validate and propagate transactions and chaincode, while the Consensus Nodes orders the
already validated transactions. While this separation has not been a concept of the first blockchain concept of
Satoshi Nakamoto, but became an unwished reality in most cryptocurrencies, Fabric is one of the first to make this
separation a design principle. This enables Fabric for example to implement a better division of labour, so that not
every peer of the network has to do every job.

While having no native currency, Fabric allows the user to define assets from client side and use them with the
Fabric Composer. Fabric’s Chaincode Smart Contracts framework is similar to Ethereum: Chaincode defines the
business logic of assets, the rules for reading and altering the so called state of the assets. Like Ethereum Fabric
maintains not a set of unspent outputs, as Bitcoin maintains, but the state of the blockchain which is not restricted to
transactional data.

Other than the public blockchains of cryptocurrencies Fabric allows participants to build a separate channel for their
assets and hence isolate and segregate transactions and a ledger. With this method, the chaincode needed to read and
alter the state of an asset will only be installed on peers involved in this certain business case. Like in good chat
programs Fabric’s blockchains allow the user to participate in both open and private interactions.

Beyond this IBM proposes an alternative design for public and permissionless blockchains. Fabric uses a public key
infrastructure to generate cryptographic certificates tied to organizations and users. So it is possible to restrict data
and channel access to certain actors.

Fabric’s strength seems to be the high grade of flexibility in permission and privacy while enabling high scalability
through a more advanced division of labour of network participants.
For IBM Fabric serves as a flagship project for blockchain development. The IT giant uses Fabric for a variety of its
own projects and for collaborations with several business partners.

In March 2017 IBM launched IBM Blockchain, a service that enables developers to “quickly build and host
security-rich production blockchain networks on the IBM Cloud.” With this move, IBM catches up with Microsoft,
which long integrated blockchains in its Azure Cloud.

However, while Microsoft is just a cloud host for several external blockchains, IBM heavily promotes its own
blockchain framework, Fabric, for a lot of use cases. For example, at the end of March, Natixis and Trafigure
partnered with IBM to use a blockchain based on Fabric for commodity trade finance for US crude oil transactions.
All major steps in a crude oil transaction are digitized on the blockchain, massively improving transparency,
efficiency, and security.

In April IBM announced several new blockchain projects based on Fabric: The company partnered with Sichuan
Heijia to build up a blockchain based supply chain platform for pharmaceutical procurements. In the same month,
IBM started to cooperate with Japan’s Mizuho Financial Group and Mizuho Bank to create a blockchain based
platform for trade financing. This projects aim to streamline trading operations and improve supply chain efficiency.

In another project disclosed in April 2017 IBM cooperates with the National University of Singapore to develop a
module on financial technology to improve the student’s education in this area. Finally, in May 2017, IBM was
chosen as a partner of TenneT, Sonnen and Vandebron to develop a blockchain for managing the electric grid in the
Netherlands and Germany.

The backbone of non-monetary, industrial blockchain technology?

While there is a lot of information available on Sawtooth and Fabric, there is less known about the other projects.
Maybe these projects first have to grow and mature to be a subject of media releases, tests and real world
application. But the best-known projects, Sawtooth and Fabric, are interesting and seem to be backed by strong IT
companies. It will be interesting to see if Hyperledgers succeeds in connecting these blockchains, for example by
developing tools which can be used with all Hyperledger blockchain frameworks.

While most other blockchain projects focus on cryptocurrencies and tokens, the projects around Hyperledger
demonstrate a strong potential to build the backbone of non-monetary, high scaling industrial applications of
blockchain technology. With interesting concepts and leaders in the technology behind, Hyperledge has not the
worst chances to win this prize.
Hyperledger Burrow v0.16
Linux

Master

Develop

Hyperledger Burrow is a permissioned Ethereum smart-contract blockchain node built with <3 by Monax.
It executes Ethereum smart contract code on a permissioned virtual machine. Burrow provides transaction
finality and high transaction throughput on a proof-of-stake Tendermint consensus engine. For smart
contract development most functionality is provided by monax chains, exposed through monax, the entry
point for the Monax Platform.

Table of Contents
 What is burrow
 Installation
 For developers
 Usage
 Configuration
 Contribute
 License
 Future work

What is Burrow ?
Hyperledger Burrow is a permissioned blockchain node that executes smart contract code following the
Ethereum specification. Burrow is built for a multi-chain universe with application specific optimization in
mind. Burrow as a node is constructed out of three main components; the consensus engine, the
permissioned Ethereum virtual machine and the rpc gateway. More specifically Burrow consists of the
following:

 Consensus Engine: transactions are ordered and finalised with the Byzantine fault-tolerant Tendermint
protocol. The Tendermint protocol provides high transaction throughput over a set of known validators and
prevents the blockchain from forking.
 Application Blockchain Interface (ABCI): The smart contract application interfaces with the consensus
engine over the ABCI. The ABCI allows for the consensus engine to remain agnostic from the smart contract
application.
 Smart Contract Application: transactions are validated and applied to the application state in the order
that the consensus engine has finalised them. The application state consists of all accounts, the validator set
and the name registry. Accounts in Burrow have permissions and either contain smart contract code or
correspond to a public-private key pair. A transaction that calls on the smart contract code in a given
account will activate the execution of that account’s code in a permissioned virtual machine.
 Permissioned Ethereum Virtual Machine: This virtual machine is built to observe the Ethereum operation
code specification and additionally asserts the correct permissions have been granted. Permissioning is
enforced through secure native functions and underlies all smart contract code. An arbitrary but finite
amount of gas is handed out for every execution to ensure a finite execution duration - “You don’t need
money to play, when you have permission to play”.
 Application Binary Interface (ABI): transactions need to be formulated in a binary format that can be
processed by the blockchain node. Currently tooling provides functionality to compile, deploy and link
solidity smart contracts and formulate transactions to call smart contracts on the chain. For proof-of-
concept purposes we provide a monax-contracts.js library that automatically mirrors the smart contracts
deployed on the chain and to develop middleware solutions against the blockchain network. Future work
on the light client will be aware of the ABI to natively translate calls on the API into signed transactions that
can be broadcast on the network.
 API Gateway: Burrow exposes REST and JSON-RPC endpoints to interact with the blockchain network and
the application state through broadcasting transactions, or querying the current state of the application.
Websockets allow to subscribe to events, which is particularly valuable as the consensus engine and smart
contract application can give unambiguously finalised results to transactions within one blocktime of about
one second.

Burrow has been architected with a longer term vision on security and data privacy from the outset:

 Cryptographically Secured Consensus: proof-of-stake Tendermint protocol achieves consensus over a


known set of validators where every block is closed with cryptographic signatures from a majority of
validators only. No unknown variables come into play while reaching consensus on the network (as is the
case for proof-of-work consensus). This guarantees that all actions on the network are fully
cryptographically verified and traceable.
 Remote Signing: transactions can be signed by elliptic curve cryptographic algorithms, either
ed25519/sha512 or secp256k1/sha256 are currently supported. Burrow connects to a remote signing
solution to generate key pairs and request signatures. Monax-keys is a placeholder for a reverse proxy into
your secure signing solution. This has always been the case for transaction formulation and work continues
to enable remote signing for the validator block signatures too.
 Secure Signing: Monax is a legal engineering company; we partner with expert companies to natively
support secure signing solutions going forward.
 Multi-chain Universe (Step 1 of 3): from the start the monax platform has been conceived for
orchestrating many chains, as exemplified by the command “monax chains make” or by that transactions
are only valid on the intended chain. Separating state into different chains is only the first of three steps
towards privacy on smart contract chains (see future work below).

Installation
burrow is intended to be used by the monax chains command via monax. Available commands such as make
| start | stop | logs | inspect | update are used for chain lifecycle management.
For Developers
Dependency management for Burrow is managed with glide, and you can build Burrow from source by
following

 Install go
 Ensure you have gmp installed (sudo apt-get install libgmp3-dev || brew install gmp)
 and execute following commands in a terminal:
 go get github.com/Masterminds/glide
 go get -d github.com/hyperledger/burrow
 REPO=$($GOPATH/src/github.com/hyperledger/burrow)
 cd $REPO && glide install
 cd $REPO/cmd/burrow && go install

To run burrow, just type $ burrow serve --work-dir <path to chain directory>, where the chain directory
needs to contain the configuration, genesis file, and private validator file as generated by monax chains
make.
This will start the node using the provided folder as working dir. If the path is omitted it defaults
to ~/.monax.
For a Vagrant file see monax-vagrant for drafts or soon this repo for Vagrant and Packer files.

Usage
Once the server has started, it will begin syncing up with the network. At that point you may begin using
it. The preferred way is through our javascript api, but it is possible to connect directly via HTTP or
websocket.

Configuration
A commented template config will be written as part of the monax chains make process and can be edited
prior to the monax chains start process.

Logging
Logging is highly configurable through the config.toml [logging] section. Each log line is a list of key-
value pairs that flows from the root sink through possible child sinks. Each sink can have an output, a
transform, and sinks that it outputs to. Below is a more involved example of than the one appearing in the
default generated config of what you can configure:
# This is a top level config section within the main Burrow config
[logging]
# All log lines are sent to the root sink from all sources
[logging.root_sink]
# We define two child sinks that each receive all log lines
[[logging.root_sink.sinks]]
# We send all output to stderr
[logging.root_sink.sinks.output]
output_type = "stderr"
[[logging.root_sink.sinks]]
# But for the second sink we define a transform that filters log lines from Tendermint's p2p
module
[logging.root_sink.sinks.transform]
transform_type = "filter"
filter_mode = "exclude_when_all_match"

[[logging.root_sink.sinks.transform.predicates]]
key_regex = "module"
value_regex = "p2p"

[[logging.root_sink.sinks.transform.predicates]]
key_regex = "captured_logging_source"
value_regex = "tendermint_log15"

# The child sinks of this filter transform sink are syslog and file and will omit log lines
originating from p2p
[[logging.root_sink.sinks.sinks]]
[logging.root_sink.sinks.sinks.output]
output_type = "syslog"
url = ""
tag = "Burrow-network"

[[logging.root_sink.sinks.sinks]]
[logging.root_sink.sinks.sinks.output]
output_type = "file"
path = "/var/log/burrow-network.log"

Contribute
We welcome all contributions and have submitted the code base to the Hyperledger project governance
during incubation phase. As an integral part of this effort we want to invite new contributors, not just to
maintain but also to steer the future direction of the code in an active and open process.

You can find us on:

 the Marmot Den (slack)


 here on Github
 support.monax.io
 read the Contributor file

Future work
Some burrows marmots have already started digging to build the enterprise ecosystem applications of
the future are listed in docs/proposals. Marmots live in groups we welcome your help on these or other
improvement proposals. Please help us by joining the conversation on what features matter to you
SAWTOOTH Tutorial

Scenarios
 Basic Cookie Market

o Building the Market


o Making a Baker
o Making a Buyer
 International Cookie Arbitrage

o Expanding the Market


o Baking Biscotti
o Buying Biscotti

Basic Cookie Market


This scenario mirrors the one in the CLI tutorial, and is a good way to both explore the basics of Marketplace
Navigator and to compare how to do similar tasks between the CLI and GUI. It walks through the creation of a
controlled market, participants, and goods, as well as the exchange of those goods.

Building the Market

In most markets, you will want the creation of Assets to be centrally controlled so that everyone can’t just make
infinite goods, similar to how the Federal Reserve controls how and when money is printed. Let’s build that Market
authority now.

1. The Market works like any other Participant, so we will start by generating a new WIF key.

2. Download the key, and then click Create Participant. You may want to rename the file something meaningful,
like “market.wif”.
3. Name the market “Market”, write a short description, and then click Submit.

4. The first thing a market needs is a currency, so click on the + button next to the Assets list.

5. We’re going to make both a new AssetType (currency), and a new Asset (usd). We will make both “restricted”,
since we do not want other participants making counterfeit currency. USD will also be “divisible”, since it is
possible to trade fractions of a dollar.
6. Now that dollars exist as a concept, we need to create some for the market. Wait for the transation to be
committed to the blockchain, and once USD appears on the sidebar, click the +next to the Holdings list.
Note

Waiting for the blockchain to commit will be a common experience throughout this scenario and won’t be
explicitly mentioned again. If you feel the need to check the status of recent transactions, you can do so by
clicking on the Block name in the menu bar.
7. We’re going to create a strategic reserve of $1,000,000, which we will later distribute to the other participants in
our market.

8. We’re going to use the pre-made reusable “token” asset to create our distribution offer, but first we’ll need
a Holding for that too.

9. Finally, we’ll create our offer to provision each participant with $1,000. Click the + Create Offerbutton in the
menu bar.
10. Set the offer to take in tokens and payout usd at a 1:1000 ratio. We only want this exchange to be possible once
per person, so set both the minimum and maximum input to 1, and limit it to Execute Once per Participant.
11. Our market is all set and ready to go! Select Sign Out from the Hi, Market dropdown, and let’s make a new
participant.
Making a Baker

Now we’re going to create Abby, an entrepeneur who will bake some cookies to sell on the market.

1. Follow the same steps as above to generate and save a new WIF key. Then fill out Abby’s info and
click Submit.

2. You can see that USD already exists in the list of Assets. Let’s add cookies. Click the + next to Assets.
3. We’ll make the cookie AssetType and chocolate chip cookie Asset similar to how we made USD, but this time
they will not be “restricted”, since almost anyone can come up with new recipes for cookies, or physically bake
new chocolate chip cookies.
4. Now that chocolate chip cookies are a thing, let’s bake a batch. Click the + next to Holdings, and make a
holding with 24 cookies.

5. The last thing we need to do before we can create a sell offer is to make a holding of US dollars to send our
payments to. We could create an empty one, but why not take advantage of that market provision? Start by
creating an authorization token by clicking the + next to Holdings.
6. Tokens are unrestricted, so we can create a holding prepopulated with one, and since they are not consumable,
one is all we need.
7. Select Dashboard from the Hi, Abby dropdown menu.
8. Click on Latest Open Offers
9. Click the Accept button to the right of the provisioning offer.
10. We can create a new savings account in the process of accepting the Market’s provisioning offer. We just have
to select New Holding from the Output Holding dropdown, and we’re good to go.
11. Finally we can create our offer to sell cookies. This will look similar to the provisioning offer the Market created
earlier, but we won’t limit how many times it can be executed. Let’s sell the cookies for $2 each.

12. We’re done with our baker Abby, so go ahead and Sign out.
Making a Buyer

Finally we will create Ben, a discerning cookiehead looking for the absolute best chocolate chip. He will take the
Market’s USD provision, and use it to purchase Abby’s cookies. You should be familiar with all the steps by now.

1. Generate and save a WIF key, and then create Ben’s account.

2. Create a token holding.

3. Use that token to accept the Market’s USD provisioning offer and create a USD holding (get there by clicking
on Dashboard > Latest Open Offers > Accept).
4. We’re ready buy some cookies! Return to the Dashboard and click on Latest Open Offers one more time. This
time though the offer we will be accepting is Abby’s.

5. Let’s get a dozen cookies! We’ve earned it.


International Cookie Arbitrage
Let’s build off our previous scenario to showcase one of the more powerful features of of the Navigator
UI: arbitrage. Say we have a new baker cooking some authentic Italian biscotti, but they only accept Euros. So long
as a USD -> Euro exchange exists, there is no need to force American buyers to tediously create new holdings and
manually execute a long series of exchanges.

Expanding the Market

1. First we need to log our Market back in. If you are still signed in as Ben, sign out and this time click Import
WIF, instead of generating a new one.

2. The easiest way to enter Market’s WIF key is to upload the market.wif file we generated earlier (you still have
that right?). Click Upload WIF File, select the file, and then click Submit.
3. Now that you are logged back in as Market, let’s create a new currency asset: Euros. Click the +to the right
of Assets, and fill out the form.

4. We’ll need a holding with a strategic reserve of €1,000,000 as well. Add the holding with the +to the right
of Holdings.
5. Finally we’ll create an offer to exchange USD for Euros. Click + Create Offer in the menu bar above. As of
this writing, the exchange rate was €0.96 to $1. A quirk of this UI is you can only enter whole integer amounts
even if the asset is divisible, but we can get around that by making our offer $100 for €96.
6. Now that we’ve expanded our Market to handle foreign currency, all that’s left to do is Sign out.
Baking Biscotti

We’re going to create a new participant, Claudio, who will bake some biscotti and put them on sale in our newly
international market.

1. Go through the steps to generate a new WIF key and create a new participant detailed above.
2. Once Claudio is provisioned, create a new biscotti asset just like we did Euros.

3. And just like Abby in the previous scenario, we will bake our first batch by creating a holding.
4. We’ll also create an empty savings account for Claudio to keep the Euros that are sure to be pouring in soon.
5. Finally, we’ll put the biscotti up for sale by creating an offer that will take €3 for 2 biscotti.
6. Claudio is all set, so let’s go ahead and Sign out.
Buying Biscotti

Almost finished. We’ll log back in as Ben who, always craving new cookie experiences, will purchase some biscotti
from Claudio.

1. Log Ben in by importing his WIF key just like we did with Market above.
2. Click on Latest Open Offers.
3. Click the Accept button to the right of Claudio’s biscotti offer.
4. Now we could have a problem. Claudio is asking for Euros, and we can see if we click on Initial Holding that
we don’t have any of those. But fear not, arbitrage to the rescue! Click on the + Offer button to right of the
initial holding dropdown. From the pop-up that appears, you can select the Market’s USD for Euro exchange
offer.

5. Now we are free to select our USD savings account as the initial holding, and route those dollars through the
Market’s exchange to our intended biscotti target, which we will keep in a new /jar holding.
Note

This exchange exposes some of the quirks of the Quantity field that may not be immediately obvious. It
represents the number of times the smallest possible integer representation of the initial exchange is going to be
executed. So for example, in this case our $100 -> €96exchange has been reduced to $25 -> €24 (the smallest
integer representation). That €24 buys you 16 biscotti, so by entering a 2 into the Quantity field, we will spend
$50, and receive 32 biscotti. It is generally best when making exchanges to double check the calculated holding
amounts before clicking Accept.
6. Click Accept and enjoy those sweet sweet digital biscotti.
Next Previous
TUTORIAL
Overview
Marketplace Navigator is a browser-based GUI designed to be used with the Sawtooth Lake Marketplace
transaction family. It allows users to easily register Participants, create and exchange Assets and Holdings,
and even view the current state of the blockchain.

Before You Begin


This guide covers the use of the Navigator UI, not the initial setup, or the intricacies of running your own
validators. For developers running these systems for the first time, begin with the CLI tutorial, and refer to
the the readme files in the /navigator directory.

Navigator Tasks
Account Creation and Setup

 Creating a Participant
 Signing in an Existing Participant

Creating Assets and Holdings

 Creating an Asset
 Creating a Holding

Offers and Transactions

 Creating an Offer
 Accepting an Offer
 Chaining Offers (Arbitrage)
 Transfering Assets Directly

Creating a Participant
The first time you sign into Marketplace Navigator you will be prompted to either create or import a
“Wallet Import Format” (WIF) key. This is a unique cryptographic string used by the blockchain to
authorize transactions, as well as by Marketplace Navigator to confirm your identity and sign you in.

Note

Beware! It is not possible to change or recover this key if it is lost!


Creating a Participant with a New Key

To create a Participant with a new WIF key:

1. Open Marketplace Navigator in your browser, or sign out of Marketplace Navigator if already signed
in. You should see this screen:

2. Click Generate WIF, and a key will be generated and saved to your browser’s local storage.
3. Before proceeding to account creation, you must save the generated key by:

 Clicking Download Key to download the key in a text file.


 Or by clicking Copy Key to Clipboad to copy the key, which can then be pasted wherever you would like it
to be saved.
4. Click Create Participant.
5. Enter a Name for yourself.
6. (Optional) Enter a Description.
7. Click Submit.
Note

Participants’ names must be unique. If you encounter a server error at this point, it could be caused by
using a name that has already been taken.
 If participant creation was successful the provisioning screen should appear:

 After several minutes, the participant is fully provisioned, and you will be brought to the user dashboard:

Creating a Participant with an Existing Key


Note that this is not the same as Signing in an Existing Participant, which is described below. If you have
previously generated a WIF key you would like to use in creating a new participant, follow these steps:

1. Open Marketplace Navigator as described above.


2. Click Import WIF.
3. Input your WIF key by:
 Pasting the key into the text box labeled “Paste WIF key”.
 Or by clicking Uploade WIF File, to upload the ”.wif” file Marketplace Navigator originally generated, or any
plain text file which contains only the WIF key you wish to upload.
4. Click Submit.
5. Fill in participant info following the same directions described above (steps 5-7).

Signing in an Existing Participant


You can sign in an existing account to Marketplace Navigator using a similar process to Creating a
Participant with an Existing Key described above. All you need is your WIF key.

1. Open Marketplace Navigator.


2. Click Import WIF.
3. Input your WIF key by:
 Pasting the key into the text box labeled “Paste WIF key”.
 Or clicking Uploade WIF File, to upload the ”.wif” file Marketplace Navigator originally generated, or any
plain text file which contains only the WIF key you wish to upload.
4. Click Submit, and you will be taken to the user dashboard.

Note

Beyond this point, the directions all assume you are successfully signed in.
Creating an Asset
Assets are types of goods which can be exchanged on the marketplace. They can include anything from
US Dollars, to barrels of oil, to cookies. Assets are further organized into AssetTypes, such as currency or
baked goods. Any participant can create new assets and types, and many kinds of markets to be
approximated.

1. From the user dashboard, click on the + button to the right of the “Assets” heading:
2. Enter a Name for the asset. Like most names in Marketplace, it must begin with a “/” character, and
generally follows a naming convention similar to a computer directory. For example: “/currency/usd”.
This field can be left blank, but that will generate a long randomized identifier, and is generally not
recommended.
3. (Optional) Enter a Description.
4. Enter a Type by either:

 Selecting an existing asset type from the dropdown menu.


 Or by using the following directions to create a new asset type:

 Click Add Type.


 In the pop-up that appears, Enter a Name. (the same naming rules apply).
 (Optional) Enter a Desciption.
 Select whether or not this asset type should be “restricted”. If selected, only the participant who created
the type will be able to create new assets with it.

Note

You may click Discard to close the Add Type pop up.
5. Use the checkboxes at the bottom to choose which options should apply to this asset:

 Restricted - Only the creating participant will be able to create new Holdings of this asset with quantities
greater than zero.
 Consumable - When spent, this asset is consumed. If disabled, it is effectively infinite.
 Divisible - This asset can exist in fractional form. In other words, it will be possible to exchange half of one
(or less).
6. Click Submit.
Creating a Holding
Holdings are containers where actual quantities of specific Assets are held. Each may only hold one kind of
asset, and in order to execute Exchanges, participants must have holdings in both the assets they are
providing and receiving.

1. From the user dashboard, click on the + button to the right of the “Holdings” heading:

2. Enter a Name for the holding. Once again the name must begin with a “/”, and generally follows a
convention similar to computer directories, such as “/accounts/checking”. If left blank, a random
identifier will be generated for the holding.
3. (Optional) Enter a Description.
4. Select an Asset from the dropdown menu.
5. Enter a Count for your holding.
Note

If you are not the creator of the asset, and that asset is “restricted”, you can still create holdings for it,
but you must enter a count of zero.
6. Click Submit.
Creating an Offer
Offers are open offers of exchange, which any participant or multiple participants can accept. In order to
create an offer you must have Holdings in both the Asset you are providing and the one you expect to
receive in return, though the latter can be empty (i.e. have a count of zero).

1. Click on the Create Offer button in the top right of your screen.
2. Enter a Name for the offer. Once again the name must begin with a “/”, and generally follows a
convention similar to computer directories, such as “/orders/cookies”. If left blank, a random identifier
will be generated for the holding.
3. (Optional) Enter a Description.
4. Select the Input holding from the dropdown. This is where payments you receive will go, and those
payments will be of the kind of asset in the holding.
5. Enter the Amount of input asset you expect to receive.
6. Select an Output holding from the dropdown. This is where the payouts you are offering will come
from.
7. Enter an Amount for the output asset.
Note

Using the Amount fields, you are actually creating an exchange ratio, not a fixed sum. So setting
amounts of 50 and 100 is equivalent to 5 and 10, 1 and 2, and so on. There is currently no way to
create a fixed indivisible package like “$10 for half a dozen cookies”.
8. Enter a Minimum. This is the lowest quantity of the input asset that can be used to fulfill the offer.
9. Enter a Maximum, the highest quantity of an input that can be used.
10. Select how repeatable the offer should be:

 Any - the offer can be fulfilled an unlimited number of times (or until the output holding is empty).
 Execute Once - it is a one time offer, and will close after being fulfilled once.
 Execute Once per Participant - Each participant in the marketplace may fulfill the offer once.
11. Click Submit.
Accepting an Offer
In order to accept an offer made by another participant, you must have Holdings for both the Assetyou
need to pay with, and the asset you expect to receive in return, though it is possible to create the latter as
part of the exchange process.

1. From the user dashboard, click on Latest Open Offers.


2. From the list that appears, click the Accept button next to the offer you wish to accept. This will bring
up the “Execute Exchange” screen:
3. Select the Initial Holding you would like to pull assets from to fulfill this offer.
4. Select the Final Output Holding where you would like to keep the assets you receive.
Note

If you would like to store the received assets in a new holding, select New Holding from the
dropdown, and enter the name of the holding into the text field that appears. As usual, this name
must begin with a “/”.
5. Enter the Quantity of exchanges you would like to execute.
Note

In this case, Quantity refers not to the count of either asset being transfered, but to the smallest
integer expression of the exchange ratio the offer was originally set at. For example, if the offer was
originally an 80:100 exchange, the smallest integer expression would be 4:5. So a Quantity of 1 would
payout 4 of the input, and receive back 5 of the output.
6. Click Accept.
Chaining Offers (Arbitrage)

It is possible to chain together multiple offers using the + Offer buttons next to the initial
holdingand final holding dropdowns. This allows you to build a chain of exchanges which can include
assets you have no Holdings in. For example, it is possible to trade US Dollars for Euros for some
authentic Italian biscotti, even though you have no holding of Euros.

 Click on either + Offer button, to bring up a dropdown of any available offers with the appropriate asset types.
 Select an offer from the list to add it to the chain.
 The initial + Offer adds offers to the beginning, and the latter adds them to the end.
 After being added, an offer can be removed from the beginning or end with the - Offer button that appears.

Transfering Assets Directly


It is possible to transfer quantities of Assets directly from one Holding to another directly without creating
and accepting offers. The transfer can be internal, sent to another holding you control, like sending USD
from your checking to your savings, or external, like a money transfer to a Nigerian prince. The transfers
are one way, and always originate from a holding you control.

1. Click on your name in the upper right corner of the screen.


2. Select Transfer Assets from the dropdown that appears:

3. From the Source dropdown, select a holding for the assets to originate from.
4. Select a Participant to whom you wish to transfer the asset. The default of Self will transfer assets
between your own holdings.

5. Select a Destination holding from the final dropdown. It will display only holdings that match the kind
of asset being transfered and belong to the participant selected.
6. Enter the Amount you would like to transfer.
7. Click Transfer.
Next Previous
Architecture Overview
What is the Sawtooth Lake Distributed Ledger?
The Sawtooth Lake Distributed Ledger is a software framework for constructing decentralized ledgers
with extensible transaction types. It is comparable to the blockchain ledger that underlies Bitcoin.
Sawtooth Lake uses a unique mechanism for reaching consensus on the validity of the ledger based on
trusted code running inside a hardware-protected Intel Software Guard Extensions (SGX) enclave.

One of the initial transaction families supported by Sawtooth Lake is the MarketPlace. The MarketPlace
Transaction Family establishes the concepts of participants, accounts, assets, holdings, liabilities, and
offers in a decentralized ledger to facilitate the exchange of digital assets. The Sawtooth Lake architecture
allows the definition of additional transaction families or the consumption of an existing asset-type
agnostic transaction family (like MarketPlace) to meet domain-specific needs.

Repository Structure
One repository contains all of the the code needed:

sawtooth-core

Contains fundamental classes used throughout the Sawtooth Lake project, as well as:

 The gossip networking layer


 Basic transaction, block, and message objects
 The base journal implementation
 The PoET journal consensus mechanism
 Built-in transaction families - Endpoint Registry and Integer Key Registry
 The implementation of a server, known as the validator
o acts as a node on the gossip network
o validators exchange and act upon messages, as defined by the core classes and via additional plug-
in transaction families like the MarketPlace Transaction Family
 The MarketPlace Transaction Family, located in the extensions directory.
o demonstrates how to inherit and extend base sawtooth-core object types to implement a custom
transaction family
o includes a command line interface called mktclient for interacting with validators running the
MarketPlace Transaction Family
o useful for buying, selling and trading digital assets
 Example code, in the form of games, which demonstrate key concepts of Sawtooth Lake
 Tools including a Vagrant environment for easily launching a network of validators
 Source files for this documentation

Core Architecture
The Sawtooth Lake Distributed Ledger consists of three major architectural layers: the Ledger layer, the
Journal layer, and the Communication Layer.

Ledgers

Ledgers are a conceptual semantic and data model layer for transaction types. Ledgers are described as a
‘conceptual’ layer because they are implemented as a specialization of existing base classes already
present in the Communication and Journal layers.
In addition to some in-built system ledgers (Endpoint Registry, and Integer Key Registry), implementing
new classes in the ledger layer allows for the creation of new transaction families. The MarketPlace
Transaction Family, located in the extensions directory of sawtooth-core, is a good example of how the
ledger layer can be extended.

Journals

A journal handles consensus on blocks of identifiers. Identifiers reference transactions, which are globally
replicated. In order to confirm blocks, nodes need a copy of the transaction. In this fashion, the journal
provides global consensus on block ordering, transaction ordering within blocks, and the content of
transactions.

The journal module in sawtooth-core contains:

 the implementation of the base transaction and transaction block classes


 the consensus algorithms
 the global store manager
 the block store and key value store

The consensus journal object is journal.journal_core.Journal in the sawtooth-core repository.

Consensus Mechanisms

Sawtooth Lake implements PoET as a consensus mechanism.

PoET and SGX


The Sawtooth Lake Distributed Ledger provides a unique mechanism to ensure fairness in the node
lottery. Instead of a Proof-of-Work competition amongst nodes, Sawtooth Lake implements a Proof-of-
Elapsed-Time (PoET) algorithm for distributed consensus. PoET relies upon a trusted execution
environment, Intel’s Software Guard Extensions (SGX), to generate fair, verifiable random wait timers and
signed certificates of timer expiration. This mechanism substantially reduces the computation and energy
cost of ensuring fair distributed consensus.

The implementation of PoET in Sawtooth Lake runs in a simulated enclave, not a true trusted execution
environment. For this reason, attestation that wait timers have been fairly generated is not possible. This
version of PoET is intended for experimental purposes and should not be used as the consensus
mechanism in any ‘production’ environment.

The PoET implementation is located in sawtooth_validator.consensus.poet0 in sawtooth-core.

Transactions

A transaction is a set of updates to be applied atomically to a ledger. The transaction defines the data
model and representation. For example, in the IntegerKey Transaction Family (located in
ledger.transaction.integer_key in sawtooth-core), the IntegerKeyTransaction is defined as a list of zero or
more updates to key value pairs using the defined verbs ‘set’, ‘inc’, and ‘dec’. The associated
IntegerKeyTransactionMessage wraps the derived transaction object in a standard message object. There
is typically a message type for every transaction type.

Blocks

A block is a set of transactions to be applied to a ledger. Other than some specialized transaction block
implementations for the consensus mechanisms, new transaction block types are not typically created.
The expectation is that multiple transaction types will coexist on single transaction blocks of type
journal.transaction_block.TransactionBlock. There is typically a message type for every transaction block
type.

Communication

The gossip protocol enables communication between nodes. It includes protocol level connection
management and basic flow control on top of UDP. A Token Bucket [1] implementation is used to limit the
average rate of message transmission.

[1] https://en.wikipedia.org/wiki/Token_bucket

Peers in the gossip network are called Nodes. Nodes exchange Messages. Message handling upon arrival
is dispatched via EventHandlers associated with the journal.

Messages
Messages represent information to send or receive from peers over the gossip network. Messages are
serialized and deserialized using a standard wire format (either CBOR or JSON).

Message types include:

 transaction messages
 transaction block messages
 journal transfer messages
 debug messages (log data)
 connection messages
 shutdown messages
 topology messages

Messages are used broadly across the architecture for both system communication (administrative
messages, consensus messages), and for transaction-type specific handling.

Transaction Family Plugin Architecture


As mentioned above, the creation of new classes in the conceptual ‘ledger’ layer allows for the addition of
transaction families. Via a message handling and dispatch model, new transaction families can register
themselves with the underlying journal consensus and global store mechanisms to allow for arbitrary
callbacks on message arrival and persistence of the transactions.

If specialized transaction stores are required, those can also be defined and added to the ledger during
initialization (via register_transaction_types).

In order to create a basic transaction family, implement the following:

def register_transaction_types(ledger)
Register message handlers for defined message types and add a transaction store to the ledger for the
transaction types.

class BasicTransactionMessage(transaction_message.TransactionMessage)
implement __init__

class BasicTransaction(transaction.Transaction)
implement __init__, __str__, is_valid, apply, and dump

Refer to ledger.transaction.integer_key in sawtooth-core for a simple example, or to


mktplace.transactions.market_place in sawtooth-core/extensions/mktplace for a more substantial
example.
Transaction Families are loaded into the validator in sawtooth-validator via the “TransactionFamilies”
config value (see sawtooth-core/validator/etc/txnvalidator.js).

Next Previous

Vagrant
Overview
Vagrant is a tool which installs and configures virtual development environments. It allows development
teams to easily specify and share consistent virtual machine configurations.

The dev tools directory (path ‘’sawtooth-core/tools’‘) of the sawtooth-core repository contains a Vagrant
configuration which is specifically tailored to Sawtooth development. A new developer with installed
copies of Vagrant and VirtualBox can clone the sawtooth-core repository and have a functional VM which
can run validators within a few minutes.

A quick introduction to using dev tools is available as a quickstart in this Developer’s Guide.

Layout of the sawtooth-dev-tools git Repository


The dev tools directory is structured as follows:

tools/
bootstrap.d/
guest-files/
plugins/
scripts/
tests/
win-bin/
Vagrantfile
Vagrantfile

Vagrantfile is the main configuration file for Vagrant. It is ruby code executed by Vagrant and is executed
every ime a vagrant command is executed.

bootstrap.d
The bootstrap.d directory contains a set of bash scripts which are executed in order during the provisioning
step of ‘vagrant up’. These scripts are always executed.

guest-files
The guest-files directory contains configuration files which are used by the bootstrap.d scripts.

There is also a local-env.sh script which contains environment specific variables for Sawtooth
development, such as PYTHONPATH.
plugins

The plugins directory contains bash scripts which can be easily configured to execute during the
provisioning step of ‘vagrant up’. These scripts run after bootstrap.d scripts.

scripts
This scripts directory contains scripts which are sometimes useful to the developer after provisioning has
been completed and the developer has a shell in the virtual machine. For example, there are scripts which
help build Ubuntu packages.

tests
The tests directory includes tests run within the Vagrant environment. These are in addition to the unit and
integration tests found in the tests directory of sawtooth-core, sawtooth-validator and sawtooth-mktplace.

win-bin
The win-bin directory includes scripts for running Sawtooth natively under Windows and is not used in the
Vagrant environment.

Layout in the Virtual Machine


A convenient feature of Vagrant is the easy sharing of directories between the host machine and the
guest virtual machine. By default the Vagrant configuration directory is mounted under /vagrant in the
virtual machine.

In the dev tools configuration a /project mount point is also defined which provides access to the
Sawtooth repositories.

Configuration Options
There is a rudimentary configuration system in place which can impact how the Vagrant environment is
provisioned.

The files involved are:

conf-defaults.sh
conf-local.sh
conf-local.sh.example
The conf-local.sh file, which is not checked into the git repository, is the one that should be modified
locally. This file can be initialized by copying conf-local.sh.example to conf-local.sh.

The conf-default.sh file defines the defaults for configuration values which are not set.

The valid config values are:


INSTALL_TYPE

By default, this is set to ‘none’. It can be set to one of:

 none - do not install anything by default


 setup.py - build and install sawtooth-core, sawtooth-validator, sawtooth-mktplace from the git
repositories using ‘python setup.py install’
 deb - build and install sawtooth-core, sawtooth-validator, sawtooth-mktplace from the git repositories
by first creating deb packages and then installing those deb packages.

START_TXNVALIDATOR
By default, this is set to ‘no’. If set to ‘yes’, then txnvalidator will be started with upstart or systemd. For this
option to work, INSTALL_TYPE must be set to ‘deb’.

PLUGINS
By default, set to “build_ubuntu_deps install_ubuntu_deps install_sphinx”. Specify a space-separated list of
plugins to run. The plugins are contained in the plugins directory.

The following plugins are available:

build_ubuntu_deps

This plugin builds the debian packages for cbor, colorlog, and pybitcointools. They are placed in
/project/build/packages/.

install_latex
This plugin installs Latex, which is required for building a PDF of the documentation. This is disabled by
default because it takes a fairly long time to download.

install_ubuntu_deps
This plugin installs the debian packages built by build_ubuntu_deps.

install_sphinx
This plugin installs sphinx, which is required for building the sawtooth documentation.

Next Previous

MarketPlace Data Model


As with other transaction families built on the Sawtooth Lake platform, the MarketPlace Transaction
Family is defined by an ordered log of transactions. The implicit data model underlying the transaction
family provides a means for understanding and enforcing consistency in the transaction log. This section
describes the data model.
Every object in the implicit data model is referenced by an identifier equivalent to the identifier of the
transaction used to create the object. The transaction identifier is a SHA256 hash of the message
signature.

Note that the authoritative log of transactions and the cached state of objects associated with the log can
be retrieved through the Distributed Ledger Web API.

Participant
A participant object refers to an organization or an individual. Conceptually, the participant object refers
to the “owner” of an asset. Participants can create assets (and asset types), own assets, offer to exchange
assets, and transfer ownership to another participant.

The current model for a participant is very simple: it is a means of capturing the information necessary to
authorize transactions on assets owned by the participant.

"Participant" :
{
"type" : "object",
"properties" :
{
"address" :
{
"type" : "string",
"format" : "ADDRESS",
"required" : true
},

"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "object",
"required" : false
}
}
}
The properties of a Participant include:

a unique derivation of the verifying key (public key) for the transaction used to register the participant; the
address: address provides a means of verifying the identity of participants for future transaction verification and
authorization

a unique name for the participant chosen by the person or organization creating the participant, names are
name:
constructed from printable ascii characters with the exception of ‘/’
description: an optional property for describing in human readable form who or what the participant represents

Account
An account object represents a collection of holdings and liabilities with at most one holding for each
asset and at most one liability for each asset type. An account is useful primarily as a means of managing
asset aggregation.

"Account" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
}
}
}
The properties of a Account include:

a unique name for the object chosen by the person or organization creating the participant, names are
name:
constructed from printable ascii characters and must begin with ‘/’

description: an optional property for describing in human readable form who or what the object represents

creator: the identifier of the participant who registered the account object

AssetType
An AssetType is a descriptor for a class of Assets. The creator of an AssetType is granted the right to
create Assets of the type and assign them to owners within a Holding. If the Restricted flag is True (it is
True by default), then the creator of the AssetType is the only participant who can create Assets of that
type. This would be appropriate, for example, for controlling creation of private stock certificates. If the
Restricted flag is False, then any Participant can create Assets of that type and assign ownership to a
participant within a Holding. This would be appropriate for broad asset types like “brown eggs” where
many Participants are likely to create Assets of the type.

"AssetType" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
},

"restricted" :
{
"type" : "boolean",
"default" : true,
"required" : false
}
}
}
The properties of a AssetType include:

a unique name for the object chosen by the person or organization creating the participant, names are
name:
constructed from printable ascii characters and must begin with ‘/’

description: an optional property for describing in human readable form who or what the object represents

creator: the identifier of the participant who registered the account object

a flag to indicate whether the creator of the asset type (if the flag is True) or other participants (if the flag is
restricted:
False) can create assets of the type

Asset
An Asset is an instance of an Asset Type. It is intended to represent a “thing” to which value and
ownership can be ascribed. Assets may be strictly intrinsic to the MarketPlace such as instances of a
virtual currency or MarketPlace tokens. Alternatively, assets may provide a MarketPlace handle for digital
or physical objects that exist outside of the MarketPlace.

"Asset" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
},

"asset-type" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#AssetType",
"required" : true
},

"restricted" :
{
"type" : "boolean",
"default" : true,
"required" : false
},

"consumable" :
{
"type" : "boolean",
"default" : true,
"required" : false
},

"divisible" :
{
"type" : "boolean",
"default" : false,
"required" : false
}
}
}
The properties of a Asset include:

a unique name for the object chosen by the person or organization creating the participant, names are
name:
constructed from printable ascii characters and must begin with ‘/’
description: an optional property for describing in human readable form who or what the object represents

creator: the identifier of the participant who registered the account object

asset-type: the identifier of the asset type from which the asset was created

a flag to indicate whether the creator of the asset (if the flag is True) or other participants (if the flag is False)
restricted:
can create Holdings for the asset with non-zero counts

a flag to indicate whether assets are transferred (if the flag is True) or copied (if the flag is False); Holdings
consumable: with non-consumable assets always have an instance count of zero or one since a non-consumable asset can
be copied infinitely

divisible: a flag to indicate whether fractional portions of assets are acceptable (if the flag is True)

Holding
A Holding object represents ownership of a collection of asset instances and controls the right to transfer
assets to a new owner. Any participant can create an empty (i.e. the instance-count property is 0) holding
for any asset. An empty Holding represents a container into which assets may be transferred. To create a
holding with instance-count greater than 0, the creator of the holding must be the creator of the asset or
the asset must be non-restricted.

"Holding" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
},

"account" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Account",
"required" : true
},

"asset" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Asset",
"required" : true
},

"instance-count" :
{
"type" : integer,
"required" : true
}
}
}
The properties of a Holding include:

a unique name for the object chosen by the person or organization creating the participant, names are
name:
constructed from printable ascii characters and must begin with ‘/’

description: an optional property for describing in human readable form who or what the object represents

creator: the identifier of the participant who registered the account object

account: the identifier of the account used to scope the holding

asset: the identifier of the asset that is held

instance-count: the number of instances of the asset being held

Liability
Like a Holding, a Liability represents ownership though in the case of a Liability ownership is of a debt or
financial obligation. Where a Holding captures ownership of specific asset instances, a Liability captures a
promise or guarantee for future ownership transfer of a specific kind of asset.

"Liability" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},
"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
},

"account" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Account",
"required" : true
},

"asset-type" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#AssetType",
"required" : true
},

"instance-count" :
{
"type" : integer,
"required" : true
},

"guarantor" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
}
}
}
The properties of a Liability include:

a unique name for the object chosen by the person or organization creating the participant, names are
name:
constructed from printable ascii characters and must begin with ‘/’

description: an optional property for describing in human readable form who or what the object represents

creator: the identifier of the participant who registered the account object

account: the identifier of the account used to scope the holding

asset-type: the identifier of the asset types


instance-count: the number of instances of the asset being held

ExchangeOffer
An ExchangeOffer represents an offer to exchange assets or liabilities of one type for assets or liabilities
of another type. Assets or liabilities are received into an input holding or liability. The ratio expresses the
number of assets to be transferred out for every one that is transferred in.

"ExchangeOffer" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
},

"input" :
{
"type" : "string",
"format" : "IDENTIFIER",
"oneOf" : [
{ "$ref" : "#Liability"},
{ "$ref" : "#Holding" }
],
"required" : true
},

"output" :
{
"type" : "string",
"format" : "IDENTIFIER",
"oneOf" : [
{ "$ref" : "#Liability"},
{ "$ref" : "#Holding" }
],
"required" : true
},

"ratio" :
{
"type" : float,
"required" : true
},

"minimum" :
{
"type" : int,
"required" : false
},

"maximum" :
{
"type" : int,
"required" : false
},

"execution" :
{
"type" : "string",
"oneOf" : [ "ExecuteOnce", "ExecuteOncePerParticipant", "Any" ],
"required" : false
}
}
}
The properties of an ExchangeOffer include:

name: a unique name for the object chosen by the person or organization creating the participant, names are
constructed from printable ascii characters and must begin with ‘/’

description:
an optional property for describing in human readable form who or what the object represents

creator:
the identifier of the participant who registered the account object

input: a Holding or Liability into which “payment” is made, this defines the kind of asset that will be received
by the creator of the offer

a Holding or Liability from which goods will be transferred, this defines the kind of asset that will be
output:
given by the creator of the offer, the creator of the offer must be the same as the creator of the holding
or liability

ratio: the number of instances to transfer from the output holding for each instance deposited into the input
holding

minimum: the smallest number of acceptable instances that can be transferred into the input holding for the offer
to be valid

maximum: the largest number of acceptable instances that can be transferred into the input holding in one
transaction for the offer to be valid

a modifier that defines additional conditions for execution of the offer, it may have one of the
following values:

execution: ExecuteOncePerParticipant

the offer may be executed by a participant at most one time


ExecuteOnce

the offer may be executed at most one time


Any

the offer may be executed as often as appropriate

SellOffer
A SellOffer is identical to an ExchangeOffer except that assets must be transferred out from a Holding.

"SellOffer" :
{
"type" : "object",
"properties" :
{
"name" :
{
"type" : "string",
"required" : false
},

"description" :
{
"type" : "string",
"required" : false
},

"creator" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Participant",
"required" : true
},

"input" :
{
"type" : "string",
"format" : "IDENTIFIER",
"oneOf" : [
{ "$ref" : "#Liability"},
{ "$ref" : "#Holding" }
],
"required" : true
},

"output" :
{
"type" : "string",
"format" : "IDENTIFIER",
"$ref" : "#Holding",
"required" : true
},

"ratio" :
{
"type" : float,
"required" : true
},

"minimum" :
{
"type" : int,
"required" : false
},
"maximum" :
{
"type" : int,
"required" : false
},

"execution" :
{
"type" : "string",
"oneOf" : [ "ExecuteOnce", "ExecuteOncePerParticipant", "Any" ],
"required" : false
}
}
}
The properties of a SellOffer include:

name: a unique name for the object chosen by the person or organization creating the participant, names are
constructed from printable ascii characters and must begin with ‘/’

description:
an optional property for describing in human readable form who or what the object represents

creator:
the identifier of the participant who registered the account object

input: a Holding or Liability into which “payment” is made, this defines the kind of asset that will be received
by the creator of the offer

output: a Holding from which goods will be transferred, this defines the kind of asset that will be given by the
creator of the offer, the creator of the offer must be the same as the creator of the holding

ratio: the number of instances to transfer from the output holding for each instance deposited into the input
holding

minimum: the smallest number of acceptable instances that can be transferred into the input holding for the offer
to be valid

maximum: the largest number of acceptable instances that can be transferred into the input holding in one
transaction for the offer to be valid

a modifier that defines additional conditions for execution of the offer, it may have one of the
following values:

ExecuteOncePerParticipant:

execution: the offer may be executed by a participant at most one time

ExecuteOnce: the offer may be executed at most one time

Any: the offer may be executed as often as appropriate

Creating Packages for Ubuntu


Prerequisites
To create packages for Ubuntu, you need the following:

 Ubuntu 16.04 LTS with Internet access


 git Repository: sawtooth-core

The remainder of these instructions assume a vanilla Ubuntu 14.04 installation as a starting point. An easy
method to obtain such a machine is by creating one with vagrant:

% vagrant init ubuntu/xenial64


% vagrant up
% vagrant ssh

Install Dependencies
Apply the latest Ubuntu updates:

vagrant@ubuntu $ sudo apt-get update -y


Install the prerequisite packages:

vagrant@ubuntu $ sudo apt-get install -y -q \


python-twisted \
python-twisted-web \
python-dev \
python-setuptools \
g++ \
swig \
libjson0 \
libjson0-dev \
libcrypto++-dev \
git \
python-all-dev \
python-stdeb

Create Directory for Resulting Packages


Create a directory to hold the packages as we build them. For this guide, we will use $HOME/packages.

vagrant@ubuntu $ mkdir $HOME/packages

Create Python Dependency Packages


cbor

Create the python-cbor deb package:

vagrant@ubuntu $ mkdir $HOME/projects


vagrant@ubuntu $ cd $HOME/projects
vagrant@ubuntu $ wget https://pypi.python.org/packages/source/c/cbor/cbor-0.1.24.tar.gz
vagrant@ubuntu $ tar xvfz cbor-0.1.24.tar.gz
vagrant@ubuntu $ cd cbor-0.1.24
vagrant@ubuntu $ python setup.py --command-packages=stdeb.command bdist_deb
vagrant@ubuntu $ cp deb_dist/python-cbor*.deb $HOME/packages/
colorlog

Create the python-colorlog deb package:

vagrant@ubuntu $ cd $HOME/projects
vagrant@ubuntu $ wget https://pypi.python.org/packages/source/c/colorlog/colorlog-2.6.0.tar.gz
vagrant@ubuntu $ tar xvfz colorlog-2.6.0.tar.gz
vagrant@ubuntu $ cd colorlog-2.6.0
vagrant@ubuntu $ python setup.py --command-packages=stdeb.command bdist_deb
vagrant@ubuntu $ cp deb_dist/python-colorlog*.deb $HOME/packages/
pybitcointools

Create the python-pybitcointools deb package:

vagrant@ubuntu $ cd $HOME/projects
vagrant@ubuntu $ wget https://pypi.python.org/packages/source/p/pybitcointools/pybitcointools-1.1.15.tar.gz
vagrant@ubuntu $ tar xvfz pybitcointools-1.1.15.tar.gz
vagrant@ubuntu $ cd pybitcointools-1.1.15
vagrant@ubuntu $ python setup.py --command-packages=stdeb.command bdist_deb
vagrant@ubuntu $ cp deb_dist/python-pybitcointools*.deb $HOME/packages/

Create SawtoothLake Python Packages


Clone Repository

Clone or copy the repository into the VM environment:

vagrant@ubuntu $ mkdir -p $HOME/projects


vagrant@ubuntu $ cd $HOME/projects
vagrant@ubuntu $ git clone https://github.com/IntelLedger/sawtooth-core.git
vagrant@ubuntu $ cd sawtooth-core
vagrant@ubuntu $ git checkout 0-7
vagrant@ubuntu $ cd $HOME
Create Packages

Create packages from sawtooth repository:

vagrant@ubuntu $ for pkg in signing core extensions/mktplace extensions/arcade extensions/bond


> do
> dir=$HOME/projects/sawtooth-core/$pkg
> if [ -d $dir ]; then
> cd $dir
> python setup.py --command-packages=stdeb.command bdist_deb
> cp deb_dist/*.deb $HOME/packages/
> fi
> done

vagrant@ubuntu $ cd $HOME/projects/sawtooth-core
vagrant@ubuntu $ ./bin/package_validator
vagrant@ubuntu $ cp python-sawtooth-validator*.deb $HOME/packages/

Create tar File of Packages


To make it easy to deliver the Ubuntu deb files, create a tar file:

vagrant@ubuntu $ cd $HOME
vagrant@ubuntu $ mv packages sawtoothlake-x.y.z-ubuntu-packages
vagrant@ubuntu $ tar cvfj sawtoothlake-x.y.z-ubuntu-packages.tar.bz2 sawtoothlake-x.y.z-ubuntu-packages
Note

The x.y.z in the above tar file name should be replaced with the version of the overall sawtoothlake
deliverable.
Next Previous

FAQ
Validators
How do I change the validator configuration?

An example configuration file is at sawtooth-core/validator/etc/txnvalidator.js.example. Copy that file to a


new file in the same directory and make changes to the new file. When starting the txnvalidator, use the –
config argument to reference the configuration file, In this example, we have copied
the txnvalidator.js.example file to single- node.js and modified it:

$ cd /project/sawtooth-core
$ ./bin/txnvalidator -v --config validator/etc/single-node.js
Multiple config files can be overlaid, and all of the settings in the config file can be overridden on the
command line, but that’s beyond the scope of this answer.

What configuration changes should I make to run a single validator?

Copy the file sawtooth-core/validator/etc/txnvalidator.js.example to single-node.js and make the following


changes:

TargetWaitTime The desired mean inter-block commit time across the network. While the default is 30
seconds, we recommend 5 seconds for development and experimenting.

InitialWaitTime This is only important when starting the first node which will initialize the ledger
(i.e. GenesisLedger is true). This will often be the case when testing. We recommend setting it to the same
value as TargetWaitTime.

Previous
Chaincode for Go developers, Part 1: Writing Blockchain
chaincode in Go for Hyperledger Fabric v0.6

How to write chaincode for a blockchain network


Varun Ojha March 06, 2017
(First published March 01, 2017)

Learn how to develop chaincode using Golang for a blockchain network based on Hyperledger Fabric v0.6. This
deep-dive tutorial covers the fundamentals, such as the APIs for interacting with the Fabric, as well as advanced
topics like data modeling, access control, and events. Abundant sample code demonstrates a home loan and
purchase contract process on blockchain.

Get a monthly roundup of the best free tools, training, and community resources to help you put
Blockchain to work. Current issue | Subscribe
In this tutorial, learn how to develop chaincode using Golang for a blockchain network based on Hyperledger Fabric
v0.6. I cover the fundamentals, such as the role of chaincode and the APIs for interacting with the underlying Fabric,
as well as advanced topics like data modeling, access control, and events. Abundant code examples demonstrate a
home loan and purchase contract process on blockchain. (See "Downloadable resources" at the end of this tutorial
to download the entire sample chaincode.)

This tutorial is the first of a series; follow-on tutorials will cover how to unit test your chaincode and develop client
applications that can invoke your deployed chaincode.

What is chaincode?
Try IBM Cloud for free

© Copyright IBM Corporation 2017 Trademarks Build your next app quickly and easily with IBM Cloud Lite. Your free account never expires, and you
get 256 MB of Cloud Foundry runtime memory, plus 2 GB with Kubernetes Clusters. Get all the details and find out how to get started.

Chaincode, also called the smart contract, is essentially the business logic that governs how the different entities or
parties in a blockchain network interact or transact with each other. Simply put, the chaincode is the encapsulation
of business network transactions in code. Invocations of the chaincode result in sets and gets of the ledger or world
state.
At the time of publishing this tutorial, Hyperledger supports writing chaincode in Golang or the Java™ language,
which eventually runs inside a docker container. Because chaincode support for Java is still in beta, I'll focus on Go in
this tutorial.

Setting up your development environment


Recommended content for blockchain developers
Sharpen your skills with developerWorks tutorials, courses, blogs, and community support in the Blockchain
Developer Center.

Follow the steps in the IBM Cloud documentation starting at "Setting up the development environment." When you
reach the section titled "Set up your development pipeline," stop there; you are now ready to start developing
chaincode in Go.

Chaincode structure
Let's take a close look at chaincode structure. As mentioned, the sample chaincode in Listing 1 and throughout
this tutorial, as well as the architecture discussed, strictly conform to the v0.6 preview of the Hyperledger
Fabric.

Line 4 of Listing 1 imports the shim package into your chaincode. The shim package provides APIs that let your
chaincode interact with the underlying blockchain network to access state variables, transaction context, caller
certificates and attributes, and to invoke other chaincodes, among other operations.

Listing 1. Sample chaincode


package main

import "fmt" import "github.com/hyperledger/fabric/core/chaincode/shim"

type SampleChaincode struct { }

func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,


error) { return nil, nil }

func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,


error) { return nil, nil
}

func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,


error) { return nil, nil }

func main() {
err := shim.Start(new(SampleChaincode))
if err != nil {
fmt.Println("Could not start SampleChaincode")
} else {
fmt.Println("SampleChaincode successfully started") }

Main function
The starting point for any Go program is the main function, and hence it's used for bootstrapping/ starting the
chaincode. When the peer deploys its instance of the chaincode, the main function gets executed.

As shown in line 2 of Listing 2, the shim.Start(new(SampleChaincode)) line starts the chaincode and registers it
with the peer. You can verify this locally by running the code in your development environment, which will
produce the following error: [shim] CRIT : peer.address not configured, can't connect to peer. Listing 2.
Main()
func main() {
err := shim.Start(new(SampleChaincode))
if err != nil {
fmt.Println("Could not start SampleChaincode")
} else {
fmt.Println("SampleChaincode successfully started") }

The SampleChaincode is the struct that is required to implement the shim.Chaincode interface, which has three
methods — Init, Query, and Invoke — for it to be considered a valid Chaincode type by the shim package. Let's look
at each of the three methods.

Init method
The Init method is called when the chaincode is first deployed onto the blockchain network and will be executed by
each peer that deploys its own instance of the chaincode. This method can be used for any tasks related to
initialization, bootstrapping, or setup.

Listing 3. Init()
func (t *SampleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,
error) { return nil, nil
}

Query method
The Query method is invoked whenever any read/get/query operation needs to be performed on the blockchain
state. Depending upon the complexity of the chaincode, this method can hold your read/get/query logic, or it could
be outsourced to separate methods that can be invoked from within the Query method.

The Query method is not intended to change the state of the underlying blockchain, and hence does not run within
a transactional context. If you try to modify the state of the blockchain within the Query method, an error will
complain about the lack of a transactional context. Also, because this method is only for reading the state of the
blockchain, its invocations are not recorded on the blockchain.

Listing 4. Query()
func (t *SampleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,
error) { return nil, nil
}

Invoke method
The Invoke method is invoked whenever the state of the blockchain is to be modified. Simply put, all create,
update, and delete operations should be encapsulated within the Invoke method. Because this method will modify
the state of the blockchain, the blockchain Fabric code will automatically create a transaction context inside which
this method will get executed. All invocations of this method are recorded on the blockchain as transactions, which
ultimately get written into blocks.

Listing 5. Invoke()
func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,
error) { return nil, nil
}

Data models in chaincode


The Hyperledger ledger consists of two parts:

1. World state, which is stored in a key value store. This key value store is powered by the RocksDB. This key
value store takes in a byte array as the value, which can be used to store a serialized JSON structure.
Essentially this key value store can be used to store any custom data model/schema required by your smart
contract to function.
2. Blockchain, which consists of a series of blocks each containing a number of transactions. Each block
contains the hash of the world state and is also linked to the previous block. Blockchain is append-only.

Listing 6 shows how to create custom data models/schemas. It defines data models required for a home loan
application. The primary model is called LoanApplication, which in turn has primitive and complex data types,
namely Personal and Financial Info.

Since our key value store stores data as JSON, these data models would eventually need to be converted into a
JSON string. The annotation for each field, for example, json:"id" acts like metadata for the marshal/unmarshal
API, which will use these annotations to map each field with its corresponding json string equivalent
representation.
Listing 6. Code to create custom data models/schemas
//custom data models type
PersonalInfo struct {
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
DOB string `json:"DOB"`
Email string `json:"email"`
Mobile string `json:"mobile"`
}

type FinancialInfo struct {


MonthlySalary int `json:"monthlySalary"`
MonthlyRent int `json:"monthlyRent"`
OtherExpenditure int `json:"otherExpenditure"` MonthlyLoanPayment int
`json:"monthlyLoanPayment"`
}

type LoanApplication struct {


ID string `json:"id"`
PropertyId string `json:"propertyId"`
LandId string `json:"landId"`
PermitId string `json:"permitId"`
BuyerId string `json:"buyerId"`
SalesContractId string `json:"salesContractId"`
PersonalInfo PersonalInfo `json:"personalInfo"`
FinancialInfo FinancialInfo `json:"financialInfo"`
Status string `json:"status"`
RequestedAmount int `json:"requestedAmount"`
FairMarketValue int `json:"fairMarketValue"`
ApprovedAmount int `json:"approvedAmount"`
ReviewerId string `json:"reviewerId"`
LastModifiedDate string `json:"lastModifiedDate"`
}

Storing and retrieving data


The code in Listing 7 and Listing 8 shows how to store and fetch data from the ledger.

Storing data into the ledger


The CreateLoanApplication method on line 1 of Listing 7 takes in two arguments. The first argument is the
ChaincodeStubInterface, which has useful APIs to interact with the blockchain ledger, transaction context, caller
certificates, etc. The second argument is a string array that can be used by the invoker of the method to pass in
required arguments.

Lines 2-8 handle logging and validation of input arguments.

On line 9, the loan application Id value, which would be used as the key to store the actual loan application object, is
retrieved.

On line 10, the actual loan application content is retrieved in the form of a JSON string. For example,
‘{"propertyId":"prop1","landId":"land1","permitId":"permit1","buyerId":"vojha24","personalInfo":
{"firstname":"Varun","lastname":"Ojha","dob":"dob","email":"varun@gmail.com","mobile":"99999999"},"finan
{"monthlySalary":10000,"otherExpenditure":0,"monthlyRent":1000,"monthlyLoanPayment":1000},"status":" 2:30pm"}’

Line 12 is where the stub.PutState method is invoked to store the loan application id and the actual loan application
JSON content as a key value pair into the blockchain ledger. Note that the value being stored in the key value store
must always be a byte array. Hence the loan application JSON string is first converted to a byte array before storing
it into the ledger.

Listing 7. Code to store data into the ledger


func CreateLoanApplication(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { fmt.Println("Entering CreateLoanApplication")

if len(args) < 2 {
fmt.Println("Invalid number of args")
return nil, errors.New("Expected at least two arguments for loan application creation") }

var loanApplicationId = args[0] var


loanApplicationInput = args[1]

err := stub.PutState(loanApplicationId, []byte(loanApplicationInput))


if err != nil {
fmt.Println("Could not save loan application to ledger", err)
return nil, err }

fmt.Println("Successfully saved loan application")


return nil, nil
}

Fetching data from the ledger


in Listing 8, the GetLoanApplication method on line 1 takes in two arguments. The first argument is the
ChaincodeStubInterface, which has useful APIs to interact with the blockchain ledger, transaction context, caller
certificates, etc. The second argument is a string array that can be used by the invoker of the method to pass in
required arguments. Lines 2-7 handle logging and validation of input arguments.

On line 9, the loan application Id value, which would be used as the key to retrieve the actual loan application object
from the ledger, is retrieved.

Line 10 is where the stub.GetState method is invoked to retrieve the loan application JSON content in the form of a
byte array by passing in the loanApplicationId key. Note that the value being stored in the key value store must
always be a byte array. Hence the loan application JSON string is first converted to a byte array before storing it into
the ledger.

Listing 8. Code to fetch data from the ledger


func GetLoanApplication(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { fmt.Println("Entering GetLoanApplication")

if len(args) < 1 {
fmt.Println("Invalid number of arguments")
return nil, errors.New("Missing loan application ID") }

var loanApplicationId = args[0]


bytes, err := stub.GetState(loanApplicationId)
if err != nil {
fmt.Println("Could not fetch loan application with id "+loanApplicationId+" from ledger", err)
return nil, err
}
return bytes, nil
}
Note: There is also a way to deal with data using traditional relational data models. For example,
ChaincodeStubInterface has a way to create tables and deal with rows and columns. But this is only a logical
abstraction, and the data will be stored as a key value pair in RocksDB. At the time of this writing, version 1.0 of
Hyperledger Fabric is under development and has deprecated the table data structure. Hence this tutorial doesn't
discuss it in order to minimize the changes a chaincode developer would need to make from v0.6 to v1.0.

Marshal and unmarshal golang structs to JSON strings


As demonstrated in Listing 7 and Listing 8, the stub.PutState and stub.GetState methods deal only with byte arrays.
So it is important to be able to convert regular struct objects being used in the chaincode to JSON strings and vice
versa.

Listing 9 shows how to marshal a struct into a JSON string byte array that can then be stored in the ledger. Line 2
creates an instance of the PersonalInfo object. Line 3 uses the json package to marshal the object into a JSON string
and return the byte array for the same.

The json package can be imported by including "encoding/json" in the import block at the top. This byte array can
then be stored in the ledger using the stub.PutState method demonstrated in Listing 7.

Listing 9. Code to marshal a struct into a JSON string byte array


var personalInfo PersonalInfo
personalInfo = PersonalInfo{"Varun", "Ojha", "dob", "varun@gmail.com", "9999999999"}
bytes, err := json.Marshal (&personalInfo)
if err != nil {
fmt.Println("Could not marshal personal info object", err)
return nil, err
} err = stub.PutState("key", bytes)

Listing 10 shows how to unmarshal a struct from a byte array into a populated struct. Line 1 fetches the
PersonalInfo JSON string bytes from the ledger using the associated key. Line 3 unmarshals the bytes retrieved in
line 1 into the PersonalInfo object referenced by the variable personalInfo.

Now you can access and modify the personalInfo object using the dot notation as shown in line 4.

Listing 10. Code to unmarshal a struct from a byte array into a


populated struct
piBytes, err := stub.GetState("la1") var personalInfo
PersonalInfo
err = json.Unmarshal(piBytes, &personalInfo)
fmt.Println(personalInfo.Firstname)

Implementing access control and permissions


One of the primary differences between Hyperledger and other blockchain fabrics is that it has a secure and
permissioned ledger, which is suitable for implementing enterprise-grade solutions.
Membership services
The Membership services component in the Hyperledger plays a pivotal role in enabling security and permissions
within the blockchain network. It's responsible for issuing Enrollment and Transaction certificates to users in
response to registration and enrollment.

• Enrollment certificate: The certificate authority in the membership services will issue an enrollment certificate
to a user that wants to transact on blockchain as a proof of identity.
• Transaction certificate: The transaction certificate is supposed to be used as a one-time token that is passed
along each invocation request of the chaincode by the invoker/invoking application. The transaction
certificates are mathematically derived from the parent enrollment certificate, and hence a theoretically
unlimited number of transaction certificates can be generated from the parent enrollment certificate. The
transaction certificate can be used to sign and encrypt the transaction data when it is stored in the blockchain.
This ensures that only the user with the transaction certificate or a regulator/auditor etc. who has the parent
certificate can actually view the contents of the transaction once they have been written.
• Attributes: Each transaction certificate can hold a number of user-defined attributes. These can be mentioned
as a part of the registration request to the certificate authority from the client application. Follow-on tutorials
in this series will deal with this in detail from the perspective of developing the client application.

Listing 11 shows how the attributes can be retrieved from the transaction certificate of the caller. As mentioned
earlier, the user or the client application will need to pass in the user’s certificate as a part of each chaincode
invocation request so as to authenticate with the target peer on the blockchain network. The HFC SDK takes care
of passing the certificate as a part of the request automatically.

The Invoke function at line 11 of Listing 11 has been modified to check for the input function name and delegate the
call to the appropriate handler function. In addition, the Invoke function also validates the access and role of the
caller who has sent the CreateLoanApplication invocation request. The Invoke function calls the custom
GetCertAttribute function to retrieve a particular attribute from the transaction certificate of the caller.

The GetCertAttribute function fetches the attribute value by passing in the attribute name on line 3.

Line 15 checks whether the caller has the role of a Bank Admin and can invoke the
CreateLoanApplication function. If the caller does not have the required role, an appropriate error is returned. In
this way, attribute-based access control can be implemented in the chaincode.

The ChaincodeStubInterface has some utility functions that deal with attributes, such as ReadCertAttribute,
VerifyAttribute, and VerifyAttributes. All of these methods rely on the
github.com/hyperledger/fabric/core/chaincode/shim/crypto/attr package to create and use the
AttributeHandlerImpl that handles attributes.

In the version of Hyperledger Fabric that is currently under development (v1.0), these utility functions have been
removed from the ChaincodeStubInterface. Hence in v1.0, the chaincode developer would need to use the
AttributeHandlerImpl directly to work with attributes.

Listing 11. Retrieving attributes from the transaction certificate of the


caller
func GetCertAttribute(stub shim.ChaincodeStubInterface, attributeName string) (string, error) {
fmt.Println("Entering GetCertAttribute") attr, err :=
stub.ReadCertAttribute(attributeName)
if err != nil {
return "", errors.New("Couldn't get attribute " + attributeName + ". Error: " + err.Error())
}
attrString := string(attr) return
attrString, nil }

func (t *SampleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte,


error) {
if function == "CreateLoanApplication" { username, _ :=
GetCertAttribute(stub, "username")
role, _ := GetCertAttribute(stub, "role") if role ==
"Bank_Home_Loan_Admin" { return
CreateLoanApplication(stub, args)
} else {
return nil, errors.New(username + " with role " + role + " does not have access to create a loan
application") }

}
return nil, nil
}

Creating and emitting custom events


The Hyperledger contains an event framework that can be used to publish/subscribe predefined or custom events.
Custom events can be created in the chaincode and emitted at your discretion. For example, an event could be
generated whenever there is any change to the state of the blockchain. These events can be subscribed to and
consumed by the client application by registering an event adapter with the event hub on blockchain. Follow-on
tutorials in this series will show in detail how the client application can subscribe to and consume events produced
via the chaincode using the HFC SDK.
In addition to custom events, some of the predefined internal events that are part of the
Hyperledger are:

• Block events
• Chaincode events
• Rejection events
• Register events

The code in Listing 12 shows how to create and publish a custom event.

Lines 1-4 define a custom event object containing type and description fields.

The CreateLoanApplication function starts on line 6 and has been modified to include the event
creation on successful creation of loan application.

Line 23 creates the instance of the customEvent object and fills in appropriate event details.

Line 24 marshals the event object to a JSON string byte array as explained earlier.

Line 28 sets the custom event. The stub.SetEvent method takes two arguments: the event name and
payload. The client application can subscribe to the same event name/topic to receive events as and
when they are generated by the chaincode.

Listing 12. Creating and publishing a custom event


type customEvent struct {
Type string `json:"type"`
Description string `json:"description"`
}

func CreateLoanApplication(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) { fmt.Println("Entering CreateLoanApplication")

if len(args) < 2 {
fmt.Println("Invalid number of args")
return nil, errors.New("Expected at least two arguments for loan application creation") }

var loanApplicationId = args[0] var


loanApplicationInput = args[1]

err := stub.PutState(loanApplicationId, []byte(loanApplicationInput))


if err != nil {
fmt.Println("Could not save loan application to ledger", err)
return nil, err }

var event = customEvent{"createLoanApplication", "Successfully created loan application with ID " +


loanApplicationId}
eventBytes, err := json.Marshal(&event)
if err != nil {
return nil, err
}
err = stub.SetEvent("evtSender", eventBytes)
if err != nil {
fmt.Println("Could not set event for loan application creation", err)
}

fmt.Println("Successfully saved loan application")


return nil, nil }
Handling logging
Logging can be handled in the chaincode either by using the standard fmt package and print
statements or by using the ChaincodeLogger type in the shim package.

The ChaincodeLogger supports the following log levels:

• CRITICAL
• ERROR
• WARNING
• NOTICE
• INFO
• DEBUG

You can set the logging level in three ways:

• shim.SetChaincodeLoggingLevel(): This method will pick up the logging level specified


in the core.yaml file in the CORE_LOGGING_CHAINCODE set. The core.yaml file
contains all the configuration information required to set up and deploy the
blockchain network.
• shim.SetLoggingLevel(level LoggingLevel): This method will set the logging level at the
shim level.
• ChaincodeLogger.SetLevel(level LoggingLevel): This method will set the logging level
at the individual logger instance level.

Listing 13 shows how to create, configure, and use the ChaincodeLogger.

Listing 13. Creating, configuring, and using the


ChaincodeLogger
func SampleLogging() {
//Different Logging Levels
criticalLevel, _ := shim.LogLevel("CRITICAL") errorLevel, _ :=
shim.LogLevel("ERROR") warningLevel, _ := shim.LogLevel("WARNING")
noticeLevel, _ := shim.LogLevel("NOTICE") infoLevel, _ :=
shim.LogLevel("INFO") debugLevel, _ := shim.LogLevel("DEBUG")

//Logging level at the shim level shim.SetLoggingLevel(infoLevel)

//Create a logger instance myLogger :=


shim.NewLogger("SampleChaincodeLogger")

//Set logging level on logger instance myLogger.SetLevel(infoLevel)

//Check logging level


fmt.Println(myLogger.IsEnabledFor(infoLevel))

//Log statements
myLogger.Info("Info Message")
myLogger.Critical("Critical Message")
myLogger.Warning("Warning Message")
myLogger.Error("Error Message")
myLogger.Notice("Notice Message")
myLogger.Debug("Debug Message") }

FAQs and best practices


While developing blockchain applications with clients, I often answer these questions.

How do I store files (images, audio, video, PDF, etc.) in blockchain?


Both of these approaches work in the current Hyperledger Fabric (v0.6):

• Store all files/objects as base64-encoded strings. The client application would convert the
file/object into a base64-encoded string and send it as an input parameter to a chaincode
function. The chaincode in turn can store it as a byte array in the key/value store.
• Store the actual file/object contents outside of blockchain; for example, in IBM Cloud Object
Storage service. Store only the link/reference/ID of the file/object on blockchain along with the
hash of the file/object. Storing the hash ensures that any tampering with the file/object
outside of blockchain can be detected by concerned parties/entities.

How can I avoid disclosing private business logic/contract details to all peers
in the network?
This question came up in a supply chain scenario where an end consumer of the blockchain solution
was not comfortable sharing private business logic/contract information (such as different
negotiated rates with different vendors) in the smart contract visible to all peers. In v0.6, this
situation can be solved using external system integration.

The solution: The business logic/rules/contract that the peer wants to keep private can be run as
a set of business rules in an external application like a service. The chaincode itself has the ability
to make outbound calls. So the chaincode could make REST API calls, for example, to the business
rules/logic service and fetch the results, thus keeping the logic hidden from the actual chaincode.

It is possible to integrate with systems external to blockchain from within the chaincode. For
example, the chaincode can be used to talk to external databases, APIs, etc. But it is important to
make sure that interaction with these systems does not make the chaincode non-deterministic.

Constraints and concerns

• The business rules service can be modified without knowledge of the remaining peers, since it
is running outside of blockchain. Depending on the type of business interaction among the
different participants in the blockchain network, this could lead to trust issues.

• The business rules service must be available to all peers in the blockchain network who will run
the smart contract/chaincode.
• The solution can lead to chaincode becoming non-deterministic. Chaincode MUST be
deterministic. In a nutshell, if the same function in the chaincode is invoked with the same
parameters by multiple parties, the results should be the same. For example, if you use a
timestamp or a counter in your chaincode functions that are tied to the response, invocations
of the chaincode by multiple peers will lead to different results. This will lead to an inconsistent
ledger state among the different peers in the blockchain network.
Remember that each invocation of the chaincode causes all the peers that are part of the
consensus network to invoke the chaincode on their local copies of the ledger.

Note: In v1.0 of the Hyperledger Fabric that is currently under development, this problem has been
solved organically via changes to the architecture itself.

Conclusion

This tutorial began with the fundamentals of chaincode and then dove into the building blocks and
different APIs available for performing important tasks in the chaincode, such as access control,
data modeling, and event management. Download the consolidated code snippets in the
SampleChaincode.go file.

Part 2 of this series covers test-driven development of chaincode. The final part will show how to
develop Node.js client applications that can talk to the blockchain network and complete the
development story.

Downloadable resources

Description Name Size


Sample chaincode in Go chaincode_sample.go.zip 1.6KB

Welcome to Hyperledger Composer

Hyperledger Composer is an extensive, open development toolset and framework to


make developing blockchain applications easier. Our primary goal is to accelerate
time to value, and make it easier to integrate your blockchain applications with the
existing business systems. You can use Composer to rapidly develop use cases and
deploy a blockchain solution in weeks rather than months. Composer allows you to
model your business network and integrate existing systems and data with your
blockchain applications.

Hyperledger Composer supports the existing Hyperledger Fabric


blockchain infrastructure and runtime, which supports pluggable blockchain
consensus protocols to ensure that transactions are validated according to policy by
the designated business network participants.

Everyday applications can consume the data from business networks, providing end
users with simple and controlled access points.
You can use Hyperledger Composer to quickly model your current business network,
containing your existing assets and the transactions related to them; assets are
tangible or intangible goods, services, or property. As part of your business network
model, you define the transactions which can interact with assets. Business networks
also include the participants who interact with them, each of which can be associated
with a unique identity, across multiple business networks.

How does Hyperledger Composer work in practice?


For an example of a business network in action; a realtor can quickly model their
business network as such:

 Assets: houses and listings


 Participants: buyers and homeowners
 Transactions: buying or selling houses, and creating and closing listings

Participants can have their access to transactions restricted based on their role as
either a buyer, seller, or realtor. The realtor can then create an application to present
buyers and sellers with a simple user interface for viewing open listings and making
offers. This business network could also be integrated with existing inventory system,
adding new houses as assets and removing sold properties. Relevant other parties
can be registered as participants, for example a land registry might interact with a
buyer to transfer ownership of the land.

Where do I go from here?


 To try Hyperledger Composer right away, see the Online Playground
 For an introduction to Composer components and concepts, see Key Concepts
 For an architectural overview of a typical solution built with Composer, see Typical Solution
Architecture

Key Concepts in Hyperledger Composer


Hyperledger Composer is a programming model containing a modeling language,
and a set of APIs to quickly define and deploy business networks and applications
that allow participants to send transactions that exchange assets.

Hyperledger Composer Components


You can experience Hyperledger Composer with our browser-based UI called
Hyperledger Composer Playground. Playground is available as a hosted version (no
install necessary) or a local install (good for editing and testing sample business
networks offline).

Developers who want to use Hyperledger Composer's full application development


capabilities should install the Developer Tools.

Key Concepts in Hyperledger Composer


Blockchain State Storage

All transactions submitted through a business network are stored on the blockchain
ledger, and the current state of assets and participants are stored in the blockchain
state database. The blockchain distributes the ledger and the state database across a
set of peers and ensures that updates to the ledger and state database are consistent
across all peers using a consensus algorithm.

Connection Profiles

Hyperledger Composer uses Connection Profiles to define the system to connect to.
A connection profile is a JSON document the is part of a business network card.
These profiles are usually provded by the creator of the system they refer to and
should be used to create business network cards in order to be able to connect to
that system.

Assets
Assets are tangible or intangible goods, services, or property, and are stored in
registries. Assets can represent almost anything in a business network, for example, a
house for sale, the sale listing, the land registry certificate for that house, and the
insurance documents for that house may all be assets in one or more business
networks.

Assets must have a unique identifier, but other than that, they can contain whatever
properties you define. Assets may be related to other assets or participants.

Participants

Participants are members of a business network. They may own assets and submit
transactions. Participant types are modeled, and like assets, must have an identifier
and can have any other properties as required.

Identities and Business Network cards

Within a business network, participants can be associated with an identity. Business


network cards are a combination of an identity, a connection profile, and metadata.
Business network cards simplify the process of connecting to a business network, and
extend the concept of an identity outside the business network to a 'wallet' of
identities, each associated with a specific business network and connection profile.

Transactions

Transactions are the mechanism by which participants interact with assets. This could
be as simple as a participant placing a bid on a asset in an auction, or an auctioneer
marking an auction closed, automatically transferring ownership of the asset to the
highest bidder.

Queries

Queries are used to return data about the blockchain world-state. Queries are
defined within a business network, and can include variable parameters for simple
customization. By using queries, data can be easily extracted from your blockchain
network. Queries are sent by using the Hyperledger Composer API.

Events

Events are defined in the business network definition in the same way as assets or
participants. Once events have been defined, they can be emitted by transaction
processor functions to indicate to external systems that something of importance has
happened to the ledger. Applications can subscribe to emitted events through
the composer-client API.
Access Control

Business networks may contain a set of access control rules. Access control rules
allow fine-grained control over what participants have access to what assets in the
business network and under what conditions. The access control language is rich
enough to capture sophisticated conditions declaratively, such as "only the owner of
a vehicle can transfer ownership of the vehicle". Externalizing access control from
transaction processor function logic makes it easier to inspect, debug, develop and
maintain.

Historian registry

The historian is a specialised registry which records successful transactions, including


the participants and identities that submitted them. The historian stores transactions
as HistorianRecord assets, which are defined in the Hyperledger Composer system
namespace.

Playground Tutorial
In this step by step tutorial we'll walk through setting up a business network, defining
our assets, participants and transactions, and testing our network by creating some
participants and an asset, and submitting transactions to change the ownership of
the asset from one to another. This tutorial is intended to act as an introduction to
Hyperledger Composer concepts using the online playground environment.

Step One: Open the Hyperledger Composer Playground


Open Composer Playground (note, this link will take you to the web Composer
Playground - you can also follow along in a local version if you've already installed
the development environment).

You should see the My Business Networks screen. The My Business


Networks page shows you a summary of the business networks you can connect to,
and the identities you can use to connect to them. Don't worry about this too much
for the time being, as we're going to create our own network.

Step Two: Creating a new business network


Next, we want to create a new business network from scratch. A business network
has a couple of defining properties; a name, and an optional description. You can
also choose to base a new business network on an existing template, or import your
own template.
1. Click Deploy a new business network under the Web Browser heading to get
started.
2. The new business network needs a name, let's call it tutorial-network .
3. Optionally, you can enter a description for your business network.
4. Next we must select a business network to base ours on, because we want to build
the network from scratch, click empty-business-network.
5. Now that our network is defined, click Deploy.

Step Four: Adding a model file


As you can see, we're in the Define tab right now, this tab is where you create and
edit the files that make up a business network definition, before deploying them and
testing them using the Test tab.

As we selected an empty business network template, we need to define our business


network files. The first step is to add a model file. Model files define the assets,
participants, transactions, and events in our business network.

For more information on our modeling language, check our documentation.

1. Click the Add a file button.


2. Click the Model file and click Add.
3. Delete the lines of code in the model file and replace it with this:

Copy

/**

* My commodity trading network

*/

namespace org.acme.mynetwork

asset Commodity identified by tradingSymbol {

o String tradingSymbol

o String description

o String mainExchange

o Double quantity

--> Trader owner

participant Trader identified by tradeId {


o String tradeId

o String firstName

o String lastName

transaction Trade {

--> Commodity commodity

--> Trader newOwner

This domain model defines a single asset type Commodity and single participant
type Trader and a single transaction type Trade that is used to modify the owner of
a commodity.

Step Five: Adding a transaction processor script file


Now that the domain model has been defined, we can define the transaction logic
for the business network. Composer expresses the logic for a business network using
JavaScript functions. These functions are automatically executed when a transaction
is submitted for processing.

For more information on writing transaction processor functions, check


our documentation.

1. Click the Add a file button.


2. Click the Script file and click Add.
3. Delete the lines of code in the script file and replace it with the following code:

Copy

/**

* Track the trade of a commodity from one trader to another

* @param {org.acme.mynetwork.Trade} trade - the trade to be processed

* @transaction

*/

async function tradeCommodity(trade) {

trade.commodity.owner = trade.newOwner;

let assetRegistry = await getAssetRegistry('org.acme.mynetwork.Commodity');


await assetRegistry.update(trade.commodity);

This function simply changes the owner property on a commodity based on


the newOwner property on an incoming Trade transaction. It then persists the
modified Commodity back into the asset registry, used to store Commodity instances.

Step Six: Access control


Access control files define the access control rules for business networks. Our
network is simple, so the default access control file doesn't need editing. The basic
file gives the current participant networkAdmin full access to business network and
system-level operations.

While you can have multiple model or script files, you can only have one access
control file in any business network.

For more information on access control files, check our documentation.

Step Seven: Deploying the updated business network


Now that we have model, script, and access control files, we need to deploy and test
our business network.

Click Update to deploy the changes to our business network.

Step Nine: Creating participants


The first thing we should add to our business network is two participants.

1. Ensure that you have the Trader tab selected on the left, and click Create New
Participant in the upper right.
2. What you can see is the data structure of a Trader participant. We want some easily
recognizable data, so delete the code that's there and paste the following:

Copy

"$class": "org.acme.mynetwork.Trader",

"tradeId": "TRADER1",

"firstName": "Jenny",
"lastName": "Jones"

3. Click Create New to create the participant.


4. You should be able to see the new Trader participant you've created. We need
another Trader to test our Trade transaction though, so create another Trader, but
this time, use the following data:

Copy

"$class": "org.acme.mynetwork.Trader",

"tradeId": "TRADER2",

"firstName": "Amy",

"lastName": "Williams"

Make sure that both participants exist in the Trader view before moving on!

Step Eleven: Transferring the commodity between the


participants
Now that we have two Traders and a Commodity to trade between them, we can test
our Trade transaction.

Transactions are the basis of all change in a Hyperledger Composer business


network, if you want to experiment with your own after this tutorial, try creating
another business network from the My Business Network screen and using a more
advanced business network template.

To test the Trade transaction:

1. Click the Submit Transaction button on the left.


2. Ensure that the transaction type is Trade.
3. Replace the transaction data with the following, or just change the details:

Copy

"$class": "org.acme.mynetwork.Trade",
"commodity": "resource:org.acme.mynetwork.Commodity#ABC",

"newOwner": "resource:org.acme.mynetwork.Trader#TRADER2"

4. Click Submit.
5. Check that our asset has changed ownership from TRADER1 to TRADER2 , by expanding
the data section for the asset. You should see that the owner is listed
as resource:org.acme.mynetwork.Trader#TRADER2 .
6. To view the full transaction history of our business network, click All Transactions on
the left. Here is a list of each transaction as they were submitted. You can see that
certain actions we performed using the UI, like creating the Trader participants and
the Commodity asset, are recorded as transactions, even though they're not defined
as transactions in our business network model. These transactions are known as
'System Transactions' and are common to all business networks, and defined in the
Hyperledger Composer Runtime.

Developer tutorial for creating a


Hyperledger Composer solution
This tutorial will walk you through building a Hyperledger Composer blockchain
solution from scratch. In the space of a few hours you will be able to go from an idea
for a disruptive blockchain innovation, to executing transactions against a real
Hyperledger Fabric blockchain network and generating/running a sample Angular 2
application that interacts with a blockchain network.

This tutorial gives an overview of the techniques and resources available to apply to
your own use case.

Note: This tutorial was written against the latest Hyperledger Composer build on
Ubuntu Linux running with Hyperledger Fabric v1.1 where referenced below and also
tested for a Mac environment.

Prerequisites
Before beginning this tutorial:

 Set up your development environment


 Install an editor e.g. VSCode or Atom

Step One: Creating a business network structure


The key concept for Hyperledger Composer is the business network definition
(BND). It defines the data model, transaction logic and access control rules for your
blockchain solution. To create a BND, we need to create a suitable project structure
on disk.

The easiest way to get started is to use the Yeoman generator to create a skeleton
business network. This will create a directory containing all of the components of a
business network.

1. Create a skeleton business network using Yeoman. This command will require a
business network name, description, author name, author email address, license
selection and namespace.

Copy

yo hyperledger-composer:businessnetwork

2. Enter tutorial-network for the network name, and desired information for
description, author name, and author email.
3. Select Apache-2.0 as the license.
4. Select org.acme.mynetwork as the namespace.

Step Two: Defining a business network


A business network is made up of assets, participants, transactions, access control
rules, and optionally events and queries. In the skeleton business network created in
the previous steps, there is a model ( .cto ) file which will contain the class definitions
for all assets, participants, and transactions in the business network. The skeleton
business network also contains an access control ( permissions.acl ) document with
basic access control rules, a script ( logic.js ) file containing transaction processor
functions, and a package.json file containing business network metadata.

Modelling assets, participants, and transactions

The first document to update is the model ( .cto ) file. This file is written using
the Hyperledger Composer Modelling Language. The model file contains the
definitions of each class of asset, transaction, participant, and event. It implicitly
extends the Hyperledger Composer System Model described in the modelling
language documentation.

1. Open the org.acme.mynetwork.cto model file.


2. Replace the contents with the following:
Copy

/**

* My commodity trading network

*/

namespace org.acme.mynetwork

asset Commodity identified by tradingSymbol {

o String tradingSymbol

o String description

o String mainExchange

o Double quantity

--> Trader owner

participant Trader identified by tradeId {

o String tradeId

o String firstName

o String lastName

transaction Trade {

--> Commodity commodity

--> Trader newOwner

3. Save your changes to org.acme.mynetwork.cto .

Adding JavaScript transaction logic

In the model file, a Trade transaction was defined, specifying a relationship to an


asset, and a participant. The transaction processor function file contains the
JavaScript logic to execute the transactions defined in the model file.

The Trade transaction is intended to simply accept the identifier of


the Commodity asset which is being traded, and the identifier of the Trader participant
to set as the new owner.
1. Open the logic.js script file.
2. Replace the contents with the following:

Copy

/**

* Track the trade of a commodity from one trader to another

* @param {org.acme.mynetwork.Trade} trade - the trade to be processed

* @transaction

*/

async function tradeCommodity(trade) {

trade.commodity.owner = trade.newOwner;

let assetRegistry = await getAssetRegistry('org.acme.mynetwork.Commodity');

await assetRegistry.update(trade.commodity);

3. Save your changes to logic.js .

Adding access control

1. Create a permissions.acl file in the tutorial-network directory.


2. Add the following access control rules to permissions.acl :

Copy

/**

* Access control rules for tutorial-network

*/

rule Default {

description: "Allow all participants access to all resources"

participant: "ANY"

operation: ALL

resource: "org.acme.mynetwork.*"

action: ALLOW

}
rule SystemACL {

description: "System ACL to permit all access"

participant: "ANY"

operation: ALL

resource: "org.hyperledger.composer.system.**"

action: ALLOW

3. Save your changes to permissions.acl .

Step Three: Generate a business network archive


Now that the business network has been defined, it must be packaged into a
deployable business network archive ( .bna ) file.

1. Using the command line, navigate to the tutorial-network directory.


2. From the tutorial-network directory, run the following command:

Copy

composer archive create -t dir -n .

After the command has run, a business network archive file called tutorial-
network@0.0.1.bna has been created in the tutorial-network directory.

Step Four: Deploying the business network


After creating the .bna file, the business network can be deployed to the instance of
Hyperledger Fabric. Normally, information from the Fabric administrator is required
to create a PeerAdmin identity, with privileges to deploy chaincode to the peer.
However, as part of the development environment installation, a PeerAdmin identity
has been created already.

After the runtime has been installed, a business network can be deployed to the
peer. For best practice, a new identity should be created to administer the business
network after deployment. This identity is referred to as a network admin.

Retrieving the correct credentials


A PeerAdmin business network card with the correct credentials is already created as
part of development environment installation.

Deploying the business network

Deploying a business network to the Hyperledger Fabric requires the Hyperledger


Composer chaincode to be installed on the peer, then the business network archive
( .bna ) must be sent to the peer, and a new participant, identity, and associated card
must be created to be the network administrator. Finally, the network administrator
business network card must be imported for use, and the network can then be
pinged to check it is responding.

1. To install the composer runtime, run the following command:

Copy

composer runtime install --card PeerAdmin@hlfv1 --businessNetworkName tutorial-


network

The composer runtime install command requires a PeerAdmin business network


card (in this case one has been created and imported in advance), and the name of
the business network.

2. To deploy the business network, from the tutorial-network directory, run the
following command:

Copy

composer network start --card PeerAdmin@hlfv1 --networkAdmin admin --


networkAdminEnrollSecret adminpw --archiveFile tutorial-network@0.0.1.bna --file
networkadmin.card

The composer network start command requires a business network card, as well as
the name of the admin identity for the business network, the file path of
the .bna and the name of the file to be created ready to import as a business
network card.

3. To import the network administrator identity as a usable business network card, run
the following command:

Copy

composer card import --file networkadmin.card

The composer card import command requires the filename specified in composer
network start to create a card.
4. To check that the business network has been deployed successfully, run the following
command to ping the network:

Copy

composer network ping --card admin@tutorial-network

The composer network ping command requires a business network card to identify
the network to ping.

Step Five: Generating a REST server


Hyperledger Composer can generate a bespoke REST API based on a business
network. For developing a web application, the REST API provides a useful layer of
language-neutral abstraction.

1. To create the REST API, navigate to the tutorial-network directory and run the
following command:

Copy

composer-rest-server

2. Enter admin@tutorial-network as the card name.


3. Select never use namespaces when asked whether to use namespaces in the
generated API.
4. Select No when asked whether to secure the generated API.
5. Select Yes when asked whether to enable event publication.
6. Select No when asked whether to enable TLS security.

The generated API is connected to the deployed blockchain and business network.

Queries Tutorial using the Composer


Query language and REST APIs
In this tutorial, we will build on the developer tutorial, extending it to demonstrate
queries. The native query language can filter results returned using criteria and can
be invoked in transactions to perform operations, such as updating or removing
assets on result sets.
Queries are defined in a query file ( .qry ) in the parent directory of the business
network definition. Queries contain a WHERE clause, which defines the criteria by
which assets or participants are selected.

This tutorial uses the tutorial-network business network developed and deployed in
the Developer-Tutorial.

Prerequisites
Before beginning this tutorial:

 Complete the development environment installation.


 Complete the developer tutorial.

Step One: Updating the business network


The business network created in the developer tutorial must be updated. The
updated business network contains two events and an additional transactions.

Update the model file

The model file must be updated to contain events and a new transaction.

1. Open the model ( .cto ) file for the tutorial-network .


2. Add the following events and transaction to the model:

Copy

event TradeNotification {

--> Commodity commodity

transaction RemoveHighQuantityCommodities {

event RemoveNotification {

--> Commodity commodity

}
3. Save the changes to your model.

Update transaction logic to use queries and events

Now that the domain model has been updated, we can write the additional business
logic that gets executed when a transaction is submitted for processing. In this
tutorial we have added events and queries to the business logic below.

1. Open the transaction processor function file lib/logic.js .


2. Replace the transaction logic with the following JavaScript:

Copy

/**

* Track the trade of a commodity from one trader to another

* @param {org.acme.mynetwork.Trade} trade - the trade to be processed

* @transaction

*/

async function tradeCommodity(trade) {

// set the new owner of the commodity

trade.commodity.owner = trade.newOwner;

let assetRegistry = await getAssetRegistry('org.acme.mynetwork.Commodity');

// emit a notification that a trade has occurred

let tradeNotification = getFactory().newEvent('org.acme.mynetwork',


'TradeNotification');

tradeNotification.commodity = trade.commodity;

emit(tradeNotification);

// persist the state of the commodity

await assetRegistry.update(trade.commodity);

}
/**

* Remove all high volume commodities

* @param {org.acme.mynetwork.RemoveHighQuantityCommodities} remove - the remove


to be processed

* @transaction

*/

async function removeHighQuantityCommodities(remove) {

let assetRegistry = await getAssetRegistry('org.acme.mynetwork.Commodity');

let results = await query('selectCommoditiesWithHighQuantity');

for (let n = 0; n < results.length; n++) {

let trade = results[n];

// emit a notification that a trade was removed

let removeNotification =
getFactory().newEvent('org.acme.mynetwork','RemoveNotification');

removeNotification.commodity = trade;

emit(removeNotification);

await assetRegistry.remove(trade);

3. Save your changes to logic.js .

The first function tradeCommodity will change the owner property on a commodity
(with a new owner Participant) on an incoming Trade transaction and emit a
Notification event to that effect. It then persists the modified Commodity back into
the asset registry which is used to store Commodity instances.

The second function calls a named query 'selectCommoditiesWithHighQuantity'


(defined in queries.qry ) which will return all Commodity asset records that have a
quantity > 60 ; emit an event ; and remove the Commodity from the AssetRegistry.

Step Two: Create a query definition file


The queries used by the Transaction Processor logic are defined in a file which must
be called queries.qry . Each query entry defines the resources and criteria against
which the query is executed.

1. In the tutorial-network directory, create a new file called queries.qry .


2. Copy and paste the following code into queries.qry :

Copy

/** Sample queries for Commodity Trading business network

*/

query selectCommodities {

description: "Select all commodities"

statement:

SELECT org.acme.mynetwork.Commodity

query selectCommoditiesByExchange {

description: "Select all commodities based on their main exchange"

statement:

SELECT org.acme.mynetwork.Commodity

WHERE (mainExchange==_$exchange)

query selectCommoditiesByOwner {

description: "Select all commodities based on their owner"

statement:

SELECT org.acme.mynetwork.Commodity

WHERE (owner == _$owner)

}
query selectCommoditiesWithHighQuantity {

description: "Select commodities based on quantity"

statement:

SELECT org.acme.mynetwork.Commodity

WHERE (quantity > 60)

3. Save your changes to queries.qry .

Step Three: Regenerate your business network archive


After changing the files in a business network, the business network must be
repackaged as a business network archive ( .bna ) and redeployed to the Hyperledger
Fabric instance.

1. Using the command line, navigate to the tutorial-network directory.


2. Run the following command:

Copy

composer archive create --sourceType dir --sourceName . -a tutorial-


network@0.0.1.bna

Step Four: Deploy the updated business network


definition
We need to deploy the modified network to become the latest edition on the
blockchain! We are using the newly created archive business network archive file to
update the existing deployed business network; this is the same business network
name, that we used during the Developer Tutorial.

1. Switch to the terminal, change directory to the folder containing the tutorial-
network.bna .
2. Run the following command to update the business network:

Copy

composer network update -a tutorial-network@0.0.1.bna -c admin@tutorial-network

3. Run the following command to test that the network is deployed:

Copy
composer network ping -c admin@tutorial-network

Step Five: Regenerate the REST APIs for the updated


Business Network
We will now integrate the newly updated business network with queries added, and
expose the REST APIs for this business network.

1. Using the command line, navigate to the tutorial-network directory.


2. Use the following command to launch the REST server:

Copy

composer-rest-server

3. Enter admin@tutorial-network as the card name.


4. Select never use namespaces when asked whether to use namespaces in the
generated API.
5. Select No when asked whether to secure the generated API.
6. Select Yes when asked whether to enable event publication.
7. Select No when asked whether to enable TLS security.

Step Six: Test the REST APIs and create some data
Open a web browser and navigate to http://localhost:3000/explorer . You should see
the LoopBack API Explorer, allowing you to inspect and test the generated REST API.

We should be able to see that the REST Endpoint called 'Query' has been added and,
upon expanding, reveals the list of REST Query operations defined in the business
network tutorial-network
Before we proceed, we need to create some data, to demonstrate queries
adequately. Using the sample JSON data provided, create 3 Traders (Participants)and
some more Commodities (Assets) using the REST APIs.

1. First, click on 'Trader' in the REST Explorer, then click on the 'POST' method on
/Trader, then scroll down to the Parameter section - create the following Trader
instances, in turn:

Copy

"$class": "org.acme.mynetwork.Trader",

"tradeId": "TRADER1",

"firstName": "Jenny",
"lastName": "Jones"

2. Click 'Try it out' to create the Participant. The 'Response Code' (scroll down) should
be 200 (SUCCESS)
3. Create another trader by copying the following JSON:

Copy

"$class": "org.acme.mynetwork.Trader",

"tradeId": "TRADER2",

"firstName": "Jack",

"lastName": "Sock"

4. Create a third trader by coping the following JSON:

Copy

"$class": "org.acme.mynetwork.Trader",

"tradeId": "TRADER3",

"firstName": "Rainer",

"lastName": "Valens"

5. Now scroll up to the top and click on 'Commodity' object in the REST Explorer.
6. Click on the POST operation and scroll down to the Parameters section: In the same
way as above, create two Commodity Asset records (see below) for owners TRADER1
and TRADER2:

Copy

"$class": "org.acme.mynetwork.Commodity",

"tradingSymbol": "EMA",

"description": "Corn",
"mainExchange": "EURONEXT",

"quantity": 10,

"owner": "resource:org.acme.mynetwork.Trader#TRADER1"

Copy

"$class": "org.acme.mynetwork.Commodity",

"tradingSymbol": "CC",

"description": "Cocoa",

"mainExchange": "ICE",

"quantity": 80,

"owner": "resource:org.acme.mynetwork.Trader#TRADER2"

Step Seven: Perform queries using the commodity


trading REST API explorer
Now that we have some Assets and Participants, we can test out some queries using
the generated Query REST operations.

Perform a simple REST query

Now that we have assets and participants, we can try out some queries.

The simplest REST query we can try out first is our named query selectCommodities .

Expand the 'Query' REST Endpoint and you will see the named queries we defined in
our model.

These queries are now exposed as REST queries and for which a /GET operation is
generated, Note that the description of the query (that we defined in our model
definition) is shown on the right hand side.
1. Expand the selectCommodities query.
2. Click the 'Try it Out' button.

It will return all existing Commodities - there should be 2 assets returned.

Perform Filtered REST Queries

Let's select all Commodities by their Exchange - for example 'EURONEXT' main
exchange.
1. Expand query Endpoint 'selectCommoditiesByExchange' and scroll to the
'Parameters' section.
2. Enter 'EURONEXT' in the 'Exchange' parameter.
3. Click 'Try it Out'.

The results reveal that only those Commodities with an Exchange of 'EURONEXT' are
shown in the response body
Perform Transaction update using results from named Query

Finally, you will recall we had defined a simple query that filters Commodities with a
Quantity greater than 60 in our query file. Queries are very powerful, when used in
transaction functions, as using queries allows transaction logic to set up the set of
assets or participants to perform updates on, or for creating remove actions for
example.

We use the selectCommoditiesWithHighQuantity query in


the removeHighQuantityCommodities transaction. If you execute this /GET operation in
the REST Explorer, you'll see it selects only those assets greater than 60 in quantity.
Now let's use the query to perform a removal of high quantity Commodities.

First check for yourself how many Commodities are present (use the 'Commodity'
/GET operation) and you should see at least two Commodities, one of which (Cocoa)
has a quantity > 60.

Let's check out the actual query, by clicking on the REST


Endpoint /selectCommoditiesWithHighQuantity and click /GET then scroll down to 'Try
it Out' - there should be one Commodity that meets the criteria.
OK. Now let's execute a REST transaction, that uses our 'High Quantity' query
definition to decide which Commodities to remove.

Click on the RemoveHighQuantityCommodities REST Endpoint to reveal the /POST


operation for same.
Click on POST, scroll down to the Parameter section and click 'Try it Out' - note: you
do not have to enter any data in the 'data' section.

Scroll down and you should see a transactionId which represents the 'remove'
invocation (itself a blockchain transaction) inside of the transaction processor
function and which will update the world state - the Response Code should be 200

Finally, let's verify our Commodities status. Return to the 'Commodity' REST
Operations and once again perform a /GET operation....'Try it Out'.
The results should show that the Commodity asset 'Cocoa' has now gone, ie only
those Commodity assets with a quantity <= 60 still remain, ie asset 'Corn' in our
example. The named query fed the transaction update (to remove high quantity
Commodities) and which was executed in business logic.

Congratulations!
Well done, you've now completed this tutorial and we hope you now have a much
better idea of the power of queries in Composer. You can start creating/building
your own queries (or modifying the existing queries and adding associated data to
this business network - note: you would need to re-deploy any query changes) to try
out!

Deploying a Hyperledger Composer


blockchain business network to
Hyperledger Fabric for a single
organization
In the development environment, a simple Hyperledger Fabric network is created for
you ( fabric-dev-servers ), along with all of the Hyperledger Composer configuration
that you need in order to deploy a blockchain business network.

This tutorial will demonstrate the steps that an administrator needs to take in order
to deploy a blockchain business network to an instance of Hyperledger Fabric for a
single organization, including how to generate the necessary Hyperledger Composer
configuration. A subsequent tutorial will demonstrate how to deploy a blockchain
business network to an instance of Hyperledger Fabric for multiple organizations.

During this tutorial, you may wish to refer to the Hyperledger Fabric documentation.

Prerequisites
1. Before you continue, ensure that you have followed the steps in installing a development
environment.

Step One: Starting a Hyperledger Fabric network


In order to follow this tutorial, you must start a Hyperledger Fabric network. You can
use the simple Hyperledger Fabric network provided in the development
environment, or you can use your own Hyperledger Fabric network that you have
built by following the Hyperledger Fabric documentation.

The tutorial will assume that you use the simple Hyperledger Fabric network
provided in the development environment. If you use your own Hyperledger Fabric
network, then you must map between the configuration detailed below and your
own configuration.

1. Start a clean Hyperledger Fabric by running the following commands:

Copy

cd ~/fabric-tools

./stopFabric.sh

./teardownFabric.sh

export FABRIC_VERSION=hlfv11

./downloadFabric.sh

./startFabric.sh

2. Delete any business network cards that may exist in your wallet. It is safe to ignore
any errors that state that the business network cards cannot be found:

Copy

composer card delete -n PeerAdmin@fabric-network

composer card delete -n admin@tutorial-network


If these commands fail, then you have network cards from a previous version and
you will have to delete the file system card store.

Copy

rm -fr ~/.composer

Step Two: Exploring the Hyperledger Fabric network


This step will explore the Hyperledger Fabric network that you have just started, so
that you can understand how it has been configured, and what components it
consists of. You will use all of the information in this section to configure
Hyperledger Composer in subsequent steps.

Configuration files

The simple Hyperledger Fabric network provided in the development environment


has been configured using the Hyperledger Fabric configuration
tools cryptogen and configtxgen .

The configuration for cryptogen is stored in the file:

Copy

~/fabric-tools/fabric-scripts/hlfv11/composer/crypto-config.yaml

The configuration for configtxgen is stored in the file:

Copy

~/fabric-tools/fabric-scripts/hlfv11/composer/configtx.yaml

You can find more information about these configuration tools, what they do, and
how to use them by reading the Hyperledger Fabric documentation.

Organizations

The simple Hyperledger Fabric network is made up of a single organization


called Org1 . The organization uses the domain name org1.example.com . Additionally,
the Membership Services Provider (MSP) for this organization is called Org1MSP . In
this tutorial, you will deploy a blockchain business network that only the
organization Org1 can interact with.

Network components
The Hyperledger Fabric network is made up of several components:

 A single peer node for Org1, named peer0.org1.example.com.


o The request port is 7051.
o The event hub port is 7053.
 A single Certificate Authority (CA) for Org1, named ca.org1.example.com.
o The CA port is 7054.
 A single orderer node, named orderer.example.com.
o The orderer port is 7050.

The Hyperledger Fabric network components are running inside Docker containers.
When running Hyperledger Composer within a Docker container, the names above
(for example, peer0.org1.example.com ) can be used to interact with the Hyperledger
Fabric network.

This tutorial will run Hyperledger Composer commands on the Docker host machine,
rather than from inside the Docker network. This means that the Hyperledger
Composer commands must interact with the Hyperledger Fabric network
using localhost as the host name and the exposed container ports.

Users

The organization Org1 is configured with a user named Admin@org1.example.com . This


user is an administrator. Administrators for an organization have the permission to
install the code for a blockchain business network onto their organization's peers,
and can also have the permission to start the blockchain business network,
depending on configuration. In this tutorial, you will deploy a blockchain business
network by acting as the user Admin@org1.example.com .

The user Admin@org1.example.com has a set of certificates and private key files stored
in the directory:

Copy

~/fabric-tools/fabric-scripts/hlfv11/composer/crypto-
config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

You will use some of these files later on to interact with the Hyperledger Fabric
network.

In addition to the administrator, the CA (Certificate Authority) for Org1 has been
configured with a default user. This default user has an enrollment ID of admin and
an enrollment secret of adminpw . However, this user does not have permission to
deploy a blockchain business network.
Channel

Finally, a channel named composerchannel has been created. The peer


node peer0.org1.example.com has been joined to this channel. You can only deploy
Hyperledger Composer blockchain business networks into existing channels, but you
can create additional channels by following the Hyperledger Fabric documentation.

Step Three: Building a connection profile


A connection profile specifies all of the information required to locate and connect to
the Hyperledger Fabric network, for example the host names and ports of all of the
Hyperledger Fabric network components. In this step, you will create a connection
profile for Hyperledger Composer to use to connect to the Hyperledger Fabric
network.

1. Create a connection profile file called connection.json .


2. Give the connection profile name , version and x-type properties by adding the
following three lines to the top of connection.json :

Copy

"name": "fabric-network",

"x-type": "hlfv1",

"version": "1.0.0",

The name property in a connection profile gives a name to the Hyperledger Fabric
network, so we can reference it later on. In the connection profile you have just
created, the name is fabric-network . You can use any name you like for the
Hyperledger Fabric network.

Hyperledger Composer is designed to be compatible with different types blockchain


networks. Currently, only Hyperledger Fabric v1.x is supported, but you must specify
the type of blockchain network to use. The x-type for Hyperledger Fabric v1.1
is hlfv1 .

The version number is the version of this connection profile format. Currently there is
only 1 version of 1.0.0 .

There is also an optional property x-commitTimeout which can also be specified with
defines how long Hyperledger Composer should wait for a submitted transaction to
be committed to your organization's peer before giving up waiting. The default if not
specified is 300 seconds .

3. We must specify the host names and ports of all of the peer nodes in the
Hyperledger Fabric network. There is only 1 peer and we give it a label
of peer0.org1.example.com .

Copy

"peers": {

"peer0.org1.example.com": {

"url": "grpc://localhost:7051",

"eventUrl": "grpc://localhost:7053"

},

Here, we have specified our single peer node peer0.org1.example.com (using the host
name localhost ), the request port 7051, and the event hub port 7053.

The peers array can contain multiple peer nodes. If you have multiple peer nodes,
you should add them all to the peers object.

4. We must specify the host name and port of the certificate authority (CA) in the
Hyperledger Fabric network that we want to use for enrolling existing users and
registering new users.

Copy

"certificateAuthorities": {

"ca.org1.example.com": {

"url": "http://localhost:7054",

"caName": "ca.org1.example.com"

},

Here we have specified our single CA ca.org1.example.com (using the


hostname localhost ) and the CA port 7054, and we also label this entry as ca-
org1.example.com
5. We must specify the host names and ports of all of the ordering nodes in the
Hyperledger Fabric that we want to connect to.

Copy

"orderers": {

"orderer.example.com": {

"url": "grpc://localhost:7050"

},

Here, we have specified our single orderer node orderer.example.com (using the
hostname localhost ) and the orderer port 7050 and we also label this
as orderer.example.com .

The orderers object can contain multiple orderer nodes. If you have multiple orderer
nodes, you should add them all to the orderers object.

6. We now must specify all the organizations in the network. In this tutorial there is only
1 organization, Org1 .

Copy

"organizations": {

"Org1": {

"mspid": "Org1MSP",

"peers": [

"peer0.org1.example.com"

],

"certificateAuthorities": [

"ca.org1.example.com"

},
Here we are describing the owners of the peers and who their certificate authority is
plus we also declare the MSP id that has been defined for this organisation. In this
tutorial it has been defined as Org1MSP .

7. We must specify the name of an existing channel. We will deploy our blockchain
business network into the channel composerchannel . This is defined in the channels
object.

Copy

"channels": {

"composerchannel": {

"orderers": [

"orderer.example.com"

],

"peers": {

"peer0.org1.example.com": {

"endorsingPeer": true,

"chaincodeQuery": true,

"eventSource": true

},

Here we are defined the channel composerchannel and also the orderers and peers
that are part of that channel. We also specify the roles the peer will perform in this
channel. In this tutorial we have added the single orderer and single peer defined
earlier referenced using their labels. The peer will have the business network installed
so will be a transaction endorser, able to handle chaincode queries and also generate
events. The blockchain business network will be deployed to all of the specified peer
nodes. Once the blockchain business network has been deployed, the specified peer
nodes will be used for querying the blockchain business network, endorsing
transactions, and subscribing to events.

8. The final section this is required is the client section. This is used by client
applications (such as Hyperledger Composer) to know what organization it is
representing when interacting and also some extra optional timeouts.
Copy

"client": {

"organization": "Org1",

"connection": {

"timeout": {

"peer": {

"endorser": "300",

"eventHub": "300",

"eventReg": "300"

},

"orderer": "300"

Here we are specifying that we are in Org1 . The timeouts are used to determine how
long to wait for a response when interacting with a peer or orderer and the values
are specified in seconds. If you don't specify anything then the default is 45 seconds .

1. Save your changes to connection.json . The completed connection profile should


look like the following:

Copy

"name": "fabric-network",

"x-type": "hlfv1",

"version": "1.0.0",

"peers": {

"peer0.org1.example.com": {

"url": "grpc://localhost:7051",

"eventUrl": "grpc://localhost:7053"
}

},

"certificateAuthorities": {

"ca.org1.example.com": {

"url": "http://localhost:7054",

"caName": "ca.org1.example.com"

},

"orderers": {

"orderer.example.com": {

"url": "grpc://localhost:7050"

},

"organizations": {

"Org1": {

"mspid": "Org1MSP",

"peers": [

"peer0.org1.example.com"

],

"certificateAuthorities": [

"ca.org1.example.com"

},

"channels": {

"composerchannel": {

"orderers": [

"orderer.example.com"

],
"peers": {

"peer0.org1.example.com": {

"endorsingPeer": true,

"chaincodeQuery": true,

"eventSource": true

},

"client": {

"organization": "Org1",

"connection": {

"timeout": {

"peer": {

"endorser": "300",

"eventHub": "300",

"eventReg": "300"

},

"orderer": "300"

Step Four: Locating the certificate and private key for the
Hyperledger Fabric administrator
In order to deploy a blockchain business network to this Hyperledger Fabric network,
we must identify ourselves as an administrator with the permissions to perform this
operation. In this step, you locate the files required to identify yourself as an
administrator.
The administrator for our Hyperledger Fabric network is a user
called Admin@org1.example.com . The certificates and private key files for this user are
stored in the directory:

Copy

~/fabric-tools/fabric-scripts/hlfv11/composer/crypto-
config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

You must first locate the certificate file for this user. The certificate is the public part
of the identity. The certificate file can be found in the signcerts subdirectory and is
named Admin@org1.example.com-cert.pem . If you look at the contents of this file, then
you will find a PEM encoded certificate similar to the following:

Copy

-----BEGIN CERTIFICATE-----

MIICGjCCAcCgAwIBAgIRANuOnVN+yd/BGyoX7ioEklQwCgYIKoZIzj0EAwIwczEL

MAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG

cmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh

Lm9yZzEuZXhhbXBsZS5jb20wHhcNMTcwNjI2MTI0OTI2WhcNMjcwNjI0MTI0OTI2

WjBbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN

U2FuIEZyYW5jaXNjbzEfMB0GA1UEAwwWQWRtaW5Ab3JnMS5leGFtcGxlLmNvbTBZ

MBMGByqGSM49AgEGCCqGSM49AwEHA0IABGu8KxBQ1GkxSTMVoLv7NXiYKWj5t6Dh

WRTJBHnLkWV7lRUfYaKAKFadSii5M7Z7ZpwD8NS7IsMdPR6Z4EyGgwKjTTBLMA4G

A1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIBmrZau7BIB9

rRLkwKmqpmSecIaOOr0CF6Mi2J5H4aauMAoGCCqGSM49BAMCA0gAMEUCIQC4sKQ6

CEgqbTYe48az95W9/hnZ+7DI5eSnWUwV9vCd/gIgS5K6omNJydoFoEpaEIwM97uS

XVMHPa0iyC497vdNURA=

-----END CERTIFICATE-----

Next, you must locate the private key file for this user. The private key is used to sign
transactions as this identity. The private key file can be found in
the keystore subdirectory. The name of the private key file is a long hexadecimal
string, with a suffix of _sk , for
example 114aab0e76bf0c78308f89efc4b8c9423e31568da0c340ca187a9b17aa9a4457_sk . The
name will change every time the configuration is generated. If you look at the
contents of this file, then you will find a PEM encoded private key similar to the
following:

Copy

-----BEGIN PRIVATE KEY-----

MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg00IwLLBKoi/9ikb6

ZOAV0S1XeNGWllvlFDeczRKQn2uhRANCAARrvCsQUNRpMUkzFaC7+zV4mClo+beg

4VkUyQR5y5Fle5UVH2GigChWnUoouTO2e2acA/DUuyLDHT0emeBMhoMC

-----END PRIVATE KEY-----

Remember the path to both of these files, or copy them into the same directory as
the connection profile file connection.json that you created in the previous step. You
will need these files in the next step.

Step Five: Creating a business network card for the


Hyperledger Fabric administrator
A business network card contains all of the information required to connect to a
blockchain business network and the underlying Hyperledger Fabric network. This
information includes the connection profile created in step three, and the certificate
and private key for the administrator located in step four.

In this step you will create a business network card for the administrator to use to
deploy the blockchain business network to the Hyperledger Fabric network.

Run the composer card create command to create a business network card. You must
specify the path to all three files that you either created or located in the previous
steps:

Copy

composer card create -p connection.json -u PeerAdmin -c Admin@org1.example.com-


cert.pem -k 114aab0e76bf0c78308f89efc4b8c9423e31568da0c340ca187a9b17aa9a4457_sk -r
PeerAdmin -r ChannelAdmin

A business network card file called PeerAdmin@fabric-network.card will have been


written to the current directory. Let's explore the options that we passed to
the composer card create command.

Copy

-p connection.json
This is the path to the connection profile file that we created in step three.

Copy

-u PeerAdmin

This is a name that we use to refer to the administrator user. Instead of


using Admin@org1.example.com everywhere, which is quite lengthy to type, we have
given a name of PeerAdmin so we can easily refer to this user.

Copy

-c Admin@org1.example.com-cert.pem

This is the path to the certificate file for the user Admin@org1.example.com that we
located in step four.

Copy

-k 114aab0e76bf0c78308f89efc4b8c9423e31568da0c340ca187a9b17aa9a4457_sk

This is the path to the private key file for the user Admin@org1.example.com that we
located in step four.

Copy

-r PeerAdmin -r ChannelAdmin

Here, we specify which roles the user has. This information is required so that
Hyperledger Composer knows which users are able to perform which operations. The
user Admin@org1.example.com is an administrator for the Hyperledger Fabric network,
and has the roles PeerAdmin (ability to install chaincode) and ChannelAdmin (ability to
instantiate chaincode).

Step Six: Importing the business network card for the


Hyperledger Fabric administrator
Hyperledger Composer can only use business network cards that are placed into a
wallet. The wallet is a directory on the file system that contains business network
cards. In this step, you will import the business network card created in step five into
the wallet so that you can use the business network card in subsequent steps.

Run the composer card import command to import the business network card into
the wallet:
Copy

composer card import -f PeerAdmin@fabric-network.card

Let's explore the options that we passed to the composer card import command.

Copy

-f PeerAdmin@fabric-network.card

This is the path to the business network card file that we created in step five.

You can now use this business network card by specifying the
name PeerAdmin@fabric-network . You are now all set to deploy the blockchain
business network to the Hyperledger Fabric network.

We are going to deploy the blockchain business network tutorial-network that is


created by following the Developer Tutorial. If you haven't created a business
network archive (.bna) file by following the developer tutorial, follow steps 1, 2, and 3
of the developer tutorial.

Step Seven: Installing the Hyperledger Composer


runtime onto the Hyperledger Fabric peer nodes
Hyperledger Composer includes a component called the Hyperledger Composer
runtime that provides all of the functionality to host and support a business network
archive, for example data validation, error handling, transaction processor function
execution, and access control. In Hyperledger Fabric terms, the Hyperledger
Composer runtime is a standard chaincode.

In this step, you will install the Hyperledger Composer runtime onto all of the
Hyperledger Fabric peer nodes. In Hyperledger Fabric terms, this is a chaincode
install operation.

Run the composer runtime install command to install the Hyperledger Composer
runtime onto all of the Hyperledger Fabric peer nodes that you specified in the
connection profile file you created in step three:

Copy

composer runtime install -c PeerAdmin@fabric-network -n tutorial-network

Let's explore the options that we passed to the composer runtime install command.

Copy
-c PeerAdmin@fabric-network

This is the name of the business network card that we imported into the wallet in
step six.

Copy

-n tutorial-network

You must install a copy of the Hyperledger Composer runtime for each blockchain
business network, and specify the name of the blockchain business network. Here we
specify the name of the blockchain business network that we are
deploying, tutorial-network .

Step Eight: Starting the blockchain business network


In this step, you will start the blockchain business network. In Hyperledger Fabric
terms, this is a chaincode instantiate operation.

Run the composer network start command to start the blockchain business network:

Copy

composer network start -c PeerAdmin@fabric-network -a tutorial-network.bna -A


admin -S adminpw

Let's explore the options that we passed to the composer network start command.

Copy

-c PeerAdmin@fabric-network

This is the name of the business network card that we imported into the wallet in
step six.

Copy

-a tutorial-network.bna

This is the path to the business network archive that contains the business network
definition for our blockchain business network called tutorial-network .

Copy

-A admin
When a blockchain business network is deployed, you must create at least one
participant who will be a blockchain business network administrator. This participant
is responsible for onboarding other participants into the blockchain business
network. Here, we are specifying that we want to create a single blockchain business
network administrator called admin .

Copy

-S adminpw

This specifies that our blockchain business network administrator admin will use an
enrollment secret of adminpw to request a certificate and private key from the CA
(Certificate Authority). When you specify this option, the name specified for the
business network administrator must be an existing enrollment ID for a user that is
already registered with the CA.

Now that our blockchain business network has been started, we can interact with it
using the business network card file admin@tutorial-network.card that was created.

Step Nine: Importing the business network card for the


business network administrator
Run the composer card import command to import the business network card into
the wallet:

Copy

composer card import -f admin@tutorial-network.card

You can now use this business network card by specifying the name admin@tutorial-
network . You are now all set to interact with the running blockchain business
network!

Step Ten: Testing the connection to the blockchain


business network
Run the composer network ping command to test the connection to the blockchain
business network:

Copy

composer network ping -c admin@tutorial-network


Check that the test result was successful, and there is a single participant listed for
the business network with the name NetworkAdmin .

Conclusion
In this tutorial you have seen how to configure Hyperledger Composer with all of the
information required to connect to a Hyperledger Fabric network, and how to deploy
a blockchain business network to that Hyperledger Fabric network.

If you used the simple Hyperledger Fabric network provided in the development
environment, why not try building your own Hyperledger Fabric network by following
the Hyperledger Fabric documentation and see if you can successfully deploy a
blockchain business network to it?

Deploying a Hyperledger Composer


blockchain business network to
Hyperledger Fabric (multiple
organizations)
This tutorial provides an insight into the process for configuring a blockchain
network, spanning multiple organizations.

It outlines the steps you need configure an Hyperledger Fabric based multi-
organisation blockchain network. The two-organisation blockchain network is based
on a sample network provided by Hyperledger Fabric. Furthermore, it describes the
steps to generate the necessary security artifacts and secure the network in either
organization.

Once the blockchain network is configured, we show how to deploy a business


network (eg. a Commodity trading business network from our sample networks),
which runs in its own chaincode container and which is instantiated on the ledger
shared across both organizations. We then show interactions with the shared ledger
as different participants / identities, as generated by an Identity provider in each
organization.

It is recommended that you first follow the accompanying singie organization tutorial
first ; this tutorial demonstrates how to deploy a blockchain network to an instance
of Hyperledger Fabric for a single organization, and will explain some of the concepts
in more detail.
The {site.data.conrefs.hlf_full}} blockchain network (for two organizations) in this
tutorial is configured using docker containers, with both organizations' fabric
networks, on the same machine - obviously, in the real world, they'll be in separate IP
networks or domains, or secure Cloud environments.

The tutorial has colour-coded steps for convenience, to indicate 'which organization'
should follow a particular step or sequence - or indeed, if steps are needed for both
Orgs.

The first kind of step is for both organizations to follow:

Example Step: A step for Org1 and Org2 to follow


The organization Org1 is represented by Alice, the Green Conga Block:

Example Step: A step for Org1 to follow


The organization Org2 is represented by Bob, the Violet Conga Block:

Example Step: A step for Org2 to follow


You can follow these steps by yourself, or pair with a friend or colleague and follow
the steps together.

Let's get started!

Prerequisites
If you have previously installed the Composer development environment, you will
need to first tear down the Hyperledger Fabric containers provided by the
development environment:

Copy

cd ~/fabric-tools

./stopFabric.sh

./teardownFabric.sh

Next, clone the following GitHub Fabric Samples repository using the command line
(do not use the samples from the Fabric site: as it is missing some changes that are
required for this tutorial)
Copy

git clone -b issue-6978 https://github.com/sstone1/fabric-samples.git

We are using the Building Your First Network Fabric sample network for this multi-
org tutorial. We will refer to this Hyperledger Fabric network as the 'BYFN' (Building
Your First Network) network henceforth. If you choose to split your organisations
across separate physical machines or separate virtual machines running on different
IP networks, it is outside the scope of this particular tutorial.

Step One: Starting a Hyperledger Fabric network


In order to follow this tutorial, you must start up a fresh Hyperledger Fabric network.
This tutorial will assume that you use the Hyperledger Fabric network provided in the
Hyperledger Fabric Building Your First Network tutorial.

1. change directory to fabric-samples

Copy

cd fabric-samples

2. Download the platform binaries, including cryptogen :

Copy

curl -sSL https://goo.gl/6wtTN5 | bash -s 1.1.0

Verify the list of docker images downloaded without issues

3. change directory into first-network sample

Copy

cd first-network

4. Next, start the BYFN network - additional flags (to the byfn.sh script below) must be
specified, as we're using CouchDB as the world state database (different to that
specified on the Fabric BYFN page) - we also want to start a Certificate Authority (CA)
for each organization.
5. Execute the following commands in sequence from the first-network directory:

Copy

./byfn.sh -m generate
./byfn.sh -m up -s couchdb -a

If the command works successfully, the first command will generate Fabric network /
security artifacts(see this link. Following the second command (above), the BYFN
network is started, and verify that you see the following output before proceeding:

Copy

========= All GOOD, BYFN execution completed ===========

_____ _ _ ____

| ____| | \ | | | _ \

| _| | \| | | | | |

| |___ | |\ | | |_| |

|_____| |_| \_| |____/

Next, delete any 'old' business network cards that may exist in your wallet from
previous Fabric environments. It is safe to ignore any errors that state that the
business network cards cannot be found:

Copy

composer card delete -n PeerAdmin@byfn-network-org1

composer card delete -n PeerAdmin@byfn-network-org2

composer card delete -n alice@trade-network

composer card delete -n bob@trade-network

composer card delete -n admin@trade-network

composer card delete -n PeerAdmin@fabric-network

However any other types of failure could indicate you have cards in the card store
which are from an older version of Hyperledger Composer and you will then have to
delete your file system card store in your HOME directory as follows:

Copy

rm -fr $HOME/.composer
Step Two: Exploring the Hyperledger Fabric network
This step will explore the BFYN network configuration and components. The
configuration details are required to complete the subsequent steps.

Organizations

The BYFN network is made up of two organizations: Org1 and Org2 . The
organization Org1 uses the domain name org1.example.com . The Membership
Services Provider (MSP) for Org1 is called Org1MSP . The organization Org2 uses the
domain name org2.example.com . The MSP for Org2 is called Org2MSP . In this tutorial,
you will deploy a blockchain business network that both of the
organizations Org1 and Org2 can interact with.

Network components

The Hyperledger Fabric network is made up of several components:

 Two peer nodes for Org1, named peer0.org1.example.com and peer1.org1.example.com.


o The request port for peer0 is 7051.
o The event hub port for peer0 is 7053.
o The request port for peer1 is 8051.
o The event hub port for peer1 is 8053.
 A single CA (Certificate Authority) for Org1, named ca.org1.example.com.
o The CA port is 7054.
 Two peer nodes for Org2, named peer0.org2.example.com and peer1.org2.example.com.
o The request port for peer0 is 9051.
o The event hub port for peer0 is 9053.
o The request port for peer1 is 10051.
o The event hub port for peer1 is 10053.
 A single CA (Certificate Authority) for Org2, named ca.org2.example.com.
o The CA port is 8054.
 A single orderer node, named orderer.example.com.
o The orderer port is 7050.

These components are running inside Docker containers. When running Hyperledger
Composer within a Docker container, the names above (for
example, peer0.org1.example.com ) can be used to interact with the Hyperledger
Fabric network.

This tutorial will run Hyperledger Composer commands on the Docker host machine,
rather than from inside the Docker network. This means that the Hyperledger
Composer commands must interact with the Hyperledger Fabric network
using localhost as the host name and the exposed container ports.
All of the network components are secured using TLS to encrypt communications.
You will need the Certificate Authority (CA) certificates for all of the network
components in order to connect to those network components. The CA certificates
can be found in the directory containing the byfn.sh script.

CA certificate for the orderer node:

Copy

crypto-
config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt

CA certificate for Org1 :

Copy

crypto-
config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt

CA certificate for Org2 :

Copy

crypto-
config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

You will use these files later on to interact with the Hyperledger Fabric network.

Users

The organization Org1 is configured with a user named Admin@org1.example.com . This


user is an administrator.

The user Admin@org1.example.com has a set of certificates and private key files stored
in the directory:

Copy

crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

The organization Org2 is configured with a user named Admin@org2.example.com . This


user is an administrator.

The user Admin@org2.example.com has a set of certificates and private key files stored
in the directory:

Copy
crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

You will use some of these files later on to interact with the Hyperledger Fabric
network.

In addition to the administrator, the CAs (Certificate Authorities)


for Org1 and Org2 have been configured with a default user. This default user has an
enrolment ID of admin and an enrolment secret of adminpw . However, this user does
not have permission to deploy a blockchain business network.

It is recommended to create a temporary working directory (and subdirectories) to


manage the Composer connection profiles and key/certificate files that we will work
with later on in the tutorial.

Copy

mkdir -p /tmp/composer/org1

mkdir -p /tmp/composer/org2

Channel

A channel named mychannel has been created. All four peer nodes -
peer0.org1.example.com , peer1.org1.example.com , peer0.org2.example.com ,
and peer1.org2.example.com have been joined to this channel.

Connection Profiles

We need a base connection profile that describes this fabric network which can then
be given to alice and bob to customize for their organization.

Copy

"name": "byfn-network",

"x-type": "hlfv1",

"version": "1.0.0",

"channels": {

"mychannel": {

"orderers": [
"orderer.example.com"

],

"peers": {

"peer0.org1.example.com": {

"endorsingPeer": true,

"chaincodeQuery": true,

"eventSource": true

},

"peer1.org1.example.com": {

"endorsingPeer": true,

"chaincodeQuery": true,

"eventSource": true

},

"peer0.org2.example.com": {

"endorsingPeer": true,

"chaincodeQuery": true,

"eventSource": true

},

"peer1.org2.example.com": {

"endorsingPeer": true,

"chaincodeQuery": true,

"eventSource": true

},

"organizations": {

"Org1": {

"mspid": "Org1MSP",
"peers": [

"peer0.org1.example.com",

"peer1.org1.example.com"

],

"certificateAuthorities": [

"ca.org1.example.com"

},

"Org2": {

"mspid": "Org2MSP",

"peers": [

"peer0.org2.example.com",

"peer1.org2.example.com"

],

"certificateAuthorities": [

"ca.org2.example.com"

},

"orderers": {

"orderer.example.com": {

"url": "grpcs://localhost:7050",

"grpcOptions": {

"ssl-target-name-override": "orderer.example.com"

},

"tlsCACerts": {

"pem": "INSERT_ORDERER_CA_CERT"

}
},

"peers": {

"peer0.org1.example.com": {

"url": "grpcs://localhost:7051",

"eventUrl": "grpcs://localhost:7053",

"grpcOptions": {

"ssl-target-name-override": "peer0.org1.example.com"

},

"tlsCACerts": {

"pem": "INSERT_ORG1_CA_CERT"

},

"peer1.org1.example.com": {

"url": "grpcs://localhost:8051",

"eventUrl": "grpcs://localhost:8053",

"grpcOptions": {

"ssl-target-name-override": "peer1.org1.example.com"

},

"tlsCACerts": {

"pem": "INSERT_ORG1_CA_CERT"

},

"peer0.org2.example.com": {

"url": "grpcs://localhost:9051",

"eventUrl": "grpcs://localhost:9053",

"grpcOptions": {

"ssl-target-name-override": "peer0.org2.example.com"

},

"tlsCACerts": {
"pem": "INSERT_ORG2_CA_CERT"

},

"peer1.org2.example.com": {

"url": "grpcs://localhost:10051",

"eventUrl": "grpcs://localhost:10053",

"grpcOptions": {

"ssl-target-name-override": "peer1.org2.example.com"

},

"tlsCACerts": {

"pem": "INSERT_ORG2_CA_CERT"

},

"certificateAuthorities": {

"ca.org1.example.com": {

"url": "https://localhost:7054",

"caName": "ca-org1",

"httpOptions": {

"verify": false

},

"ca.org2.example.com": {

"url": "https://localhost:8054",

"caName": "ca-org2",

"httpOptions": {

"verify": false

}
}

Copy this base file (above) into a new file byfn-network.json under the new
directory /tmp/composer and save it.

Open byfn-network.json and replace all instances of the


text INSERT_ORG1_CA_CERT with the CA certificate for the peer nodes for Org1 : - use
the following command to get the certificate from the .pem file so that it can be
embedded into the above connection profile.

Copy

awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' crypto-


config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
> /tmp/composer/org1/ca-org1.txt

Copy the contents of the file /tmp/composer/org1/ca-org1.txt and replace the


text INSERT_ORG1_CA_CERT in the .json file. It should now look something like this
(must be a single line in the profile file as shown)

Copy

"pem": "-----BEGIN CERTIFICATE-----


\nMIICNTCCAdygAwIBAgIRAMNvmQpnXi7uM19BLdha3MwwCgYIKoZIzj0EAwIwbDEL\nMAkGA1UEBhMCVV
MxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xFDASBgNVBAoTC2V4YW
1wbGUuY29tMRowGAYDVQQDExF0bHNjYS5l\neGFtcGxlLmNvbTAeFw0xNzA2MjYxMjQ5MjZaFw0yNzA2Mj
QxMjQ5MjZaMGwxCzAJ\nBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1TYW4gRn
Jh\nbmNpc2NvMRQwEgYDVQQKEwtleGFtcGxlLmNvbTEaMBgGA1UEAxMRdGxzY2EuZXhh\nbXBsZS5jb20w
WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAASJn3QUVcKCp+s6lSPE\nP5KlWmE9rEG0kpECsAfW28vZQSIg
2Ez+Tp1alA9SYN/5BtL1N6lUUoVhG3lz8uvi\n8zhro18wXTAOBgNVHQ8BAf8EBAMCAaYwDwYDVR0lBAgw
BgYEVR0lADAPBgNVHRMB\nAf8EBTADAQH/MCkGA1UdDgQiBCB7ULYTq3+BQqnzwae1RsnwQgJv/HQ5+je2
xcDr\nka4MHTAKBggqhkjOPQQDAgNHADBEAiB2hLiS8B1g4J5Qbxu15dVWAZTAXX9xPAvm\n4l25e1oS+g
IgBiU/aBwSxY0uambwMB6xtQz0ZE/D4lyTZZcW9SODlOE=\n-----END CERTIFICATE-----\n"

In the same .json file - you need to replace all instances of the
text INSERT_ORG2_CA_CERT with the CA certificate for the peer nodes for Org2 : - use
the following command to convert the .pem file to something that can be embedded
into the above connection profile.

Copy

awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' crypto-


config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
> /tmp/composer/org2/ca-org2.txt

Copy the contents of the file /tmp/composer/org2/ca-org2.txt and replace the text
called INSERT_ORG2_CA_CERT . Once again, all on the same line.
Replace all instances of the text INSERT_ORDERER_CA_CERT with the CA certificate for
the orderer node: use the following command to convert the .pem file to something
that can be embedded into the above connection profile json file.

Copy

awk 'NF {sub(/\r/, ""); printf "%s\\n",$0;}' crypto-


config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt >
/tmp/composer/ca-orderer.txt

Copy the contents of the file /tmp/composer/ca-orderer.txt and replace the


text INSERT_ORDERER_CA_CERT . Once again, all on the same line.

Once done, save this file as /tmp/composer/byfn-network.json .

This connection profile now describes the fabric network setup, all the peers,
orderers and certificate authorities that are part of the network, it defines all the
organizations that are participating in the network and also defines the channel's on
this network. Hyperledger Composer can only interact with a single channel so only
one channel should be defined.

Step Three: Customizing the connection profile for Org1


This is just a case of specifying the organization that alice belongs to, in
a client section with optional timeouts, add the following block into the above
connection profile /tmp/composer/byfn-network.json , between the version property
and just before the channel property - once done, save it as a NEW file
called /tmp/composer/org1/byfn-network-org1.json .

Copy

"client": {

"organization": "Org1",

"connection": {

"timeout": {

"peer": {

"endorser": "300",

"eventHub": "300",

"eventReg": "300"

},
"orderer": "300"

},

So the section of the profile should look like

Copy

...

"version": "1.0.0",

"client": {

"organization": "Org1",

"connection": {

"timeout": {

"peer": {

"endorser": "300",

"eventHub": "300",

"eventReg": "300"

},

"orderer": "300"

},

"channel": {

...

Step Four: Building a connection profile for Org2


Repeat the same process for bob - but this time specify the organization as Org2 and
then save the file as /tmp/composer/byfn-network-org2.json - so the section of the
profile should look like:

Copy
...

"version": "1.0.0",

"client": {

"organization": "Org2",

"connection": {

"timeout": {

"peer": {

"endorser": "300",

"eventHub": "300",

"eventReg": "300"

},

"orderer": "300"

},

"channel": {

...

Step Five: Locating the certificate and private key for the
Hyperledger Fabric administrator for Org1
The administrator for our Hyperledger Fabric Org1 network is a user
called Admin@org1.example.com . The certificates and private key files for this user are
stored in the directory:

Copy

crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

You must first locate the certificate file for this user. The certificate is the public part
of the identity. The certificate file can be found in the signcerts subdirectory and is
named Admin@org1.example.com-cert.pem .

Next, you must locate the private key file for this user. The private key is used to sign
transactions as this identity. The private key file can be found in
the keystore subdirectory. The name of the private key file is a long hexadecimal
string, with a suffix of _sk , for
example: 78f2139bfcfc0edc7ada0801650ed785a11cfcdef3f9c36f3c8ca2ebfa00a59c_sk . The
name will change every time the configuration is generated, hence the wildcard
below.

Remember the path to both of these files - or copy them into the same directory as
the connection profile file /tmp/composer/org1/byfn-network-org1.json that you
created in 'Step Three'. You will need these files in the next steps.

Use the following commands to do this:

Copy

export ORG1=crypto-
config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

cp -p $ORG1/signcerts/A*.pem /tmp/composer/org1

cp -p $ORG1/keystore/*_sk /tmp/composer/org1

Step Six: Locating the certificate and private key for the
Hyperledger Fabric administrator for Org2
The administrator for our Hyperledger Fabric network is a user
called Admin@org2.example.com . The certificates and private key files for this user are
stored in the directory:

Copy

crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

You must first locate the certificate file for this user. The certificate is the public part
of the identity. The certificate file can be found in the signcerts subdirectory and is
named Admin@org2.example.com-cert.pem .

Next, you must locate the private key file for this user. The private key is used to sign
transactions as this identity. The private key file can be found in
the keystore subdirectory. The name of the private key file is a long hexadecimal
string, with a suffix of _sk , for
example d4889cb2a32e167bf7aeced872a214673ee5976b63a94a6a4e61c135ca2f2dbb_sk . The
name will change every time the configuration is generated.
Remember the path to both of these files, or copy them into the same directory as
the connection profile file /tmp/composer/byfn-network-org2.json that you created in
step four. You will need these files in the next steps.

Use the following commands to do this:

Copy

export ORG2=crypto-
config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

cp -p $ORG2/signcerts/A*.pem /tmp/composer/org2

cp -p $ORG2/keystore/*_sk /tmp/composer/org2

Step Seven: Creating business network cards for the


Hyperledger Fabric administrator for Org1
In this step you will create business network cards for the administrator to use to
deploy the blockchain business network to the Hyperledger Fabric network.

Run the composer card create command to create a business network card using the
connection profile for Org1 . You must specify the path to all three files that you
either created or located in the previous steps: (note: the sk file will differ.)

Copy

composer card create -p /tmp/composer/org1/byfn-network-org1.json -u PeerAdmin -c


/tmp/composer/org1/Admin@org1.example.com-cert.pem -k /tmp/composer/org1/*_sk -r
PeerAdmin -r ChannelAdmin -f PeerAdmin@byfn-network-org1.card

If the command works successfully, a business network card file


called PeerAdmin@byfn-network-org1.card will have been written to the current
directory.

Step Eight: Creating business network cards for the


Hyperledger Fabric administrator for Org2
In this step you will create business network cards for the administrator to use to
deploy the blockchain business network to the Hyperledger Fabric network.
Run the composer card create command to create a business network card using the
connection profile for Org2 . You must specify the path to all three files that you
either created or located in the previous steps:

Copy

composer card create -p /tmp/composer/org2/byfn-network-org2.json -u PeerAdmin -c


/tmp/composer/org2/Admin@org2.example.com-cert.pem -k /tmp/composer/org2/*_sk -r
PeerAdmin -r ChannelAdmin -f PeerAdmin@byfn-network-org2.card

If the command works successfully, a business network card file


called PeerAdmin@byfn-network-org2.card will have been written to the current
directory.

Step Nine: Importing the business network cards for the


Hyperledger Fabric administrator for Org1
Run the composer card import command to import the business network card
for Org1 into the wallet:

Copy

composer card import -f PeerAdmin@byfn-network-org1.card --name PeerAdmin@byfn-


network-org1

If the command works successfully, a business network card called PeerAdmin@byfn-


network-org1 will have been imported into the wallet.

Step Ten: Importing the business network cards for the


Hyperledger Fabric administrator for Org2
Run the composer card import command to import the business network card
for Org2 into the wallet:

Copy

composer card import -f PeerAdmin@byfn-network-org2.card --name PeerAdmin@byfn-


network-org2

If the command works successfully, a business network card called PeerAdmin@byfn-


network-org2 will have been imported into the wallet.
Step Eleven: Installing the Hyperledger Composer
runtime onto the Hyperledger Fabric peer nodes for
Org1
Run the composer runtime install command to install the Hyperledger Composer
runtime onto all of the Hyperledger Fabric peer nodes for Org1 that you specified in
the connection profile file you created in 'Step Three':

Copy

composer runtime install -c PeerAdmin@byfn-network-org1 -n trade-network

As you can see from the above, we are using a Composer business network name
called trade-network to test our multi-org environment. You will need a file trade-
network.bna (business network archive, from our sample networks) to do the test. If
you don't have this, just go to https://composer-playground.mybluemix.net/and
deploy the trade-network sample in the online Playground, then 'connect' to the
business network as 'admin', and finally export it to the current directory as trade-
network.bna . (Note: If you are planning on using a different network, such as the
Composer tutorial network tutorial-network as your business network, you would
need to use that name in the runtime install command above and thereafter, as the
business network name in this tutorial).

Step Twelve: Installing the Hyperledger Composer


runtime onto the Hyperledger Fabric peer nodes for
Org2
Run the composer runtime install command to install the Hyperledger Composer
runtime onto all of the Hyperledger Fabric peer nodes for Org2 that you specified in
the connection profile file you created in step four:

Copy

composer runtime install -c PeerAdmin@byfn-network-org2 -n trade-network

Step Thirteen: Defining the endorsement policy for the


business network
A running business network has an endorsement policy, which defines the rules
around which organizations must endorse transactions before they can be
committed to the blockchain. By default, a business network is deployed with an
endorsement policy that states that only one organization has to endorse a
transaction before it can be committed to the blockchain.

In real world blockchain business networks, multiple organizations will want to


ensure that they endorse transactions before they can be committed to the
blockchain, and so the default endorsement policy is not suitable. Instead, you can
specify a custom endorsement policy when you start a business network.

You can find more information on endorsement policies in the Hyperledger Fabric
documentation, in Endorsement policies.

Please note that the endorsement policies used for a business network must be in
the JSON format used by the Hyperledger Fabric Node.js SDK. This is a different
format to the simple endorsement policy format used by the Hyperledger Fabric CLI,
which you will see in the Hyperledger Fabric documentation.

Create an endorsement policy file called /tmp/composer/endorsement-policy.json with


the following contents and save it to disk. You will use this file in later steps, so
remember where you place it!

Copy

"identities": [

"role": {

"name": "member",

"mspId": "Org1MSP"

},

"role": {

"name": "member",

"mspId": "Org2MSP"

}
],

"policy": {

"2-of": [

"signed-by": 0

},

"signed-by": 1

The endorsement policy you have just created states that both Org1 and Org2 must
endorse transactions in the business network before they can be committed to the
blockchain. If Org1 or Org2 do not endorse transactions, or disagree on the result of
a transaction, then the transaction will be rejected by the business network.

Step Fourteen: Understanding and selecting the


business network administrators
When a business network is started, the business network must be configured with a
set of initial participants. These participants will be responsible for bootstrapping the
business network and onboarding other participants into the business network. In
Hyperledger Composer, we call these initial participants the business network
administrators.

In our business network, the organizations Org1 and Org2 have equal rights. Each
organization will provide a business network administrator for the business network,
and those business network administrators will onboard the other participants in
their organizations. The business network administrator for Org1 will be Alice, and
the business network administrator for Org2 will be Bob.

When the business network is started, the certificates (the public part of the identity)
for all of the business network administrators must be passed to the organization
performing the commands to start the business network. After the business network
has been started, all of the business network administrators can use their identities to
interact with the business network.

You can find more information on business network administrators in Deploying


Business Networks.

Step Fifteen: Retrieving business network administrator


certificates for Org1
Run the composer identity request command to retrieve certificates for Alice to use
as the business network administrator for Org1 :

Copy

composer identity request -c PeerAdmin@byfn-network-org1 -u admin -s adminpw -d


alice

The -u admin and the -s adminpw options to this command correspond to the default
user registered with the Hyperledger Fabric CA (Certificate Authority).

The certficates will be placed into a directory called alice in the current working
directory. There are three certificate files created, but only two are important. These
are admin-pub.pem , the certificate (including the public key), and admin-priv.pem , the
private key. Only the admin-pub.pem file is suitable for sharing with other
organizations. The admin-priv.pem file must be kept secret as it can be used to sign
transactions on behalf of the issuing organization.

Step Sixteen: Retrieving business network administrator


certificates for Org2
Run the composer identity request command to retrieve certificates for Bob to use
as the business network administrator for Org2 :

Copy

composer identity request -c PeerAdmin@byfn-network-org2 -u admin -s adminpw -d


bob

The -u admin and the -s adminpw options to this command correspond to the default
user registered with the Hyperledger Fabric CA (Certificate Authority).

The certficates will be placed into a directory called bob in the current working
directory. There are three certificate files created, but only two are important. These
are admin-pub.pem , the certificate (including the public key), and admin-priv.pem , the
private key. Only the admin-pub.pem file is suitable for sharing with other
organizations. The admin-priv.pem file must be kept secret as it can be used to sign
transactions on behalf of the issuing organization.

Step Seventeen: Starting the business network


Run the composer network start command to start the business network.
Only Org1 needs to perform this operation. This command uses
the /tmp/composer/endorsement-policy.json file created in step thirteen, and
the admin-pub.pem files created by both Alice and Bob in step fifteen and step sixteen,
so you must ensure that all of these files are accessible to this command:

Copy

composer network start -c PeerAdmin@byfn-network-org1 -a trade-network.bna -o


endorsementPolicyFile=/tmp/composer/endorsement-policy.json -A alice -C
alice/admin-pub.pem -A bob -C bob/admin-pub.pem

Once this command completes, the business network will have been started. Both
Alice and Bob will be able to access the business network, start to set up the business
network, and onboard other participants from their respective organizations.
However, both Alice and Bob must create new business network cards with the
certificates that they created in the previous steps so that they can access the
business network.

Step Eighteen: Creating a business network card to


access the business network as Org1
Run the composer card create command to create a business network card that Alice,
the business network administrator for Org1 , can use to access the business network:

Copy

composer card create -p /tmp/composer/org1/byfn-network-org1.json -u alice -n


trade-network -c alice/admin-pub.pem -k alice/admin-priv.pem

Run the composer card import command to import the business network card that
you just created:

Copy

composer card import -f alice@trade-network.card


Run the composer network ping command to test the connection to the blockchain
business network:

Copy

composer network ping -c alice@trade-network

If the command completes successfully, then you should see the fully qualified
participant identifier org.hyperledger.composer.system.NetworkAdmin#alice in the
output from the command. You can now use this business network card to interact
with the blockchain business network and onboard other participants in your
organization.

Lets create a participant, issue an identity (mapped to that participant) and create an
asset on the blockchain network as that identity.

Run the composer participant add command below, copying it to the command line
to execute:

Copy

composer participant add -c alice@trade-network -d


'{"$class":"org.acme.trading.Trader","tradeId":"trader1-org1",
"firstName":"Jo","lastName":"Doe"}'

Next create the identity for trader1-org1 with the composer issue identity command
below:

Copy

composer identity issue -c alice@trade-network -f jo.card -u jdoe -a


"resource:org.acme.trading.Trader#trader1-org1"

Import the card and test it

Copy

composer card import -f jo.card

composer network ping -c jdoe@trade-network

Next we will create an asset - From the command line, submit a transaction to create
a Commodity asset, as participant jdoe (or alternatively, if you already have
Composer Playground installed, connect as jdoe@trade-network to trade-network to
create the asset 'EMA' - the JSON snippet is shown below ).
To create the asset using the CLI - copy the transaction submit sequence below - it
creates a Commodity asset for you:

Copy

composer transaction submit --card jdoe@trade-network -d '{"$class":


"org.hyperledger.composer.system.AddAsset","registryType": "Asset","registryId":
"org.acme.trading.Commodity", "targetRegistry" :
"resource:org.hyperledger.composer.system.AssetRegistry#org.acme.trading.Commodity
", "resources": [{"$class": "org.acme.trading.Commodity","tradingSymbol":"EMA",
"description":"Corn commodity","mainExchange":"EURONEXT",
"quantity":"10","owner":"resource:org.acme.trading.Trader#trader1-org1"}]}'

Or alternatively, to create in Playground - copy the following:

Copy

"$class": "org.acme.trading.Commodity",

"tradingSymbol": "EMA",

"description": "Corn commodity",

"mainExchange": "EURONEXT",

"quantity": 10,

"owner": "resource:org.acme.trading.Trader#trader1-org1"

Finally, do a composer network list to confirm the generated artifacts in the business
network:

Copy

composer network list -c jdoe@trade-network

Step Nineteen: Creating a business network card to


access the business network as Org2
Run the composer card create command to create a business network card that Bob,
the business network administrator for Org2 , can use to access the business network:

Copy

composer card create -p /tmp/composer/org2/byfn-network-org2.json -u bob -n trade-


network -c bob/admin-pub.pem -k bob/admin-priv.pem
Run the composer card import command to import the business network card that
you just created:

Copy

composer card import -f bob@trade-network.card

Run the composer network ping command to test the connection to the blockchain
business network:

Copy

composer network ping -c bob@trade-network

If the command completes successfully, then you should see the fully qualified
participant identifier org.hyperledger.composer.system.NetworkAdmin#bob in the output
from the command. Let's onboard another Trader, this time for Org 2:

Once again, create a participant, issue an identity (mapped to that participant) - as


we already have an asset on the blockchain network, we will use a transaction to
change the ownership (from Org1 trader to an Org2 trader):

Run the composer participant add command below, copying it to the command line
to execute:

Copy

composer participant add -c bob@trade-network -d


'{"$class":"org.acme.trading.Trader","tradeId":"trader2-org2",
"firstName":"Dave","lastName":"Lowe"}'

Next create the identity for trader2-org2 with the composer issue identity command
below:

Copy

composer identity issue -c bob@trade-network -f dave.card -u dlowe -a


"resource:org.acme.trading.Trader#trader2-org2"

Import the card and test it

Copy

composer card import -f dave.card

composer network ping -c dlowe@trade-network


Lastly, submit a transaction to change ownership of the Commodity asset created
earlier. We will submit the transaction as the asset owner Jon Doe and transfer it to
trader 'Dave Lowe'. We will then verify the ownership change has occurred as the
Org 2 trader participant mapped to the dlowe identity: Perform the step below.

Copy

composer transaction submit --card jdoe@trade-network -d


'{"$class":"org.acme.trading.Trade","commodity":"resource:org.acme.trading.Commodi
ty#EMA","newOwner":"resource:org.acme.trading.Trader#trader2-org2"}'

Finally, do a composer network list as the Org 2 trader participant to confirm the
change of ownership on the asset:

Copy

composer network list -c dlowe@trade-network

Conclusion
In this tutorial you have seen how to configure a blockchain network based on
Hyperledger Composer in a multi-organizational setup. You've also learned how to
deploy a business network (such as our Commodities trading network) to that
blockchain network and perform some simple transactions as participants in each
organization, using identities that were issued by the Certificate of Authorities in
either organization.

Вам также может понравиться