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:

  1. 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

  2. Install: Install the chaincode package on peers bash peer lifecycle chaincode install mycc.tar.gz

  3. 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

  4. 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

  5. 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:

  1. Package the new version of the chaincode
  2. Install the new package on peers
  3. Approve the new chaincode definition with an incremented sequence number
  4. 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

  1. Lifecycle System Chaincode (LSCC)
  2. Manages the lifecycle of user chaincodes
  3. Handles installation, instantiation, and upgrades
  4. Stores chaincode definitions

  5. Configuration System Chaincode (CSCC)

  6. Manages channel configuration
  7. Handles channel creation and updates
  8. Stores channel policies

  9. Query System Chaincode (QSCC)

  10. Provides ledger query functions
  11. Retrieves blocks and transactions
  12. Supports historical queries

  13. Endorsement System Chaincode (ESCC)

  14. Handles transaction endorsement
  15. Verifies endorsement policy compliance
  16. Signs transaction proposals

  17. Validation System Chaincode (VSCC)

  18. Validates transaction endorsements
  19. Enforces endorsement policies
  20. 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.