Chaincode 实现 shim.ChaincodeStubInterface 接口,有三个方法,分别是:Init、Query 和 Invoke。
链码结构:
链码包头:由于需要编译为可执行文件,所以需要 main 包。
package main
导入包:导入其他库的包,一般这里需要导入两个包 "github.com/hyperledger/fabric/core/chaincode/shim" 和 "github.com/hyperledger/fabric/protos/peer" 其他包,根据实际需要而定。
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
定义类结构,一般不设置,自定义结构需要自己设置
type SimpleChaincode struct {
}
Init方法 ,默认调用方法,进行账本初始化。
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
}
只要在区块链状态上执行任何读取/获取/查询操作,就需要调用 Query 方法。如果尝试在 Query 方法内修改区块链的状态,将会抛出异常。
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface) pb.Response {
}
此方法主要是对区块链做修改操作,但是很多例子中一些用户也在 Invoke 做查询。put, get, del 等操作都在可以在 Invoke 中运行,通过输入的参数,来调用具体的函数。
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
}
例如如下代码片段:
func (s *SmartContract) Invoke(stub shim.ChaincodeStubInterface) sc.Response {
// Retrieve the requested Smart Contract function and arguments
function, args := stub.GetFunctionAndParameters()
// Route to the appropriate handler function to interact with the ledger appropriately
if function == "balanceToken" {
return s.balanceToken(stub, args)
} else if function == "initLedger" {
return s.initLedger(stub)
} else if function == "transferToken" {
return s.transferToken(stub, args)
}
return shim.Error("Invalid Smart Contract function name.")
}
在Invoke 函数中,首先使用 stub.GetFunctionAndParameters() 获取合约函数参数,然后通过不同参数名称,实现调用智能合约不同的函数。
if function == "balanceToken" {
return s.balanceToken(stub, args)
} else if function == "initLedger" {
return s.initLedger(stub)
} else if function == "transferToken" {
return s.transferToken(stub, args)
}
main函数,程序的入口,该函数被用于引导/启动链代码。当对peer节点部署chaincode并实例化时,就会执行 main 函数,一般不做修改,shim.Start(new(SampleChaincode)) 启动链代码并注册到peer 节点。
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
合约函数,用于智能合约具体的代码逻辑,一般首字母小写以作区分,例子如下:
func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
carAsBytes, _ := APIstub.GetState(args[0])
return shim.Success(carAsBytes)
}
本例中实现通过args []string,获取输入参数作为键,获得值的操作。
下一篇将介绍合约接口数据操作方法。希望大家关注我的微信公众号,有疑问可以后台留言。