1.新建并进入链码存储文件夹:mkdir -p $GOPATH/src/sacc && cd $GOPATH/src/sacc
编写智能合约vim saac.go:
package main //go语言主包开始
import ( // 引入库
"fmt" //第一个为自身的库,作为输出显示
"github.com/hyperledger/fabric/core/chaincode/shim" //引入shim接口库,fabric专有
"github.com/hyperledger/fabric/protos/peer" //引入节点数据流库,处理节点的数据
)
// SimpleAsset implements a simple chaincode to manage an asset 定义资产结构
type SimpleAsset struct {
}
// Init is called during chaincode instantiation to initialize any
// data. Note that chaincode upgrade also calls this function to reset
// or to migrate data. 实例化时初始化函数。必须有
func (t *SimpleAsset) Init(stub shim.ChaincodeStubInterface) peer.Response { //调用接口,获得参数
// Get the args from the transaction proposal
args := stub.GetStringArgs() //获得API上传的参数
if len(args) != 2 { //如果参数不为两个报错,通过接口显示错误
return shim.Error("Incorrect arguments. Expecting a key and a value")
}
// Set up any variables or assets here by calling stub.PutState()
// We store the key and the value on the ledger
err := stub.PutState(args[0], []byte(args[1])) //将获得的数据写入账本,同时如果发生错误,则收集发生错误
if err != nil { //如果发生错误就显示错误和参数
return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
}
return shim.Success(nil) //返回成功初始化
}
// Invoke is called per transaction on the chaincode. Each transaction is
// either a 'get' or a 'set' on the asset created by Init function. The Set
// method may create a new asset by specifying a new key-value pair.
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response { //通过接口获取参数
// Extract the function and args from the transaction proposal
fn, args := stub.GetFunctionAndParameters() //通过接口,调用getfunc获取参数函数名,具体参数
var result string
var err error
if fn == "set" { //如果函数名为set,调用set函数,上传参数
result, err = set(stub, args)
} else { // assume 'get' even if fn is nil //否则,调用get函数
result, err = get(stub, args)
}
if err != nil { //如果有错误,则发出错误
return shim.Error(err.Error())
}
// Return the result as success payload
return shim.Success([]byte(result)) //返回调用成功
}
// 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 set(stub shim.ChaincodeStubInterface, args []string) (string, error) { //将2个键值对上传至账本
if len(args) != 2 { //如果参数个数不为2,则报错
return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")
}
err := stub.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 get(stub shim.ChaincodeStubInterface, args []string) (string, error) { //通过接口获得参数
if len(args) != 1 {
return "", fmt.Errorf("Incorrect arguments. Expecting a key")
}
value, err := stub.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() { //主函数,价值结构完整
if err := shim.Start(new(SimpleAsset)); err != nil {
fmt.Printf("Error starting SimpleAsset chaincode: %s", err)
}
}
2.编译智能合约准备:go get -u --tags nopkcs11 github.com/hyperledger/fabric/core/chaincode/shim
go build --tags nopkcs11
进入编译和测试demo: cd chaincode-docker-devmode
在此目录下新建三个终端
同时T1下载镜像:docker-compose -f docker-compose-simple.yaml up
T2进入测试程序容器:docker exec -it chaincode bash
进入合约文件夹:cd sacc
编译智能合约:go build
对等节点运行链码:CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=mycc:0 ./sacc
进入cli容器:docker exec -it cli bash
安装程序:peer chaincode install -p chaincodedev/chaincode/sacc -n mycc -v 0
实例化在通道程序:peer chaincode instantiate -n mycc -v 0 -c '{"Args":["a","10"]}' -C myc
3.测试程序
初始化程序:peer chaincode invoke -n mycc -c '{"Args":["set", "a", "20"]}' -C myc
查询函数peer chaincode query -n mycc -c '{"Args":["query","a"]}' -C myc //query时默认的不进行账本改变的查询