Module 3: Chaincode and Smart Contracts
3.1 Introduction to Chaincode
What is Chaincode?
Chaincode is Hyperledger Fabric's term for smart contracts. It is a program written in a supported language (Go, Node.js, or Java) that implements a prescribed interface. Chaincode runs in a secured Docker container isolated from the endorsing peer process. It initializes and manages the ledger state through transactions submitted by applications.
Chaincode Definition
In Hyperledger Fabric, chaincode is defined by:
- Code: The actual program that implements the chaincode interface
- Name: A unique identifier for the chaincode
- Version: A version string that allows for chaincode upgrades
- Endorsement Policy: Rules that determine which peers must execute and endorse a transaction
- Private Data Collections: Optional collections for private data
- Initialization Parameters: Optional parameters for chaincode initialization
Chaincode vs. Smart Contracts
While the terms "chaincode" and "smart contract" are often used interchangeably in Hyperledger Fabric, there is a subtle distinction:
- Chaincode: The technical implementation - the program that is deployed to the network
- Smart Contract: The business logic or rules encoded within the chaincode
A single chaincode can implement multiple smart contracts, each representing a different business process or agreement.
Chaincode Execution Environment
Chaincode runs in a secured Docker container, isolated from the peer process. This isolation provides several benefits:
- Security: Prevents chaincode from accessing the peer's file system
- Resource Control: Allows for resource allocation and limitations
- Language Support: Enables support for multiple programming languages
- Versioning: Facilitates running multiple versions simultaneously
- Isolation: Prevents one chaincode from affecting others
The chaincode container is started when a transaction proposal requires its execution and can be kept running for subsequent transactions to improve performance.
Chaincode Lifecycle
The lifecycle of chaincode in Hyperledger Fabric involves several stages, from development to retirement.
Chaincode Lifecycle in Fabric 2.x
Fabric 2.x introduced a new chaincode lifecycle that requires multiple organizations to agree on chaincode parameters before it can be used on a channel. The process includes:
-
Package: Create a chaincode package (.tar.gz file)
bash peer lifecycle chaincode package mycc.tar.gz --path /path/to/chaincode --lang golang --label mycc_1.0 -
Install: Install the chaincode package on peers
bash peer lifecycle chaincode install mycc.tar.gz -
Approve: Organizations approve the chaincode definition
bash peer lifecycle chaincode approveformyorg -o orderer.example.com:7050 --channelID mychannel --name mycc --version 1.0 --package-id mycc_1:hash --sequence 1 --tls --cafile /path/to/orderer/tls/cert -
Commit: Commit the chaincode definition to the channel
bash peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID mychannel --name mycc --version 1.0 --sequence 1 --tls --cafile /path/to/orderer/tls/cert -
Invoke: Interact with the chaincode
bash peer chaincode invoke -o orderer.example.com:7050 --channelID mychannel --name mycc -c '{"function":"initLedger","Args":[]}' --tls --cafile /path/to/orderer/tls/cert
Chaincode Lifecycle Governance
The new lifecycle provides several governance improvements:
- Decentralized Governance: Multiple organizations must approve chaincode parameters
- Explicit Agreement: Organizations explicitly approve chaincode before it's used on a channel
- Simpler Endorsement Policies: Endorsement policies can be specified at the channel level
- Safer Updates: Chaincode can be updated without risk of inconsistent states
- Inspectable Packages: Organizations can inspect chaincode packages before approval
Chaincode Upgrade Process
Upgrading chaincode follows a similar process to the initial deployment, with a few key differences:
- Package the new version of the chaincode
- Install the new package on peers
- Approve the new chaincode definition with an incremented sequence number
- Commit the new chaincode definition to the channel
The upgrade process allows for: - Bug fixes and feature additions - Changes to endorsement policies - Updates to private data collection configurations - Smooth transitions between versions
Chaincode Interface
Chaincode must implement a specific interface to interact with the Hyperledger Fabric network.
Core Chaincode Interface
In Go, the core chaincode interface is defined as:
type Chaincode interface {
Init(stub ChaincodeStubInterface) pb.Response
Invoke(stub ChaincodeStubInterface) pb.Response
}
- Init: Called when the chaincode is instantiated or upgraded
- Invoke: Called when a transaction proposal is submitted to the chaincode
Chaincode Stub Interface
The chaincode stub provides APIs for the chaincode to interact with the ledger:
type ChaincodeStubInterface interface {
// Get state from ledger
GetState(key string) ([]byte, error)
// Put state into ledger
PutState(key string, value []byte) error
// Delete state from ledger
DelState(key string) error
// Get history of a key
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)
// Range query
GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error)
// Rich queries (CouchDB)
GetQueryResult(query string) (StateQueryIteratorInterface, error)
// Invoke another chaincode
InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response
// Get transaction context
GetTxID() string
GetChannelID() string
GetTxTimestamp() (*timestamp.Timestamp, error)
// Private data functions
PutPrivateData(collection, key string, value []byte) error
GetPrivateData(collection, key string) ([]byte, error)
// ... and more
}
Transaction Context
Each chaincode invocation receives a transaction context that includes:
- Transaction ID: A unique identifier for the transaction
- Channel ID: The channel on which the transaction is executed
- Timestamp: The time when the transaction was proposed
- Creator: The identity of the transaction creator
- Proposal: The original transaction proposal
This context provides important metadata for the chaincode execution and can be used for access control, auditing, and business logic.
System Chaincode
Hyperledger Fabric includes several system chaincodes that provide core functionality to the network.
Types of System Chaincode
- Lifecycle System Chaincode (LSCC)
- Manages the lifecycle of user chaincodes
- Handles installation, instantiation, and upgrades
-
Stores chaincode definitions
-
Configuration System Chaincode (CSCC)
- Manages channel configuration
- Handles channel creation and updates
-
Stores channel policies
-
Query System Chaincode (QSCC)
- Provides ledger query functions
- Retrieves blocks and transactions
-
Supports historical queries
-
Endorsement System Chaincode (ESCC)
- Handles transaction endorsement
- Verifies endorsement policy compliance
-
Signs transaction proposals
-
Validation System Chaincode (VSCC)
- Validates transaction endorsements
- Enforces endorsement policies
- Checks for policy compliance before committing
Differences from User Chaincode
System chaincodes differ from user chaincodes in several ways:
- Deployment: Pre-deployed with the peer, not through the chaincode lifecycle
- Execution: Run within the peer process, not in separate containers
- Access: Have privileged access to peer internals
- Visibility: Not directly accessible to external applications
- Upgrades: Updated as part of the peer software, not independently
Understanding the basics of chaincode is essential for developing applications on Hyperledger Fabric. In the next sections, we'll explore chaincode development in different programming languages and dive deeper into state management and advanced concepts.