智能合约。我写的智能合约在IDE能正常运行,在管理台不能正常运行
【问题分类】
- bug
- P2P网络相关(包含libp2p,liquid)
- 链账户身份与权限相关(证书问题、public、多签投票问题)
- 核心交易引擎相关(交易池、DAG)
- 共识相关
- 智能合约相关
- 存储相关
- SDK相关
- 长安链CMC工具
- 长安链管理台
- 长安链浏览器
- 长安链合约IDE
- 长安链web签名插件
- 跨链相关
- 轻节点相关
- 隐私计算相关
- 密码学相关
- 环境依赖
- 其他补充:
【问题描述】(请对问题进行描述,方便定位问题)
以下是我写的智能合约,在官方存证合约的基础上改的,新增了一个删除功能,一个查询历史数据的功能
/*
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 (
"chainmaker/pb/protogo"
"chainmaker/sandbox"
"chainmaker/sdk"
"encoding/json"
"fmt"
"log"
"strconv"
)
type FactContract struct {
}
// 存证对象
type Fact struct {
FileHash string
FileName string
Time int
}
// 新建存证对象
func NewFact(fileHash string, fileName string, time int) *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()
case "deltedByFileHash":
return f.DeleteByFileHash()
case "getHistoryByFileHash":
return f.GetHistoryByFileHash()
default:
return sdk.Error("无效方法名,没有找到该方法名")
}
}
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, time)
// 序列化
factBytes, err := json.Marshal(fact)
if err != nil {
return sdk.Error(fmt.Sprintf("传过来的参数序列化失败, 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)
createUser, _ := sdk.Instance.GetSenderRole()
sdk.Instance.Infof("[saveUser] create=" + createUser)
// 返回结果
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 (f *FactContract) DeleteByFileHash() protogo.Response {
// 获取参数
fileHash := string(sdk.Instance.GetArgs()["file_hash"])
// 查询结果
err := sdk.Instance.DelState("fact_bytes", fileHash)
if err != nil {
return sdk.Error("failed to delere get_state")
}
// 返回结果
return sdk.Success(nil)
}
func (f *FactContract) GetHistoryByFileHash() protogo.Response {
// 获取参数
fileHash := string(sdk.Instance.GetArgs()["file_hash"])
// 查询结果
iter, err := sdk.Instance.NewHistoryKvIterForKey("fact_bytes", fileHash)
if err != nil {
return sdk.Error("failed to delere get_state")
}
defer iter.Close()
var keyModifications []*sdk.KeyModification
// 遍历结果
for {
keyModification, err := iter.Next()
if err != nil {
sdk.Instance.Infof("Error iterating: %v", err)
}
if keyModification == nil {
break
}
keyModifications = append(keyModifications, keyModification)
sdk.Instance.Infof("Key: %s, Field: %s, Value: %s, TxId: %s, BlockHeight: %d, IsDelete: %t, Timestamp: %s, \n",
keyModification.Key, keyModification.Field, keyModification.Value, keyModification.TxId, keyModification.BlockHeight, keyModification.IsDelete, keyModification.Timestamp)
}
jsonBytes, err := json.Marshal(keyModifications)
if err != nil {
return sdk.Error(fmt.Sprintf("Error marshaling keyModifications: %v", err))
}
// 返回结果
return sdk.Success(jsonBytes)
}
func main() {
err := sandbox.Start(new(FactContract))
if err != nil {
log.Fatal(err)
}
}
问题如下:
- 1、我在IDE编译运行测试都不报错,但是放在管理平台部署就报错。
- 2、使用save、FindByFileHash,方法不报错、但是使用getHistoryByFileHash方法就会报错
- 3、getHistoryByFileHash这个功能是我自己写的用来查询历史记录的,方法在IDE执行不报错,管理台运行报错
【系统信息】(请填写系统信息,方便定位问题)
- chainmaker-go version * : [v2.3.0]
- OS & version * :
- docker镜像 version:
- 管理台 version: v2.3.2
- 合约IDE version: v2.3.+
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information