
ETH交易构建 & 签名
Hello , 我是09
此篇内容为我2018~2020年在【库神】工作时,对部分重要知识做的学习总结
随着比特币冲破10万美金,行业又再次兴起,希望相关从业者可以学习到你需要的内容
介绍
私钥
Secp256k1,和比特系列一样
公钥
Secp256k1,和比特系列一样
构建交易
(1)所有数据采用RLP编码,RLP编码规定数据(字符串或列表)的长度的长度不得大于8字节。因为超过8字节后,一个字节的前缀就不能存储了,大致RLP的规则是清除掉数据签名的站位0,然后对数据进行大端存储,详细内容可以百度RLP。
(2)所有构建的交易数据,转十六进制后,需要进行去除站位用到的0。
(3)RLP编码,针对String类型的编码规范如下:
数据长度为 1 :如果字符串的长度是1个字节,并且它的值在[0x00, 0x7f],所以不需要添加前缀,因为大于0x7f的话就是大于127,那么在阿斯克码表中长度就无法用一个字符来表示了,
数据长度0~55:其RLP编码是前缀跟上(拼接)字符串本身,前缀的值是0x80加上字符串,字符串的最大长度是55,因此前缀的最大值是0x80+55=0xb7,取值范围是[0x80, 0xb7]
数据长度 > 55:前缀的值是0xb7加上字符串长度的二进制形式的字节长度,因此前缀的最大值是0xb7+8=0xbf,因此在本规则下前缀的取值范围是[0xb8, 0xbf]
RLP编码,针对列表List,iOS中为Array类型:
数据长度为0~55:前缀的值是0xc0加上列表的总长度。在本规则下前缀的取值范围是[0xc0, 0xf7]。
数据长度 > 55:前缀的值是0xf7加上列表总长度的长度。编码的第一个字节的取值范围是[0xf8, 0xff]
e8 // 0xC0 + 整体交易数据的len 我的交易数据长度为40,那么192 + 40 = 232 所以为e8
80 // nonce len + 0x80 (我测试这一笔nonce为0,所以十六进制为80)
85 // gasprice len + 0x80 + 5
02540be400 // gasprice
83 // gaslimit len + 0x80 + 3
013880 // gaslimit
94 // to addr len + 0x80V+ 20
fb69e9a99762a5e30dda7f677722b8c3bd4d3414 // to addr
86 // Amount len + 0x80
5af3107a4000 // Amount
签名
(1)采用Secp256k1
(2)对数据采用采用SHA3_256操作。
(3)签名过后,需要将签名的数据对应r、s、v分开来分别操作。
(4)v需要加等于27.
(5)签名后得到的数据:
aa41c9ba059210fa658640ca9f312a30c18781ea85f4d6b03984407e43c579f35337604cd48ee1cfdfeed742f53559be77311b004fa8424d7de8e400af5f8215
(6)对于签名数据需要拆分,并拼接到交易数据中
1b // sign V (V = 27) 27的数据length为1, 当数据长度为1的时候,计算长度的时候不需要
a0 // Signr len + 0x80
aa41c9ba059210fa658640ca9f312a30c18781ea85f4d6b03984407e43c579f3 // Signr
a0 // SignS len + 0x80
5337604cd48ee1cfdfeed742f53559be77311b004fa8424d7de8e400af5f8215 // SingS
五、完整待广播交易数据
f86b808502540be4008301388094fb69e9a99762a5e30dda7f677722b8c3bd4d3414865af3107a4000801ba0aa41c9ba059210fa658640ca9f312a30c18781ea85f4d6b03984407e43c579f3a05337604cd48ee1cfdfeed742f53559be77311b004fa8424d7de8e400af5f8215
f8 // 0xf7 + 整个数据的len “6b” 所占的字节len 就变成了 0xf7 + 1 = 0xf8
6b // 整个交易数据的长度 包括签名
80 // nonce len + 0x80 (我测试这一笔nonce为0,所以十六进制为80)
85 // gasprice len + 0x80
02540be400 // gasprice
83 // gaslimit len + 0x80
013880 // gaslimit
94 // to addr len + 0x80
fb69e9a99762a5e30dda7f677722b8c3bd4d3414 // to addr
86 // Amount len + 0x80
5af3107a4000 // Amount
80 // 备注,因为没有备注所以长度为0x80 + 0 = 0x80
1b // sign V (V = 27) 27的数据length为1, 当数据长度为1的时候,计算长度的时候不需要 hby + 27 + 1
a0 // Signr len + 0x80
aa41c9ba059210fa658640ca9f312a30c18781ea85f4d6b03984407e43c579f3 // Signr
a0 // SignS len + 0x80
5337604cd48ee1cfdfeed742f53559be77311b004fa8424d7de8e400af5f8215 // SingS
总结
(1)在对交易签名、没有签名的时候,拼接整体数据的头部信息是不一样的!
(2)所有数据,都需要删除站位的0。
(3)签名后需要将r、s分开处理。
(4)v单独处理
RLP编码规则
RLP编码的重点是给原始数据前面添加若干字节的前缀,而且这个前缀是和数据的长度相关的,并且是递归的。
RLP编码中的长度是数据的实际存储空间的字节大小,去掉首位0的正整数,用大端模式表示的二进制格式表示。
RLP编码规定数据(字符串或列表)的长度的长度不得大于8字节。因为超过8字节后,一个字节的前缀就不能存储了。
如果字符串的长度是1个字节,并且它的值在[0x00, 0x7f] 范围之间,那么其RLP编码就是字符串本身。即前缀为空,用前缀代表字符串本身;
否则,如果一个字符串的长度是0-55字节,其RLP编码是前缀跟上(拼接)字符串本身,前缀的值是0x80加上字符串的长度。由于在该规则下,字符串的最大长度是55,因此前缀的最大值是0x80+55=0xb7,所以在本规则下前缀(第一个字节)的取值范围是[0x80, 0xb7];
如果字符串的长度大于55个字节,其RLP编码是前缀跟上字符串的长度再跟上字符串本身。前缀的值是0xb7加上字符串长度的二进制形式的字节长度(即字符串长度的存储长度)。即用额外的空间存储字符串的长度,而前缀中只存字符串的长度的长度。例如一个长度是1024的字符串,字符串长度的二进制形式是\x04\x00,因此字符串长度的长度是2个字节,所以前缀应该是0xb7+2=0xb9,由此得到该字符串的RLP编码是\xb9\x04\x00再跟上字符串本身。因为字符串长度的长度最少需要1个字节存储,因此前缀的最小值是0xb7+1=0xb8;又由于长度的最大值是8个字节,因此前缀的最大值是0xb7+8=0xbf,因此在本规则下前缀的取值范围是[0xb8, 0xbf];
以上3个规则是针对字符串的,接下来的两个规则针对列表的。由于列表的任意嵌套的,因此列表的编码是递归的,先编码最里层列表,再逐步往外层列表编码。如果一个列表的总长度(payload,列表的所有项经过编码后拼接在一起的字节大小)是0-55字节,其RLP编码是前缀依次跟上列表中各项的RLP编码。前缀的值是0xc0加上列表的总长度。在本规则下前缀的取值范围是[0xc0, 0xf7]。本规则与规则2类似;
如果一个列表的总长度大于55字节,它的RLP编码是前缀跟上列表的长度再依次跟上列表中各元素项的RLP编码。前缀的值是0xf7加上列表总长度的长度。编码的第一个字节的取值范围是[0xf8, 0xff]。本规则与规则3类似;
问题
v : 代表什么意思
为什么不需要From addr
签名数据里面为什么没有公钥
RLP的优势
KFC6979
Private到keystore的导入导出