前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >以太坊: ETH 发送交易 sendRawTransaction 方法数据的签名 和 验证过程

以太坊: ETH 发送交易 sendRawTransaction 方法数据的签名 和 验证过程

作者头像
林冠宏-指尖下的幽灵
发布2018-09-19 15:03:57
2.1K0
发布2018-09-19 15:03:57
举报
文章被收录于专栏:林冠宏的技术文章

作者:林冠宏 / 指尖下的幽灵

掘金:https://juejin.im/user/587f0dfe128fe100570ce2d8

博客:http://www.cnblogs.com/linguanh/

GitHub : https://github.com/af913337456/

腾讯云专栏: https://cloud.tencent.com/developer/user/1148436/activities


前序

最近的工作一直是基于 以太坊公链 做 DApp 开发,虽然对其各 API 的调用都已经很了解了,但是源码部分一直还没深入去看过。工欲善其事,必先利其器,故计划阅读完 以太坊go 版源码,后续会更新系列文章。本文主要简谈 sendRawTransaction 是如何保证我们交易安全的。

1.数据签名

方法:sendRawTransaction
整体流程:

  1. 传入各参数 ---->

  1. 使用from 对应的 privateKeysecp256k1 算法对 各入参 签名得出三个量:V,R,S ---->

  1. RLP (递归长度前缀) 方式序列比签名的数据 与 原入参数据 ---->

  1. 发送到 ETH 节点

sendRawTransaction 函数的各个入参:

  • from 发送者钱包地址
  • value 数值,为与 decimal 的乘积
  • gas 油费,非最终真实使用值,真实为 gasUsed
  • gasPrice 油费单价
  • data 附属的数据,可做智能合约函数入参
  • nonce 交易系列号,类似id

它们都将会被 from 所对应的密钥 进行签名而得出三个量:V,R,S。同时,各个入参依然以原来的可见的形式进入序列化步骤。

注意:

还有另外一个叫做 sendTransaction 的方法,通过分析源码,可以发现 sendTransaction 内部其实会帮助我们根据我们传参的 from 字段到节点的 accountManager 账号管理器中获取from 的密钥,来帮我们进行数据签名,所以,sendTransaction 一般不会用于远程调用,而用于本地调用,因为只有在本地启动节点的时候,才能配置我们解锁的钱包。

所用的签名加密方式是:非对称加密 中的 secp256k1 椭圆曲线算法

非对称加密:

它是一类加密方式的统称。具体到某种能实现它的算法有下面几种:

  • RSA
  • secp256k1 (椭圆曲线)
  • ElGamal
  • ...

sendRawTransaction 用到的就是 secp256k1

RLP 序列化

RLP (递归长度前缀)提供了一种适用于任意二进制数据数组的编码,RLP已经成为以太坊中对对象进行序列化的主要编码方式。RLP的唯一目标就是解决结构体的编码问题;对原子数据类型(比如,字符串,整数型,浮点型)的编码则交给更高层的协议;以太坊中要求数字必须是一个大端字节序的、没有零占位的存储的格式。

签名后,数据将会被发送到 ETH 节点。

2. 数据验证

对应到以太坊的 sendRawTransaction RPC 接口。

  1. 收到 RLP 序列化的数据后,先进行 RLP 的反序列化
代码语言:javascript
复制
func (s *PublicTransactionPoolAPI) SendRawTransaction(..., encodedTx hexutil.Bytes) (common.Hash, error) {
    tx := new(types.Transaction)
    if err := rlp.DecodeBytes(encodedTx, tx); err != nil { // 反序列化
        return common.Hash{}, err
    }
    return submitTransaction(ctx, s.b, tx)
}
  1. 数据的基础校验,主要是一些范围限制以及格式限制校验
    • tx.Size() > 32*102
    • tx.Value().Sign() < 0
    • pool.currentMaxGas < tx.Gas()
    • ...
  2. 检查签名,所使用的是 secp256k1.RecoverPubkey 方法,secp256k1 本身支持根据签名信息反推公钥

用消息和签名推导出对方的公钥。再通过公钥,签名,消息的哈希值计算出一个叫 r 的值,这个 r 是签名的一部分,校验签名就是拿计算出来的 r 和签名中携带的 r 经行对比,如果一致就校验通过

代码语言:javascript
复制
if C.secp256k1_ext_ecdsa_recover(
    context,
    (*C.uchar)(unsafe.Pointer(&pubkey[0])), 
    sigdata,  // 签名
    msgdata) == 0 { // msgdata tx 的 hash 内容
    
    return nil, ErrRecoverFailed
}
3. 数据篡改

因为签名生成的 V R S 是由私钥进行签名的,如果修改者只修改了外部的值,例如 value,本来是要转 10 个 ETH , 被改成转 100 个,等数据传到以太坊的时候,在检查签名的时候,就会发现不匹配,而抛出错误。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018-09-09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前序
  • 1.数据签名
    • 方法:sendRawTransaction
      • 整体流程:
        • 注意:
      • 非对称加密:
        • RLP 序列化
        • 2. 数据验证
          • 3. 数据篡改
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档