以太坊P2P模組節點發現演算法剖析
阿新 • • 發佈:2018-12-22
核心資料結構:
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的訊息到達,證明此節點存活,並加入到節點列表中