Skip to content

GitLab

  • Projects
  • Groups
  • Snippets
  • Help
    • Loading...
  • Sign in
issue
issue
  • Project overview
    • Project overview
    • Details
    • Activity
    • Releases
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 23
    • Issues 23
    • List
    • Boards
    • Labels
    • Service Desk
    • Milestones
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Members
    • Members
  • Activity
  • Graph
  • Create a new issue
  • Commits
  • Issue Boards
Collapse sidebar

新注册的用户请输入邮箱并保存,随后登录邮箱激活账号。后续可直接使用邮箱登录!

  • chainmaker
  • issueissue
  • Issues
  • #1011

Closed
Open
Opened Mar 07, 2024 by 应攀 邝@aa1234 of 19 tasks completed4/19 tasks

智能合约。我写的智能合约在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. 1、我在IDE编译运行测试都不报错,但是放在管理平台部署就报错。
  2. 2、使用save、FindByFileHash,方法不报错、但是使用getHistoryByFileHash方法就会报错
  3. 3、getHistoryByFileHash这个功能是我自己写的用来查询历史记录的,方法在IDE执行不报错,管理台运行报错

image image

【系统信息】(请填写系统信息,方便定位问题)

  • chainmaker-go version * : [v2.3.0]
  • OS & version * :
  • docker镜像 version:
  • 管理台 version: v2.3.2
  • 合约IDE version: v2.3.+
Edited Mar 07, 2024 by 应攀 邝
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
None
Milestone
None
Assign milestone
Time tracking
None
Due date
None
Reference: chainmaker/issue#1011

Copyright © 2021 ChainMaker Org. All Rights Reserved. 长安链 版权所有。