- 本文接续前面文章的内容,进行链码的设计以及单元测试;
- 涉及版本为 fabric 2.4,供1.x版本的写法做对比;
目录
一、需要引入的包
import (
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
二、基本结构
对于Fabric 2.4,需要构造智能合约结构体
type SmartContract struct {
contractapi.Contract
}
三、链码函数示例
1)合约函数实现
func (s *SmartContract) HelloWorld(ctx contractapi.TransactionContextInterface) error {
fmt.Println("Hello, World!")
return nil
}
参数介绍:
- contractapi.TransactionContextInterface —— 交易上下文接口
- 除此之外,在TransactionContextInterface中还可以参考以下但不限于此的实用方法:
[1] 获得调用的函数
- GetArgs() [][]byte 以byte数组的数组的形式获得传入的参数列表
- GetStringArgs() []string 以字符串数组的形式获得传入的参数列表
- GetFunctionAndParameters() (string, []string) 将字符串数组的参数分为两部分,数组第一个字是Function,剩下的都是Parameter
- GetArgsSlice() ([]byte, error) 以byte切片的形式获得参数列表
[2] 增删改查State DB
ChainCode核心的操作就是对State Database的增删改查,对此Fabric接口提供了3个对State DB的操作方法。
- 增改数据 PutState(key string, value []byte) error
- 删除数据DelState(key string) error
- 查询数据GetState(key string) ([]byte, error)
2)主函数 —— 链码实例化
func main() {
chaincode, err := contractapi.NewChaincode(&SmartContract{})
if err != nil {
fmt.Printf("Error creating basic chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting basic chaincode: %s", err.Error())
}
}
四、链码全貌
package main
import (
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
type SmartContract struct {
contractapi.Contract
}
func (s *SmartContract) HelloWorld(ctx contractapi.TransactionContextInterface) error {
fmt.Println("Hello, World!")
return nil
}
func main() {
chaincode, err := contractapi.NewChaincode(&SmartContract{})
if err != nil {
fmt.Printf("Error creating basic chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting basic chaincode: %s", err.Error())
}
}
五、测试代码
package cc__test
import (
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
"github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode"
"github.com/hyperledger/fabric-samples/asset-transfer-basic/chaincode-go/chaincode/mocks"
"github.com/stretchr/testify/require"
"testing"
)
// 交易上下文接口
type transactionContext interface {
contractapi.TransactionContextInterface
}
// 提供链码相关的大量实用方法
type chaincodeStub interface {
shim.ChaincodeStubInterface
}
// 查询迭代器
type stateQueryIterator interface {
shim.StateQueryIteratorInterface
}
// 测试函数
func TestSmartContract_Init(t *testing.T) {
chaincodeStub := &mocks.ChaincodeStub{}
transactionContext := &mocks.TransactionContext{}
transactionContext.GetStubReturns(chaincodeStub)
sysTester := chaincode.SmartContract{}
err := sysTester.InitLedger(transactionContext)
require.NoError(t, err)
}
测试结果
每一个不曾起舞的日子,都是对生命的辜负。