Welcome to the Linux Foundation Forum!

Lab 8 Final Step

At the end of Lab 8 I am prompted to upgrade the chaincode to a version that utilizes the contract API.

If you were initializing a chainode that implements the Fabric contract API (instead of the Fabric
Chaincode Shim API), then you’d need to specify the name of the initialization function to be
called in the chanincode. For example:
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile
$ORDERER_TLS_CA -C allarewelcome -n mychaincode --peerAddresses
'{"function":"initLedger","args":["key0", "value0"]}' --isInit
We leave as an exercise to the reader to upgrade the sacc chaincode one more time, this time specifying that it must be initialized as described above.

Since there is no chaincode provided or reference that utilizes the contract api I am at a loss as to how to complete this lab. This seems like something that is more focused on fabric developer activities rather than fabric administration.

Is there an expectation for the exam that chaincode will have to be modified? Or should it simply be provided by a developer?


  • I was able to resolve this by modifying sacc.go and re-deploying:
    1. Add import "github.com/hyperledger/fabric-contract-api-go/contractapi"
    2. Make SimpleAsset extend/implement contractapi.Contract
    3. Make get/set methods public and methods of SimpleAsset
    4. Accept contractapi.TransactionContextInterface as first argument to Get/Set
    5. Replace calls to stub with ctx.GetStub()
    6. Delete extraneous code

     * Copyright IBM Corp All Rights Reserved
     * SPDX-License-Identifier: Apache-2.0
    package main
    import (
    // SimpleAsset implements a simple chaincode to manage an asset
    type SimpleAsset struct {
    // Set stores the asset (both key and value) on the ledger. If the key exists,
    // it will override the value with the new one
    func (sc *SimpleAsset) Set(ctx contractapi.TransactionContextInterface, args []string) (string, error) {
        if len(args) != 2 {
            return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")
        err := ctx.GetStub().PutState(args[0], []byte(args[1]))
        if err != nil {
            return "", fmt.Errorf("Failed to set asset: %s", args[0])
        return args[1], nil
    // Get returns the value of the specified asset key
    func (sc *SimpleAsset) Get(ctx contractapi.TransactionContextInterface, args []string) (string, error) {
        if len(args) != 1 {
            return "", fmt.Errorf("Incorrect arguments. Expecting a key")
        value, err := ctx.GetStub().GetState(args[0])
        if err != nil {
            return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
        if value == nil {
            return "", fmt.Errorf("Asset not found: %s", args[0])
        return string(value), nil
    // main function starts up the chaincode in the container during instantiate
    func main() {
        simpleAsset := new(SimpleAsset)
        cc, err := contractapi.NewChaincode(simpleAsset)
        if err != nil {
        if err := cc.Start(); err != nil {

    Due to the nature of the peer CLI and the json ctor argument, invoking was a bit difficult, but I finally accomplished that with the following:
    peer chaincode invoke -C allarewelcome -c '{"function":"set","args":["[\"key1\", \"value1\"]"]}' -n sacc --tls --cafile $ORDERER_TLS_CA

  • @brentbrownfield, Great job, this information will help other learners. Bobbi


Upcoming Training