pragma solidity ^0.5.0;
contract Data {
struct Equipment{
string timestamp;
string dev_id;
string dev_type;
string name;
string cmd;
string data;
}
uint256 public i = 0;
Equipment[] public equipmentlist;
//临时存放搜索结果
Equipment[] public serchresult;
function Set(string memory _timestamp,string memory _dev_id,string memory _dev_type,string memory _name,string memory _cmd,string memory _data) public{
Equipment memory equipment = Equipment(_timestamp,_dev_id,_dev_type,_name,_cmd,_data);
equipmentlist.push(equipment);
i++;
}
function Get(uint256 _a) public view returns (string memory,string memory,string memory,string memory,string memory,string memory){
return (equipmentlist[_a].timestamp,equipmentlist[_a].dev_id,equipmentlist[_a].dev_type,equipmentlist[_a].name,equipmentlist[_a].cmd,equipmentlist[_a].data);
}
}
以上合约为例子
我需要使用go进行调用rpc写入数据,
比如我要调用上面的Set函数
以下是拼接好的data数据这个数据对应了上面的Set函数以及参数:
0xab43366d00000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000018000000000000000000000000000000000000000000000000000000000000001c00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000000161000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009e998bfe59b9be696b900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009e79a84e9a38ee6a0bc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009e79a84e9a38ee6a0bc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000472e589af000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009e6b395e59bbde79a840000000000000000000000000000000000000000000000
怎么拼接的呢,下面我们进行分解.
这里我们分解一下.
因为我们要对Set函数进行调用所以这里以Set函数为例子
对以下内容进行Keccak256Hash计算:
Set(string,string,string,string,string,string)
结果转成16进制然后再取前10位得到
0xab43366d
这里需要对6个字符串参数进行运算,默认字符串参数一个占32,这里有6个字符串参数,我们就把32乘以6得到192然后转成16进制就是c0,再在前面填充0直到补齐64位
这里就是 192 转16进制再填充0
00000000000000000000000000000000000000000000000000000000000000c0
//然后在192的基础上加上64,在重复上面的操作.一共重复6次,因为有6个字符串参数
//这里是192+64=256 转16进制再填充0
0000000000000000000000000000000000000000000000000000000000000100
//256+64=320 转16进制再填充0
0000000000000000000000000000000000000000000000000000000000000140
//320+64=384 转16进制再填充0
0000000000000000000000000000000000000000000000000000000000000180
//384+64=448 转16进制再填充0
00000000000000000000000000000000000000000000000000000000000001c0
//448+64=512 转16进制再填充0
0000000000000000000000000000000000000000000000000000000000000200
这里就比较麻烦了,这个值是分别对6个字符串参数写入的值进行处理再拼接得到的
,我这里把它分解成了若干个64位的16进制
第一行是第一个字符串值的长度,这里长度为1,因为我写入的数据就是一个a他的长度所以是1,再在之前填充0满足64位长度
0000000000000000000000000000000000000000000000000000000000000001
第二行就是对第一个字符串值转成16进制然后在后面填充0直到长度满足64位
6100000000000000000000000000000000000000000000000000000000000000
这是对第二个参数进行处理,获取长度转16进制
0000000000000000000000000000000000000000000000000000000000000009
数据转16进制填充0
e998bfe59b9be696b90000000000000000000000000000000000000000000000
这是对第三个参数进行处理
0000000000000000000000000000000000000000000000000000000000000009
e79a84e9a38ee6a0bc0000000000000000000000000000000000000000000000
这是对第四个参数进行处理
0000000000000000000000000000000000000000000000000000000000000009
e79a84e9a38ee6a0bc0000000000000000000000000000000000000000000000
这是对第五个参数进行处理
0000000000000000000000000000000000000000000000000000000000000004
72e589af00000000000000000000000000000000000000000000000000000000
这是对第六个参数进行处理
0000000000000000000000000000000000000000000000000000000000000009
e6b395e59bbde79a840000000000000000000000000000000000000000000000
就是这样.拼接起来,我这里为了方便观看所以用换行符分割了
还有就是参数初始不一定就是32,比如字符串参数还随着写入数据长度更改,可能为64或者更大,
如果参数类型是uint那又是另外种拼接方法.
我这里附上文档
https://solidity.readthedocs.io/en/v0.6.1/abi-spec.html#types
这个是我用的代码
主要代码片段:
h:=crypto.Keccak256Hash([]byte(`Set(string,string,string,string,string,string)`))
head:=h.Hex()[:10]
data:=`a`
data1:=`参数`
data2:=`参数3`
data3:=`参数4`
data4:=`参数5`
data5:=`参`
data,n:=handledata(data)
data1,n1:=handledata(data1)
data2,n2:=handledata(data2)
data3,n3:=handledata(data3)
data4,n4:=handledata(data4)
data5,n5:=handledata(data5)
//取字符串的长度
DATA:=fmt.Sprintf("%064x%s%064x%s%064x%s%064x%s%064x%s%064x%s",n,data,n1,data1,n2,data2,n3,data3,n4,data4,n5,data5)
//fmt.Println(DATA)
set:=fmt.Sprintf("%064x",192)
set1:=fmt.Sprintf("%064x",256)
set2:=fmt.Sprintf("%064x",320)
set3:=fmt.Sprintf("%064x",384)
set4:=fmt.Sprintf("%064x",448)
set5:=fmt.Sprintf("%064x",512)
h:=crypto.Keccak256Hash([]byte(`Set(string,string,string,string,string,string)`))
head:=h.Hex()[:10]
//"0xab43366d"+192的十六进制+
Data=head+set+set1+set2+set3+set4+set5+DATA
fmt.Println(Data)
处理字符串的函数:
//处理字符串
func handledata(stringdata string)(string,int){
//获取字符串长度
n:= len(stringdata)
//转化为16进制
data:=fmt.Sprintf("%x",stringdata)
//获得字符串长度
n1:=len(data)
//获得000000.....字符串
data1:=fmt.Sprintf("%064x",stringdata)
//裁减尾部的字符串
data1=data1[:len(data1)-n1]
//把字符串加在前面再返回
return data+data1,n
}
如果遇到什么问题欢迎添加我的微信共同交流。