以太坊源码分析—Whisper

[TOC]git

前言

Whisper是以太坊中一项很是有趣的技术,它是一个基于身份的通讯系统,被设计用于Dapp之间少许数据通讯。Whisper协议运行在以太坊p2p协议框架之上,全部运行Whisper协议的节点(如下简称节点)组成一个Whisper网络。经过节点之间的消息转发,理论上,每一个节点均可以收到全部Whisper消息。github

特性

Whisper具备如下基本特性和概念算法

通讯加密

每一条Whisper消息在网络上都是加密传输的,能够选择非对称加密(椭圆曲线)和对称加密(AES GSM)两种加密算法之一。segmentfault

Envelope(信封)

Envelope是网络中传输的Whisper消息的基本单位,它包含已加密的原始消息以及消息相关的控制信息:网络

  • Expiry time:消息的超时时刻,过了这个时刻,本消息不会被节点处理或者转发
  • TTL:消息的存活时间,一个消息在从被建立起,只能生存TTL的时间,过了这个时间以后,消息在网络中超时
  • Topic:消息的主题
  • AESNonce:采用AES对称密钥加密算法时使用的Nonce值
  • EnvNonce:用于PoW计算

当一个节点从一个Peer收到一个Envelope时,无论它本身管不关内心面的数据(Topic是否符合设置的值), 它都会将这个Envelope转发给其余Peer,这是Whisper的固有机制。app

Topic(主题)

每一个Envelope上写明了本身封装消息的Topic,若是一个节点不关心这个Topic,那么它就不须要去试着打开(解密)这个Envelope。一般一个Topic对应一个消息加密时使用的Key(不管是对称仍是非对称加密)。因此,若是一个节点收到了一个关心的TopicEnvelope时,它应该能打开这个Envelope框架

Filter(过滤器)

Dapp 能够在节点上安装多个Filter,每一个Filter包含一组条件,只有知足这些条件的Envelope才能被打开,准确的说,不是节点打开Envelope,而是节点上安装的Filter打开Envelope,每一个Filter有一个缓冲区能够存储解密后的消息,若是一个Envelope知足多个Filter,那么这个消息会存储在多个Filter中。Filter能够设置如下条件:函数

  • Topics:关心的主题的集合
  • Sender address:建立这个消息的节点
  • Recipient address:指定接收节点的地址
  • PoW requirement:消息须要的工做量证实
  • AcceptP2P:节点是否接收P2P消息,这类消息有特殊的用途
Proof of Work(工做量证实)

Proof of Work用来防止节点恶意大量发送消息,采用的算法和PoW共识算法差很少。消息的建立者须要找到一个nonce使得消息的Hash值小于一个值。这个值与消息的大小和TTL有关,消息越大,TTL越大,则找到nonce越困难,计算工做量的公式为oop

formula

其中$BestBit$为Hash值中从左往右第一个为1的bit所在的位置(这个值越大,则须要尝试nonce的次数越多)源码分析

源码分解

本部分主要涉及Whisper filter envelope ,它们的联系以下图:

Whisper

Whisper表示一个协议实例,负责整个Whisper功能的运行,其中比较重要的字段以下:

  • protocol - Whisper协议的特定值,最重要的是其中的Run字段,它表示该协议的运行入口
  • filter - 本节点安装的全部Filter
  • privateKeys - 本节点存储的非对称密钥对的集合,一个Whisper实例能够保存多个密钥对
  • symKeys - 本届点存储的对称密钥的集合,一个Whisper实例能够保存多个对称密钥
  • envelopes - envelope池,保存全部待广播发送的信封。信封池的存储键值是envelope的Hash
  • expirations - 超时池,记录envelope的的过时时间,超时池的存储键值是unix时间,值是envelope的Hash
  • peers - 活跃的Peer节点的集合,数据来源是p2p底层
  • msgQueue - 普通Whisper消息的envelope处理通道

以太坊源码分析—p2p节点发现与协议运行提到过,两个节点在底层链接创建后,会运行共同支持的协议的Run函数,对于Whisper协议来讲,就是HandlerPeer函数。
whisper
HandlePeer最终运行在两个Go routine中,一个是Whisper.runMessageLoop(),它负责从底层读取消息,另外一个是Peer.update(),它负责周期性的将envelope池中的未发送的envelope发送到对端并将过时的envelope删除。

Envelope

Envelope表示一个Whisper消息,它有两个来源

  1. 出方向经过NewEnvelope()构造
  2. 入方向从Peer节点接收

其重要的字段有

  • Topic - Envelope中的数据的主题,节点的Filter能够过滤感兴趣的主题进行解密
  • EnvNonce - 消息的建立者在PoW中找到的nonce
  • pow - 消息具备的pow值

消息发送的典型过程

如下是本节点广播发送一小段数据payload,封装到Envelope,再加入到Envelope池的过程,其中wh表示Whisper实例
send

  1. 首先构造发送参数,包括原始数据payload,主题Topic等
  2. 利用发送参数构造SentMessage
  3. 根据发送参数将SentMessage封装到新建立的Envelope,这一步包括签名(sign)加密(encrypt)计算nonce(Seal)
  4. Envelope加入Envelope池

消息接收的典型过程

如下是典型的Whisper消息接收过程,其中w表示Whisper实例
receive

  • w.runMessageLoop()从底层收到Whisper消息,并解码成Envelope,加入Envelope池,调用postEvent()向w.messageQueue写入这个事件
  • 另外一方面,当w经过Start启动后,从w.messageQueue接收事件,开始Filter匹配
  • 用已安装的每一个Filter去匹配这个Envelope,若是匹配上,就将Envelope打开(解密),最终将其放入Filter的缓冲区中。

demo

写了一个whipser的chat-room demo,托管在github上,感兴趣能够瞧瞧

相关文章
相关标签/搜索