以太坊源碼分析—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上,感興趣能夠瞧瞧

相關文章
相關標籤/搜索