前言
这篇文章,咱们承接上文,来聊聊
上篇文章的飞机票
在Xuper链上部署Java语言智能合约和分析存证合约的实现逻辑
“如何根据自己公司的业务逻辑定义存证合约里面的数据结构来实现存证智能合约”
首先需要明确下公司存证业务需要上链的数据结构
`{
"data":"", #这里是一个动态的json字符串
"businessId":"", #业务id
"fileHash":"", #文件hash
"applyNotarization","" #申请组织编号
"entityName":"" #公司名称
}`
业务需求
1、将上面的数据上链
2、可以通过业务id businessId和fileHash查询
官方给的go语言版本的存证合约模版
`这个咱上篇文章已经详细介绍过存证合约模版的实现逻辑了
这里把数据结构贴出来 然后和自己需要的数据结构进行比对
{
"Owner":"xiaoming" , # 这个表示用户名
"UserFiles":{ # 这个是一个map集合
"filehash":{ # map集合的key是文件hash
"Timestamp":"" # 时间戳
"Hashval":"" # []byte(filehash) 其实也是hash值
}
}
}`
比对结果
1、filehash这个map的key对应的value是一个对象 对象内容官方模版只有Timestamp和Hashval这2个字段 那么咱们把 data、businessId、fileHash、applyNotarization、entityName 这5个字段加入进去
2、另外咱们上篇文章也说了 官方模版里面 是通过owner和filehash确认一条上链数据的 ,那么咱们的需求又增加了一个查询参数 businessId 那么再添加一个map集合 里面的与元素 key表示businessId value表示一个对象的json字符串不就可以解决了
最终符合业务需求的数据结构
`{
"Owner":"xiaoming",
"UserFiles":{
"filehash":{
"Timestamp":"",
"Hashval":"",
"data":"",
"businessId":"",
"applyNotarization":"",
"entityName":"",
"fileHash":""
}
},
"BuisnessUserFiles":{
"businessId":{
"Timestamp":"",
"Hashval":"",
"data":"",
"businessId":"",
"applyNotarization":"",
"entityName":"",
"fileHash":""
}
}
}`
下面存证合约模版代码
- 数据结构
1、添加了一个map集合 key-value ,key为businessId
2、将那5个业务字段添加进去
3、需要注意的是 对象里面的参数首字母必须大写 否则 给属性赋不了值
- 数据上链方法修改
模仿filehash书写的方式和逻辑
1、给属性赋值
2、给map集合赋值或初始化
- 查询方法
这2个查询的方法也是模仿官方模版里面的getFile方法
编译合约
`进入到go源码合约文件目录
GOOS=js GOARCH=wasm go build -o hello.wasm
会编译合约文件生成一个hello.wasm文件`
部署合约
./xchain-cli wasm deploy --account XC1111111111111111@xuper --cname hello_last_9 --fee 5574291 --runtime go ./hello-go/hello.wasm -a '{"owner":"mengfanxiao"}'
调用合约
若合约源码问题有问题如何解决
现象是:合约部署成功 但调用合约失败
那么就可以认定是 自己自定义的合约代码有问题
如果每次测试合约都需要部署到链上再发起调用会特别麻烦,官方提供的3种方式,可以脱离链上环境运行合约
官方提供的3种方式 上面的go语言合约代码问题我是通过方式2完成的 没有通过官方提供的这3种方式解决 原因如下;
这里简单的说下目前的现状 截止20200706,主要目的是避免朋友们在坑里待得时间太久 耽误了进度
官方文档
https://xuperchain.readthedoc..._manuals/XdevManual.html
通过百度超级链官网控制台入口来测试合约源码文件是否有问题
目前仅仅支持c++语言开发的合约的测试,那咱们用的是go语言,所以这种方式就用不了,为什么用go语言呢,因为只有go语言才有存证的合约模版
大致的使用步骤是
a、先注册一个账号登陆控制台
b、充值2元钱
c、创建一个合约账户
d、创建合约
d-1 输入合约名称
d-2 可以选择现有的模版,也可以选择空白的模版
d-2-1 选择空白模版的话 可以将自己的c++编写的合约代码复制进去
空白模版
d-2-2 若是选择的现有的模版 可以基于现有的模版代码进行修改
通过xdev可执行命令来测试
dev工具是随xuperchain发布的一个合约编译和测试工具
先来运行下官方给的例子 熟悉下流程和确保运行环境没有问题
咱们目前的环境是最新版的master版本
使用默认的方式启动的 nohup ./xchain &
使用 xdev 测试c++语言合约
- 配置环境变量
`export PATH=$HOME/xuperchain/output:$PATH
export XDEV_ROOT=$HOME/xuperchain/core/contractsdk/cpp
注意这里配置的是cpp目录`
- 初始化代码
xdev init hello-cpp
目录结构和图【空白模版】是对应的
- 编译
`cd hello-cpp
xdev build -o hello.wasm`
- 部署下合约
./xchain-cli wasm deploy --account XC1111111111111111@xuper --cname hello --fee 5200000 --runtime c ./hello-cpp/hello.wasm
- 调用合约
./xchain-cli wasm invoke --method hello --fee 110000 hello
- 测试
xdev test
合约部署和调用都可以通过
使用xdev测试go语言存证模版合约
- 编译
`cd xuperchain/core/contractsdk/go/example/eleccert
GOOS=js GOARCH=wasm go build -o hello.wasm`
- 合约部署
`./xchain-cli wasm deploy --account XC1111111111111111@xuper --cname hello --fee 5200000 --runtime go ./hello-go/hello.wasm
此时会报错使得当前节点挂掉`
梳理下问题现象
1、当前节点环境是通过 nohup ./xchain & 方式启动的
2、通过wsam部署方式部署c++合约对应的合约文件是可以的
3、通过wsam部署方式部署go合约对应的合约文件是不可以的 会导致节点挂掉
调整启动方式
nohup ./xchain --vm ixvm &
然后再执行上面的部署命令是可以的
结论
目前版本可能还不支持没有指定--vm ixvm虚拟机的情况下通过wasm的方式部署go语言合约
还有一种可能是上面配置的环境变量配置的是cpp 这里是不是需要配置成go?朋友们感兴趣的话 可以尝试下
- 测试
- go和c++合约文件区别
下面咱通过同样的方式部署下咱们自定义的存证的智能合约
1、先对go源码文件编译生成hello.wasm文件
2、复制到 hello-go 文件夹
3、执行 xdev test命令
此时心里十万个茶叶蛋飞奔而过
我辛辛苦苦使用xdev测试我的合约文件 想找出里面是哪里的代码有问题 但你却告诉我这种结构,遂“含恨”放弃这种方式
第三种方式 是通过vscode来编译源码文件
这种方式就不演示了 原理就是用的xdev命令对源码进行编译(build)和测试(test)
因为我对vscode编译go不太熟 所以这里简单的记录下步骤 以免下次用vscode再对go编译的时候看看这里就知道了
1、打开vscode 添加add workspace 工作目录 指定一个文件夹 该文件夹下面包含go源码文件
2、Terminal-Configure Tasks-create task.json
`{
// See https://go.microsoft.com/fwli...
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "xdev build",
"type": "shell",
"command": "xdev build -p",
"options": {
"cwd": "${workspaceFolder}"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "xdev test",
"type": "shell",
"command": "xdev test",
"options": {
"cwd": "${workspaceFolder}"
}
}
]
}`
3、然后Terminal-run Build Task 的时候也一直报错 说找不到 XDEV_ROOT,XCHAIN_ROOT环境变量
因为我知道原理就是利用的xdev来做的,我对xdev已经不抱什么希望了,所以就没有再去解决这个问题
后来转变了下方向 终于找到了适合的方向
比较合适的方法【推荐】
我一开始想着既然是合约源码有问题,那么在源码文件中添加一些日志,然后一行一行的进行定位不就可以找到问题代码了吗,后来看了下存证模版源码文件中没有输出日志的代码 所以我就没有采用这种方式
大家可以试下 添加写日志文件 然后去logs/contract.log日志文件中找下日志
我最终采用的方式是:
1、一份存证模版文件源码 这个肯定是没有问题的
2、我基于模版文件源码新写的一份文件
我在想在模版文件中添加了这么多代码 第一次执行肯定会有问题的
类似于“步子垮大了 容易扯蛋”,“一口不能吃下一个大胖子”
那么我将新增的代码一点一点的放入模版文件,每次放入都会经历编译、部署、调用执行的过程 确保每次新增的代码没有问题,遂很快的解决了这个问题
手续费去向问题
通过节点账户调用合约发起交易,那么手续费来源节点账户,目的账户是出块节点账户吗
咱们查看交易详情
./xchain-cli tx query 1fcc2d5cc2e6bad345a21d14871bd641167c44b5a5ac69076d3095458ed94784
不查不知道 一查吓一跳 请看蓝色字体
1、来源账户余额不止这个数 怎么是 1000000
2、目的账户怎么是$
大家是不是在担心账户余额要是不够了,是不是发起不了交易了?
这个担心是多余的
原因:
- 因为当前节点是出块节点,每次出块都会有奖励, 每次奖励的金额可以调整 如果担心的话 可以调大点
- 再一个就是定时出块机制 每隔3秒出一次奖励一次
- 初始金额可以调大些
还不放心的话 可以多个节点账户做备用账户 若一个账户余额不够了 则使用其他的账户来发起合约交易(当然需要对应账户下面的合约账户部署的合约喽)
上面遗留的2个问题 咱们下回分解哦
自定义合约文件源码地址
https://gitee.com/pingfanrenbiji/xuper-java-sdk/blob/master/src/test/resources/com/baidu/xuperunion/api/eleccert.go
本文使用 mdnice 排版
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。