以太坊上交易hash和交易签名的计算
参考:https://zhuanlan.zhihu.com/p/267651205
一:用于签名的哈希值的计算:在使用私钥计算一笔交易的签名内容时,先要对交易结构的相关数据以及链id(chainId)进行哈希,然后再使用私钥对哈希结果进行签名得到签名结果(签名结果包含R, S, V3个字段)。该哈希值不会被写入区块链里
传入交易对象Transaction、签名器Signer、以及私钥ecdsa.PrivateKey
首先调用签名器的Hash方法对交易对象tx进行hash(其实这里和生成交易id的过程是一样的只不过,如果使用的是EIP155Signer签名器会包含有ChainID,正常以太坊上的交易id的生成过程中没有这个ChainID)
Signer这个签名接口的具体实现是3种签名器:FrontierSigner是签名器最早实现的版本,HomesteadSigner是后来实现的版本,EIP155Signer则是最新的版本,并在签名的哈希值计算中引入了chainId来防止跨链实施攻击。
在EIP155Signer版本签名器中,节点需要对客户端发送过来的签名结果中的V值进行校验,校验V值中包含的chainId是否和本节点的chainId相比较,如果不一致,则认为该笔交易不是本条链上的交易,从而判断该交易非法。对于使用EIP155Signer版本签名器,签名结果中的V值的计算方法是:V=chainId*2+35
EIP155Signer.Hash()方法我们后面看
sig, err := crypto.Sign(h[:], prv)
需要注意的是,即使是对于同一个哈希值h,每次使用同一个私钥prv对哈希值h进行签名得到的R, S这2个字段不一定会相同。
二:交易hash生成
交易hash的生成和签名器的Hash方法对交易对象tx进行hash的过程类似,我们先看下EIP155Signer.Hash()方法
实际上就是将Transaction的基础输入数据取出来再加上chainid一起传入rlpHash进行rlp编码后hash
基础输入数据包括:
AccountNonce(发起者的Nonce),
Price(gasPrice),
GasLimit,Recipient(接收者),
Amount(转账金额),
Payload(智能合约相关的内容,如果是普通转账交易,该字段为空)
再看下以太坊上交易hash的计算
可以看到直接使用的是rlpHash(Transaction)
Transaction的结构体为
data的结构体为
因为hash字段使用了rlp:"-",表示rlp编码解码时忽略该字段。hash ,size 和from这3个atomic.Value类型的字段也是不包括的 )进行处理,处理过程是先对整个交易数据进行RLP编码,再运用Keccak256哈希算法获得交易哈希
所以最后除了AccountNonce,Price,GasLimit,Recipient,Amount,Payload还多了签名的V、R、S三个值
所以一笔交易在签名之后生成了V、R、S,就算还没被打包,他的交易hash也是可以计算出来的了。
而由于V、R、S每次签名都不一样,所以不同的2笔交易计算出来的交易哈希相同的可能性基本为0