天天看點

【fabric 3】開發你的第一個chaincode

參考:http://hyperledger-fabric.readthedocs.io/en/latest/chaincode4ade.html

1.編碼

每一個chaincode都需要實作

chaincode interface

Init

Invoke

接口

每一個chaincode都應該有一個main函數

代碼結構如下所示:

package main

import (
    "fmt"
    "strconv"
    "github.com/hyperledger/fabric/core/chaincode/shim"
    peer "github.com/hyperledger/fabric/protos/peer"
)

type MyFirstCC struct {
}

func (t *MyFirstCC) Init(stub shim.ChaincodeStubInterface) peer.Response {
}

func (t *MyFirstCC) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
}

func main() {
}
           

main

函數,負責在

instantiate

時啟動chaincode

func main() {
    err := shim.Start(new(MyFirstCC))
    if err != nil {
        fmt.Printf("error start MyFirstCC")
    }
}
           

Init

函數,在chaincode

instantiation

upgrade

時調用,初始化或者重置資料

func (t *MyFirstCC) Init(stub shim.ChaincodeStubInterface) peer.Response {
    fmt.Println("ex10 Init")
    _, args := stub.GetFunctionAndParameters()

    //set 2 parmas for this chaincode init
    //when instantiation chaincode,should give 2 params
    if len(args) != {
        return shim.Error("Incorrect len of arguments")
    }

    var Aval int
    var A string
    var err error

    A = args]
    Aval, err = strconv.Atoi(args])
    if err != nil {
        return shim.Error("Expecting integer value for asset holding")
    }
    fmt.Printf("Aval = %d\n", Aval)
    //put the data to ledger
    err = stub.PutState(A, []byte(strconv.Itoa(Aval)))

    if err != nil {
        return shim.Error("failed to Create asset")
    }
    return shim.Success(nil)
}
           

Invoke

函數,在交易時調用。我們可以自定義一些函數,當調用時傳遞函數名字和參數即可,例如,在本例中我們自定義

set

get

函數。

set

更新賬本資料,

get

讀取賬本資料

func (t *MyFirstCC) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    fmt.Println("ex10 Invoke")

    fn, args := stub.GetFunctionAndParameters()
    var result string
    var err error
    if fn == "set" {
        result, err = set(stub, args)
    } else if fn == "get" {
        result, err = get(stub, args)
    } else {
        return shim.Error("func not found")
    }

    if err != nil {
        return shim.Error(err.Error())
    }

    return shim.Success([]byte(result))
}

func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
    fmt.Println("ex10 set")
    if len(args) != {
        return "", fmt.Errorf("Incorrect arguments")
    }

    var Aval int
    var A string
    var err error

    A = args]
    Aval, err = strconv.Atoi(args])
    if err != nil {
        return "", fmt.Errorf("Expecting integer value for asset holding")
    }
    fmt.Printf("Aval = %d\n", Aval)
    //update data in ledger
    err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
    if err != nil {
        return "", fmt.Errorf("failed to PutState:%s", args])
    }
    return args], nil
}

func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
    fmt.Println("ex10 get")
    if len(args) != {
        return "", fmt.Errorf("Incorrect arguments")
    }

    var A string
    A = args]
    //read data from ledger
    value, err := stub.GetState(A)
    if err != nil {
        return "", fmt.Errorf("failed to get asset: %s with error:%s", args], err)
    }
    if value == nil {
        return "", fmt.Errorf("asset not found")
    }
    return string(value), nil
}
           

2.測試

  • 将上述代碼整合到一個.go檔案中,在

    github.com/hyperledger/fabric/examples/chaincode/go

    下邊建立一個檔案夾,命名為

    example10

    ,将go檔案放置在本檔案夾下,這樣可以将我們自己寫的chaincode映射到clidocker中
  • 準備環境,可參考【fabric 2】v1.0環境搭建詳細過程第1-3步,

    注意:這個步驟執行一次即可滿足後續測試需要了

  • 啟動docker容器,當你的chaincode有更新時需要執行下面的步驟,以同步到cli中

    docker-compose -f docker-compose-cli.yaml up -d

  • 進入cli容器

    docker exec -it cli bash //建立channel需要先進入cli

  • 建立channel
ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer channel create -o orderer.example.com: -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile $ORDERER_CA
           
  • peer加入channel
  • install chaincode
  • instantiate chaincode
  • 調用chaincode的

    get

    方法
peer chaincode query -C mychannel -n mycc -c '{"Args":["get","a"]}' //查詢餘額不往賬本寫資料,不需要背書,用query即可
           
  • 調用chaincode的

    set

    方法

再次調用chaincode的

get

方法

【fabric 3】開發你的第一個chaincode

3. 可能遇到的問題

有的時候更改了chaincode代碼重新開機docker發現chaincode沒有更新,原因可能是上次建立的chaincode docker image還在,可以通過如下方法解決

【fabric 3】開發你的第一個chaincode
docker rm 23bae5e36c07
           
【fabric 3】開發你的第一個chaincode

至此,問題解決,每次都會更新的

繼續閱讀