Smart Contracts in Hyperledger Fabric: A Practical Go Developer’s Guide
Introduction
This documentation serves as a comprehensive guide, providing a detailed walkthrough of the process involved in creating, compiling, deploying, testing, and updating a smart contract (also referred to as chain code) using the Go programming language within the Hyperledger Fabric framework. Hyperledger Fabric is a powerful, modular, open-source blockchain platform that is specifically designed to support enterprise-grade applications. It offers a flexible and secure environment for the development of decentralized applications (DApps), allowing organizations to build sophisticated solutions that leverage the benefits of distributed ledger technology. This guide is designed to equip you with the essential knowledge and practical steps required to effectively develop, deploy, and manage smart contracts on a Hyperledger Fabric network.

Prerequisites
- Hyperledger Fabric Network: A functional Hyperledger Fabric network is required, whether it is a development network set up using the test network scripts or a more complex custom deployment. Familiarity with the basic network components such as peers, orderers, and channels is essential.
- Go Programming Environment: A properly configured Go programming environment is necessary, including a compatible version of the Go
compiler and the setting of the GOPATH environment variable. Visit the official Go website to download and install the most recent stable Go re-
lease. - Fabric Peer CLI: The Hyperledger Fabric Peer command-line interface(CLI) must be installed and correctly configured. This CLI is the primary
tool for interacting with the Fabric network and is required to deploy and manage smart contracts. - Understanding of Fabric Concepts: A fundamental grasp of key Hyperledger Fabric concepts such as channels, peers, orderers, organizations,
and the chaincode lifecycle is highly recommended. A basic understanding of the transaction flow, endorsement policies, and the role of MSPs is
useful for following the instructions in this document.
Creating a Smart Contract
Hyperledger Fabric’s core application is the smart contract (or chaincode), which defines the business logic and governs asset management and transaction execution on the blockchain ledger. Chaincode in Hyperledger Fabric can be written in Go, Java, or JavaScript, with Go being a preferred choice due to its high performance and concurrency support. Using the github.com/hyperledger/fabric-contract-api-go/contractapi
package simplifies the development process, abstracting away much of the boilerplate code. Below is an example of a basic Go smart contract that manages blockchain assets, which can represent anything from tokens to documents.
package main
import (
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
// SmartContract defines the structure for the asset management chaincode
type SmartContract struct {
contractapi.Contract
}
// CreateAsset function to create an asset
func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, id string, value string) error {
// Save the asset with ID and value to the ledger (world state)
return ctx.GetStub().PutState(id, []byte(value))
}
// ReadAsset function to retrieve an asset's value by its ID
func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, id string) (string, error) {
// Retrieve the asset from the ledger
value, err := ctx.GetStub().GetState(id)
if err != nil {
return "", fmt.Errorf("failed to read from world state: %v", err)
}
return string(value), nil
}
func main() {
// Initialize the chaincode
chaincode, err := contractapi.NewChaincode(new(SmartContract))
if err != nil {
fmt.Printf("Error creating chaincode: %s", err)
return
}
// Start the chaincode
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting chaincode: %s", err)
}
}
This example smart contract features two fundamental functions:
- CreateAsset: This function creates a new asset on the ledger. It accepts an asset id and an associated value as input parameters, and it stores
these as key-value pairs in the ledger’s world state. - ReadAsset: This function retrieves the value of an asset by its id. It queries the ledger’s world state using the provided ID and returns the
corresponding value.
The main function initializes and starts the chaincode, which then becomes a service that runs within the Fabric network, ready to process transactions.
The error handling in this example is kept minimal for simplicity, but in production scenarios, robust error handling with specific error codes and messages is essential for debugging and maintaining the smart contract effectively.
Compiling the Smart Contract
Once the smart contract code is written in Go, the next crucial step is to compile it into an executable binary. This compilation process transforms the human-readable Go code into machine-executable instructions that can be understood and executed by Hyperledger Fabric peer nodes. The process involves setting up Go modules, managing dependencies, and executing the build command to generate the final binary. This ensures that the smart contract can be deployed and run efficiently within the Hyperledger Fabric blockchain network.
Step-by-Step Compilation
- Initialize a new Go module
go mod init <module_name>
This command initializes a new Go module within your project directory. This action will create a ‘go.mod‘ file, which acts as a manifest that
defines the dependencies of your project and their respective versions. Replace with a name representative of your project (e.g.,assetcontract).
- Download and tidy up the dependencies
go mod tidy
The ‘go mod tidy‘ command is instrumental in fetching the necessary dependencies specified in your Go code, such as the fabric-contract-api-go
package. It also removes any unused dependencies and ensures that the module’s dependency list is clean and up to date. This step ensures that
your project compiles correctly by ensuring that all necessary packages are available.
- Build the smart contract:
go build
This crucial step compiles your smart contract Go code into a platform specific executable binary. By default, the binary is generated in the
current directory, named after the module or source file if it is named ‘main.go‘. For production deployments on Hyperledger Fabric, it is crucial
to compile the code for the target architecture on which the peer nodes will execute. If the target peer nodes are running on Linux based platforms
the common strategy is to compile the chaincode using the ‘GOOS=linux‘ environment variable which would look something like this ‘GOOS=linux
go build‘.
- Terminal Output:
$ go mod init assetcontract
$ go mod tidy
$ go build
This series of commands produces the executable binary file of your smart contract in the current directory, which is now ready to be packaged and deployed onto your Fabric network.
Testing the Smart Contract
Once the chaincode is deployed onto the Fabric network, rigorously testing its functionality is paramount. This step ensures that the smart contract is behaving as expected and that transactions are being handled correctly. The Fabric Peer CLI is used to test the smart contract using its invoke and query functions.
- Invoke the CreateAsset function to create an asset
peer chaincode invoke -o <orderer_address:port> --channelID mychannel \
--name mychaincode -c ’{"Args":["CreateAsset","asset1","100"]}’
This command sends a transaction to the Fabric network that executes the CreateAsset function of the deployed smart contract. In this specific
example, an asset with the ID of asset1 and a value of 100 is created in the ledger. For this command, replace with the address and port of your orderer node. After the command has been executed, a successful transaction will mean that the state of the chain has been changed and asset1 is now present on the chain.
- Query the ReadAsset function to read the asset’s value
peer chaincode query -o <orderer_address:port> --channelID mychannel \
--name mychaincode -c ’{"Args":["ReadAsset","asset1"]}’
This query command is used to read the value of asset1 from the Fabric network’s ledger by calling the ReadAsset function. The query does not
change the state of the ledger.
- Terminal Output:
Invoke result: asset1 created successfully
Query result: 100
The output above confirms that the asset asset1 was successfully created and that its value is indeed 100. This implies that the chaincode is operational and its basic read and write functionalities are correct.
Updating the Smart Contract
Smart contracts, like any software, may require updates to add new features, fix bugs, or adjust existing functionalities. Updating smart contracts on a
blockchain platform requires care, as it must maintain the integrity and continuity of the ledger. Here’s how to update a chaincode:
- Modify the smart contract Go file: Update the smart contract’s Go code by adding new logic, modifying existing functions, or applying fixes.
- Rebuild and package the updated chaincode: After you modify the code, rebuild and repackage it with a new version label, which will allow the chaincode to be identified on the Fabric network.
peer lifecycle chaincode package mychaincode_v2.tar.gz \
--path ./ \
--lang golang \
--label mychaincode_2
Terminal Output
Successfully created chaincode package: mychaincode_v2.tar.gz
- Install, approve, and commit the updated chaincode: Install the chaincode package and approve it with the new version information. The sequence must be incremented, and a new package-id must be used.
peer lifecycle chaincode install mychaincode_v2.tar.gz
peer lifecycle chaincode approveformyorg --channelID mychannel \
--name mychaincode --version 2.0 --package-id <package_id_v2> --sequence 2
peer lifecycle chaincode commit --channelID mychannel \
--name mychaincode --version 2.0 --sequence 2
Terminal Output
Successfully approved updated chaincode definition for mychannel
Successfully committed updated chaincode definition for mychannel
A crucial point to understand is that the sequence number must be incremented during each update. For this example, we have updated the version from 1.0 to 2.0 and therefore we must increment the sequence from 1 to 2. Failing to do so will result in the chaincode not being updated on the channel. Updating smart contracts in a production environment requires careful planning, including migration strategies for existing data, and testing of the new version before full deployment.
Conclusion
This guide has provided a detailed overview of the essential steps required for creating, compiling, deploying, testing, and updating a smart contract using Go in Hyperledger Fabric. This thorough process, when executed correctly, establishes a strong foundation for developing complex blockchain applications that use smart contracts to enforce business rules and automate logic within a decentralized network. By following the steps outlined in this guide, developers are well-equipped to build robust, secure, and scalable blockchain solutions. This comprehensive knowledge now allows you to progress towards creating increasingly intricate decentralized systems that take full advantage of the smart contract capabilities offered within the Hyperledger Fabric framework.