Hyperledger Fabric 链码的结构

每个链码都需要实现一下 Chaincode 接口

Chaincode接口

type Chaincode interface {
    Init(stub shim.ChaincodeStubInterface) peer.Response
    Invoke(stub shim.ChaincodeStubInterface) peer.Response
}

Init: 当链码实例化或者升级的时候,Init方法会被调用

Invoke: 当链码收到调用(invoke)或者查询的时候,Invoke 会被调用

链码的基本结构

package main

// 引入相应的依赖包
import (
    "fmt"
    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
)

type SimpleChaincode struct {

}

// 链码实例化(instantiate)或 升级(upgrade)时调用 Init 方法
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
    return shim.Success(nil)
}

// 链码收到调用(invoke) 或 查询 (query)时调用 Invoke 方法
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    return shim.Success(nil)
}

// 主函数 ,调用 shim.Start 方法
func main() {
    err := shim.Start(new(SimpleChaincode))

    if( err!= nil) {
        fmt.Printf("Error starting Simple Chaincode is %s \n",err)
    }
}

链码通过 shim.ChaincodeStubInterface提供的方法来读取和修改账本状态。

helloworld

  • 初始化的时候,给 str 赋值 helloworld
  • 查询 str 当前的值
  • 重新设置 str 的值
  • 再次查询 str 的值
package main

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

type Helloworld struct {

}

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

    fmt.Println("helloworld init")
    args := stub.GetStringArgs()
    err := stub.PutState(args[0],[]byte(args[1]))

    if err != nil {
        shim.Error(fmt.Sprintf("helloworld init err %s",err))
    }
    return shim.Success(nil)
}

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

    fn,args := stub.GetFunctionAndParameters()

    var result string
    var err error
    if fn == "set" {
        result,err = set(stub,args)
    } else {
        result,err = get(stub,args)
    }
    if err != nil {
        shim.Error(err.Error())
    }
    return shim.Success([]byte(result))
}

func set (stub shim.ChaincodeStubInterface, args []string) (string,error){

    fmt.Println("helloworld set")

    err := stub.PutState(args[0],[]byte(args[1]))
    if err != nil {
        return "", fmt.Errorf("Failed to set asset: %s", args[0])
    }
    return args[0],nil
}

func get(stub shim.ChaincodeStubInterface, args []string) (string,error){

    value, err := stub.GetState(args[0])

    if err != nil {
        return "", fmt.Errorf("Failed to get asset: %s", args[0])
    }
    if value == nil {
        return "", fmt.Errorf("Asset not found: %s", args[0])
    }

    return string(value),nil
}

func main() {
    err := shim.Start(new(Helloworld))

    if err != nil {
        fmt.Printf("shim start err %s",err)
    }
}

helloworld_test.go

package main

import (
    "fmt"
    "testing"
    "github.com/hyperledger/fabric/core/chaincode/shim"
)

func checkInit(t *testing.T, stub *shim.MockStub, args [][]byte) {
    res := stub.MockInit("1", args)
    if res.Status != shim.OK {
        fmt.Println("Init failed", string(res.Message))
        t.FailNow()
    }
}

func checkQuery(t *testing.T, stub *shim.MockStub, name string) {
    res := stub.MockInvoke("1", [][]byte{[]byte("get"), []byte(name)})
    if res.Status != shim.OK {
        fmt.Println("Query", name, "failed", string(res.Message))
        t.FailNow()
    }
    if res.Payload == nil {
        fmt.Println("Query", name, "failed to get value")
        t.FailNow()
    }

    fmt.Println("Query value", name, "was ", string(res.Payload))

}

func checkInvoke(t *testing.T, stub *shim.MockStub, args [][]byte) {
    res := stub.MockInvoke("1", args)
    if res.Status != shim.OK {
        fmt.Println("Invoke", args, "failed", string(res.Message))
        t.FailNow()
    }
}

func Test_Helloworld(t *testing.T) {

    hello := new(Helloworld)
    stub := shim.NewMockStub("hello", hello)

    checkInit(t, stub, [][]byte{[]byte("str"), []byte("helloworld")})
    checkQuery(t, stub, "str")

    checkInvoke(t, stub, [][]byte{[]byte("set"), []byte("str"), []byte("helloworld-1111")})
    checkQuery(t, stub, "str")
}

通过 go test -v helloworld_test.go helloworld.go 测试相应的方法,运行结果:

=== RUN Test_Helloworld
helloworld init
Query value str was helloworld
helloworld set
Query value str was helloworld-1111
--- PASS: Test_Helloworld (0.00s)
PASS
ok command-line-arguments 0.028s

你可能感兴趣的:(Hyperledger Fabric 链码的结构)