首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >波场链/币安链/马蹄链DAPP智能合约系统开发详细分析及代码部署

波场链/币安链/马蹄链DAPP智能合约系统开发详细分析及代码部署

原创
作者头像
VX_I357O98O7I8
发布2022-12-15 17:11:23
4770
发布2022-12-15 17:11:23
举报
文章被收录于专栏:商业模式策划商业模式策划

3.3. 使用 SDK写一个简单合约

下面我们将写一个合约,合约的功能是保存和查询用户的年龄信息,合约的名字叫 age_contract。合约有两个方法:

第一个方法 saveAge:保存年龄信息。接收两个参数:姓名 name 和年龄 age,把姓名和年龄保存到链上,成功返回成功信息,失败返回错误信息。

第二个方法 getAge:查询年龄信息。接收一个参数 name ,如果链上存在用户的年龄信息则返回,如果不存在则返回 -1

编写合约的步骤如下:

  1. 创建合约。在 文件目录的 workspace上点击鼠标右键,选择创建合约工程,输入合约名字 age_contract,然后点击创建,此时在文件目录会有一个合约工程 age_contract
  2. 第二步创建合约文件。在 age_contract 上点击鼠标右键,选择创建文件,输入 main.go。然后点击创建,此时在 arg_contract 目录会有一个 main.go 文件。
  3. 开始编写合约。打开 main.go, 复制下面代码到代码编辑区。保存代码 (CTRL+s),保存时合约IDE会自动生成 go.modgo.sum 文件。 package main import ( "chainmaker/pb/protogo" "chainmaker/shim" ) // AgeContract save and get age type AgeContract struct { } // InitContract 合约初始化方法,会在合约部署到链上时执行 func (ac *AgeContract) InitContract(stub shim.CMStubInterface) protogo.Response { return shim.Success([]byte("Init Success")) } // InvokeContract 调用合约,在链上执行合约时,实际调用的是这个方法,此时调用合约会直接返回错误信息 `no contarct method` func (ac *AgeContract) InvokeContract(stub shim.CMStubInterface) protogo.Response { return shim.Error("no contarct method") } //合约入口 func main() { //运行合约 err := shim.Start(new(AgeContract)) if err != nil { panic(err) } } 这段代码是空合约模板,没有实现任何方法,以后写合约的时候都可以先复制这段代码初始化合约文件。后面我们要做的是增加两个合约方法 saveAgegetAge
  4. 增加 saveAgegetAge 方法。复制下面代码到 main.go。 package main import ( "strconv" "chainmaker/pb/protogo" "chainmaker/shim" ) // AgeContract save and get age type AgeContract struct { } // InitContract 合约初始化方法,会在合约部署到链上时执行 func (ac *AgeContract) InitContract(stub shim.CMStubInterface) protogo.Response { return shim.Success([]byte("Init Success")) } // InvokeContract 调用合约,在链上执行合约时,实际调用的是这个方法 func (ac *AgeContract) InvokeContract(stub shim.CMStubInterface) protogo.Response { return shim.Error("no contarct method") } // saveAge 保存用户年龄信息 func (ac *AgeContract) saveAge(stub shim.CMStubInterface) protogo.Response { //获取所有的合约参数 args := stub.GetArgs() name := string(args["name"]) ageStr := string(args["age"]) if name == "" || ageStr == "" { message := "name or age is empty" //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error(message) } _, err := strconv.Atoi(ageStr) if err != nil { message := "convert age to int fail. err: " + err.Error() //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error(message) } //保存用户年龄信息到链 err = stub.PutStateFromKey(name, ageStr) if err != nil { message := "put state from key fail. err: " + err.Error() //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error(message) } //返回合约执行成功信息 return shim.Success([]byte("success")) } // getAge 获取用户年龄信息 func (ac *AgeContract) getAge(stub shim.CMStubInterface) protogo.Response { //获取所有的合约参数 args := stub.GetArgs() name := string(args["name"]) if name == "" { message := "name is empty" //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error("-1") } ageStr, err := stub.GetStateFromKey(name) if err != nil { message := "get state from key fail. err: " + err.Error() //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error("-1") } if ageStr == "" { message := "age not found" //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error("-1") } //返回用户年龄 return shim.Success([]byte(ageStr)) } func main() { //运行合约 err := shim.Start(new(AgeContract)) if err != nil { panic(err) } } 这段代码较第三步增加了两个方法: func (ac *AgeContract) saveAge(stub shim.CMStubInterface) protogo.Response {} func (ac *AgeContract) getAge(stub shim.CMStubInterface) protogo.Response {} 这两个方法分别是存储和查询用户年龄。 此时saveAgegetAge 方法是孤立存在的,不能通过合约调用到对应的方法,下面我们将在合约调用方法中关联合约和方法,这样调用合约方法时就能找到对应的方法。
  5. 关联合约方法。复制完整的合约代码到 main.go。 修改 AgeContract .InvokeContract() 方法,增加关联合约方法代码。修改后的内容如下: // InvokeContract 调用合约,在链上执行合约时,实际调用的是这个方法 func (ac *AgeContract) InvokeContract(stub shim.CMStubInterface) protogo.Response { //获取要调用的合约方法 method := string(stub.GetArgs()["method"]) //case "saveAge" 关联方法名 "saveAge" 到 ac.saveAge() //case "getAge" 关联方法名 "getAge" 到 ac.getAge() switch method { case "saveAge": return ac.saveAge(stub) case "getAge": return ac.getAge(stub) default: return shim.Error("no contarct method") } } 完整的合约代码如下: package main import ( "strconv" "chainmaker/pb/protogo" "chainmaker/shim" ) // AgeContract save and get age type AgeContract struct { } // InitContract 合约初始化方法,会在合约部署到链上时执行 func (ac *AgeContract) InitContract(stub shim.CMStubInterface) protogo.Response { return shim.Success([]byte("Init Success")) } // InvokeContract 调用合约,在链上执行合约时,实际调用的是这个方法 func (ac *AgeContract) InvokeContract(stub shim.CMStubInterface) protogo.Response { //获取要调用的合约方法 method := string(stub.GetArgs()["method"]) //case "saveAge" 关联方法名 "saveAge" 到 ac.saveAge() //case "getAge" 关联方法名 "getAge" 到 ac.getAge() switch method { case "saveAge": return ac.saveAge(stub) case "getAge": return ac.getAge(stub) default: return shim.Error("no contarct method") } } // saveAge 保存用户年龄信息 func (ac *AgeContract) saveAge(stub shim.CMStubInterface) protogo.Response { //获取所有的合约参数 args := stub.GetArgs() name := string(args["name"]) ageStr := string(args["age"]) if name == "" || ageStr == "" { message := "name or age is empty" //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error(message) } _, err := strconv.Atoi(ageStr) if err != nil { message := "convert age to int fail. err: " + err.Error() //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error(message) } //保存用户年龄信息到链上 err = stub.PutStateFromKey(name, ageStr) if err != nil { message := "put state from key fail. err: " + err.Error() //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error(message) } //返回合约执行成功信息 return shim.Success([]byte("success")) } // getAge 获取用户年龄信息 func (ac *AgeContract) getAge(stub shim.CMStubInterface) protogo.Response { //获取所有的合约参数 args := stub.GetArgs() name := string(args["name"]) if name == "" { message := "name is empty" //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error("-1") } ageStr, err := stub.GetStateFromKey(name) if err != nil { message := "get state from key fail. err: " + err.Error() //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error("-1") } if ageStr == "" { message := "age not found" //打印日志,调试合约时,日志会在控制台输出中展示 stub.Log(message) //返回合约执行错误信息 return shim.Error("-1") } //返回用户年龄 return shim.Success([]byte(ageStr)) } func main() { //运行合约 err := shim.Start(new(AgeContract)) if err != nil { panic(err) } }
  6. 测试合约执行效果。至此我们的合约已经编写完成,下面我们可以通过合约调试功能测试一下合约执行效果。先双击 main.go,然后点击合约调试图标。如图所示,选中 saveAge 方法,增加 nameage 参数。然后点击构建合约,等构建完成之后点击执行合约,保存用户年龄信息到链上。 左侧 构建和执行合约 按钮下面会显示合约执行结果。 控制台->输出 会打印合约执行日志 stub.Log() 的内容。 控制台->世界状态 会显示合约的世界状态。{key:"Bob","value":"22"}
V+MrsFu123
V+MrsFu123
  1. 调用 getAge 方法,查询存储的用户年龄信息。如下图:选中 getAge 方法,增加 name 参数,然后点击构建并执行。 左侧 构建和执行合约 按钮下面会显示合约执行结果。 控制台->输出 会打印合约执行日志 stub.Log() 的内容。 控制台->世界状态 会显示合约的世界状态。{key:"Bob","value":"22"}

Smartide-invokeGetAge

V+mrsfu123
V+mrsfu123

3.4. SDK 详细介绍

上面我们一步一步创建了一个简单的合约,用到了SDK提供的一小部分方法。

//保存用户年龄信息到链上
err = stub.PutStateFromKey(name, ageStr)
//从链上查询用户年龄信息
ageStr, err := stub.GetStateFromKey(name)

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 3.3. 使用 SDK写一个简单合约
  • 3.4. SDK 详细介绍
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档