1. 程式人生 > >以太坊P2P模組節點發現演算法剖析

以太坊P2P模組節點發現演算法剖析

核心資料結構:

NodeTable類負責以太坊的節點發現,NodeTable採用kademlia(KAD)演算法進行節點發現

  • NodeTable維護一個網路節點列表,此列表為當前可用節點,供上層使用
  • 由於NodeID經過sha3生成出的Hash為256位。列表有256-1=255項,其中-1是因為刨除了當前節點(本機)
  • 列表的每一項位一個節點桶(NodeBucket),每個桶中最多放16個節點
  • 列表的第i項代表據當前節點(本機)距離為i+1的網路節點集合

節點探索演算法:

其中節點間距離定義如下:

  • 節點NodeID(512位)會先用sha3演算法生成一個256位hash。算兩個節點的256位hash的XOR值,節點距離定義為此XOR值的1位最高位的位數。(例如:0010 0000 1000 0101 位XOR值的化 那麼這兩個節點的距離為14)
  • 此處的NodeID為網路節點公鑰(512位)
  • 注意:這裡的節點距離與機器的物理距離無關,這個距離僅僅是邏輯上的一種約定

發現演算法思路如下:

這裡寫圖片描述

  • 1.先隨機一個目標節點的NodeID
  • 2.在列表中以相對NodeID的“距離”為指標,由近及遠查詢此待連節點“附近”的節點。並將這些節點放入“附近”節點集合
  • 3.向目標節點的“附近”節點集合中的每個節點發送FindNode訊息
  • 4.若在目標節點的”附近”沒有搜到節點,則返回步驟1
  • 5.否則等待600ms後跳轉到步驟2

節點的狀態:

這裡寫圖片描述

  • Pending:
    • 掛起狀態,每個新發現的節點或通過程式碼新增的節點的初始狀態
    • 在新增節點時會向此節點發送Ping訊息,已檢視是否線上
  • Alive:此狀態說明Pong訊息已收到,此節點線上。
  • Evicted:由於對當前節點某個距離的桶最多隻允許存在16個節點,若在此距離發現的新節點正好超過了限額,則新節點保留,桶中最老的節點會被喚出,進入此狀態

如何冷啟動:

由於初始化時節點列表為空,所以不可能找到目標節點的所謂附近節點。這就需要一些初始種子節點進行連線。在eth客戶端啟動時會新增5個種子節點,這些節點的NodeID、ip、埠被硬編碼在Host.pocHosts函式中。
這裡寫圖片描述

節點發現協議:

  • 協議:
    • FindNode:節點查詢協議,向目標節點詢問其臨近節點列表
    • Neighbours:響應FindNode訊息,當某節點接到其它節點發來的FindNode訊息時,會回送Neighbours訊息,其中攜帶了此節點的附近節點
    • PingNode:用來檢視節點是否存活。對於缺失NodeID的節點,也可用來詢問其NodeID
    • Pong:對PingNode訊息的響應
  • 協議互動:
    這裡寫圖片描述
    • 在上面的演算法描述中,當前節點會向隨機選定的節點的附近節點集合中每個節點發送FindNode訊息,表示希望查這些節點的附近節點
    • 這些節點在接收到FindNode訊息會需要向傳送節點回送Neighbours訊息,並在此訊息內含有所在節點的附近節點集合
    • 當前節點在收到回送的Neighbours訊息後,會將Neighbours中所攜帶的節點加入到自己的網路節點列表中,並對這些攜帶節點發送Ping訊息
    • 等到Pong的訊息到達,證明此節點存活,並加入到節點列表中