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 18
    • Issues 18
    • 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
  • #1458

Closed
Open
Opened Sep 05, 2025 by jieke@13992732469🎨

SDK 内部的 GlobalStateStore 为 nil,导致调用 PutStateByte 时空指针访问,代码检查没有问题

使用SmartEditor编写的go合约部署成功后,在合约容器中执行时,出现: ChainMaker Sandbox/VM 中运行时触发 nil pointer panic,原因为SDK 内部的 GlobalStateStore 为 nil,导致调用 PutStateByte 时空指针访问。 go合约代码如下: package main

import ( "encoding/json" "fmt" "log" "strconv"

"chainmaker/pb/protogo"
"chainmaker/sandbox"
"chainmaker/sdk"

)

// 合约主结构 type FactContract struct { }

// 存证对象:用户信息 type Fact struct { ID string Username string Sex string Age int }

// 新建存证对象 func NewFact(id, username, sex string, age int) *Fact { return &Fact{ ID: id, Username: username, Sex: sex, Age: age, } }

// 初始化合约 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 "findByID": return f.FindByID() default: return sdk.Error("invalid method") } }

// 保存存证对象 func (f *FactContract) Save() protogo.Response { sdkInstance := sdk.Instance if sdkInstance == nil { return sdk.Error("SDK instance is nil") }

params := sdkInstance.GetArgs()
if params == nil {
	return sdk.Error("transaction args are nil")
}

// 参数检查
idBytes, ok := params["id"]
if !ok || len(idBytes) == 0 {
	return sdk.Error("missing 'id' argument")
}
usernameBytes, ok := params["username"]
if !ok || len(usernameBytes) == 0 {
	return sdk.Error("missing 'username' argument")
}
sexBytes, ok := params["sex"]
if !ok {
	sexBytes = []byte("")
}
ageBytes, ok := params["age"]
if !ok || len(ageBytes) == 0 {
	return sdk.Error("missing 'age' argument")
}

id := string(idBytes)
username := string(usernameBytes)
sex := string(sexBytes)
age, err := strconv.Atoi(string(ageBytes))
if err != nil {
	msg := fmt.Sprintf("age is [%s] not int", string(ageBytes))
	sdkInstance.Errorf(msg)
	return sdk.Error(msg)
}

// 构建 Fact 对象
fact := NewFact(id, username, sex, age)

// 序列化
factBytes, err := json.Marshal(fact)
if err != nil {
	return sdk.Error(fmt.Sprintf("marshal fact failed, err: %s", err))
}

// 发送事件
sdkInstance.EmitEvent("user_event", []string{fact.ID, fact.Username})

// 存储状态
err = sdkInstance.PutStateByte("fact_bytes", fact.ID, factBytes)
if err != nil {
	return sdk.Error(fmt.Sprintf("fail to save fact bytes, err: %s", err))
}

// 日志记录
sdkInstance.Infof("[save] id=%s, username=%s", fact.ID, fact.Username)

return sdk.Success([]byte(fmt.Sprintf("save success, id=%s", fact.ID)))

}

// 根据 ID 查询存证对象 func (f *FactContract) FindByID() protogo.Response { sdkInstance := sdk.Instance if sdkInstance == nil { return sdk.Error("SDK instance is nil") }

params := sdkInstance.GetArgs()
if params == nil {
	return sdk.Error("transaction args are nil")
}

idBytes, ok := params["id"]
if !ok || len(idBytes) == 0 {
	return sdk.Error("missing 'id' argument")
}
id := string(idBytes)

// 查询存储的数据
result, err := sdkInstance.GetStateByte("fact_bytes", id)
if err != nil {
	return sdk.Error(fmt.Sprintf("failed to call GetStateByte, err: %s", err))
}
if result == nil {
	return sdk.Error("no record found for id: " + id)
}

// 反序列化
var fact Fact
if err = json.Unmarshal(result, &fact); err != nil {
	return sdk.Error(fmt.Sprintf("unmarshal fact failed, err: %s", err))
}

// 日志记录
sdkInstance.Infof("[find_by_id] id=%s, username=%s", fact.ID, fact.Username)

return sdk.Success(result)

}

// 合约入口 func main() { err := sandbox.Start(new(FactContract)) if err != nil { log.Fatal(err) } }

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#1458

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