go调用以太坊rpc发送交易中的DATA参数数据解析

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
}

如果遇到什么问题欢迎添加我的微信共同交流。

 

你可能感兴趣的:(eth)