2.2.2. 编写合约注意事项
main
长安链提供golang合约与链交互的相关接口,写合约时可直接导入包,并进行引用,具体信息可参考文章末尾”接口描述章节”。
当合约编写完成后,则需要编译合约,具体教程如下
需要保证是在Linux环境下编译,在此文件夹的当前路径执行如下编译命令:
# 如果需要在其他系统环境下编译合约,请参考Golang的交叉编译修改go build命令。
go build -ldflags="-s -w" -o file_name
7z a file_name file_name
在编译合约时,首先使用golang编译程序。
编译后使用7zip对编译好的可执行文件进行压缩。
编译结果输出与使用脚本编译一致。
编译完成后,将得到一个.7z
格式的合约文件,可将之部署到指定到长安链上,完成合约部署。 部署合约的使用教程可详见:部署示例合约。
ChainMaker官方提供了通过go.mod引用合约SDK进行合约开发的示例合约工程。
以存证合约为例,可以直接下载下编译存证合约,过程如下:
$ git clone https://git.chainmaker.org.cn/contracts/contracts-go.git
$ cd contracts-go/fact
$ ./build.sh fact
...
更多合约示例可以直接查看仓库contracts-go
/*
Copyright (C) BABEC. All rights reserved.
Copyright (C) THL A29 Limited, a Tencent company. All rights reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"encoding/json"
"fmt"
"log"
"strconv"
"chainmaker.org/chainmaker/contract-sdk-go/v2/pb/protogo"
"chainmaker.org/chainmaker/contract-sdk-go/v2/sandbox"
"chainmaker.org/chainmaker/contract-sdk-go/v2/sdk"
)
type FactContract struct {
}
// 存证对象
type Fact struct {
FileHash string `json:"fileHash"`
FileName string `json:"fileName"`
Time int32 `json:"time"`
}
// 新建存证对象
func NewFact(fileHash string, fileName string, time int32) *Fact {
fact := &Fact{
FileHash: fileHash,
FileName: fileName,
Time: time,
}
return fact
}
func (f *FactContract) InitContract() protogo.Response {
return sdk.Success([]byte("Init contract success"))
}
func (f *FactContract) UpgradeContract() protogo.Response {
return sdk.Success([]byte("Upgrade contract success"))
}
func (f *FactContract) InvokeContract(method string) protogo.Response {
switch method {
case "save":
return f.save()
case "findByFileHash":
return f.findByFileHash()
default:
return sdk.Error("invalid method")
}
}
func (f *FactContract) save() protogo.Response {
params := sdk.Instance.GetArgs()
// 获取参数
fileHash := string(params["file_hash"])
fileName := string(params["file_name"])
timeStr := string(params["time"])
time, err := strconv.Atoi(timeStr)
if err != nil {
msg := "time is [" + timeStr + "] not int"
sdk.Instance.Errorf(msg)
return sdk.Error(msg)
}
// 构建结构体
fact := NewFact(fileHash, fileName, int32(time))
// 序列化
factBytes, err := json.Marshal(fact)
if err != nil {
return sdk.Error(fmt.Sprintf("marshal fact failed, err: %s", err))
}
// 发送事件
sdk.Instance.EmitEvent("topic_vx", []string{fact.FileHash, fact.FileName})
// 存储数据
err = sdk.Instance.PutStateByte("fact_bytes", fact.FileHash, factBytes)
if err != nil {
return sdk.Error("fail to save fact bytes")
}
// 记录日志
sdk.Instance.Infof("[save] fileHash=" + fact.FileHash)
sdk.Instance.Infof("[save] fileName=" + fact.FileName)
// 返回结果
return sdk.Success([]byte(fact.FileName + fact.FileHash))
}
func (f *FactContract) findByFileHash() protogo.Response {
// 获取参数
fileHash := string(sdk.Instance.GetArgs()["file_hash"])
// 查询结果
result, err := sdk.Instance.GetStateByte("fact_bytes", fileHash)
if err != nil {
return sdk.Error("failed to call get_state")
}
// 反序列化
var fact Fact
if err = json.Unmarshal(result, &fact); err != nil {
return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))
}
// 记录日志
sdk.Instance.Infof("[find_by_file_hash] fileHash=" + fact.FileHash)
sdk.Instance.Infof("[find_by_file_hash] fileName=" + fact.FileName)
// 返回结果
return sdk.Success(result)
}
func main() {
err := sandbox.Start(new(FactContract))
if err != nil {
log.Fatal(err)
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。