點對點網路組建:從 Kademlia 到 Discv5

買賣虛擬貨幣
如果你一直在研究以太坊或者相關的技術,你可能聽說過 discv4 或 discv5。但這些究竟是什麼呢?它們是如何工作的呢?它們出眾的地方在哪裡呢?想要回答這些問題,我們需要從頭開始梳理一下。這篇博文假定讀者對這個領域比較陌生,因此沒有技術背景的人也可以閱讀。開篇故事的開端:在 P2P(peer-to-peer) 網路中,節點的相互發現及網路成型的過程會面臨一些問題。早年間的 P2P 檔案共享技術,比如 Napster,使用單個伺服器共享資訊,資訊中記錄誰擁有什麼檔案。某個節點向中心伺服器發起連線並提交記錄自己所擁有檔案的列表。另一個節點之後向同一個中心伺服器發起連線,尋找自己所需檔案的儲存節點,然後和找到的節點建立聯絡。然而這是一個有缺陷的系統 —— 系統很容易遭受攻擊,而且中心化伺服器節點可能會吃官司。(譯者注:單個伺服器上儲存檔案內容和節點的對應關係,如果提供了一些受版權保護內容的連結關係,那麼這個中心化伺服器的提供者將直接受到原版權方的法律追責)因此,點對點網路亟需另一種解決方案。研究者們經過數年研究和實驗,提出了分散式雜湊表(DHT)。分散式雜湊表
2001 年,研究者們為 DHT 提出了 4 種新的協議,分別是 Tapestry、Chord、CAN 以及 Pastr,這 4 個協議在核心功能上各有取捨和改變,因此擁有不同的特性。上文中一直都在說 DHT。那麼 DHT 到底是什麼呢?分散式雜湊表(DHT)是一個分散式的鍵值列表。參與到 DHT 的節點可以很輕鬆地檢索到某個鍵對應的值。假定一個網路中,有 9 個鍵值對和 3 個節點,理想情況下,每個節點只需要儲存 3 個鍵值對(最好的方式是儲存6個鍵值對,以提供冗餘),意味著如果要更新某個鍵值對,只有部分網路節點需要更新。大致想法是這樣的,網路中的任何節點都可以基於資訊在節點間分佈的方式,知道要去哪裡尋找它所需要的特定鍵值對。Kademlia現在我們知道 DHT 是什麼了,那我們來看看 discv4 的前身 Kademlia。Kademlia 是 Petar Maymounkov 和 David Mazières 於 2002 年發明的 DHT 協議。我覺得這個協議可能是最流行,而且使用最廣泛的 DHT 協議。它的工作原理很簡單,讓我們來看看吧。
在 Kademlia 中,節點和值透過距離來排列(其排列有嚴格數學化的定義)。這裡的距離不是地理位置上的距離,而是基於識別符號的表示方法。透過使用一些距離函式,可以計算出兩個識別符號之間的距離。Kademlia 使用 XOR(異或運算子) 作為距離函式。XOR 函式的特點在於,只有當輸入不同時,輸出才為 true。下面是用二進位制識別符號表示的例子。XOR 10011001    00110010    --------    10101011
上面的這個例子是說,十進位制數字 153 和 50 之間的距離是 171。使用 XOR 作為距離函式有很多原因,包括:1. 某個 ID 與它自己的距離是 0。2. 距離是對稱的,A 到 B 的距離和 B 到 A 的距離相同。3. 遵循三角不等式,如果 A,B,C 是三角形上的三點,那麼 A 到 B 的距離,小於或等於 A 到 C 的距離加上 B 到 C 的距離。綜上,節點可以根據距離函式來確定哪個節點離它更近,並基於這種 “距離” 來做決策。
Kademlia 節點儲存著一個路由表。路由表中包含多個列表。每後一個列表所記載的節點都比前一個列表中的節點離得遠一點。每個節點維護離自己最近節點的資訊;另一個節點離得越遠,本地節點儲存的相關資訊就越少。假定我想要找到一個特定的節點。我要做的就是向我已知的節點傳送請求,這些節點返回他們的記錄中離我的目標節點更近的鄰居節點。我重複此過程,直到某群鄰居幫我找到目標節點。對值來說也是同樣的過程。值跟節點之間的距離是確定的,因為值和節點的識別符號 ID 以相同的方式組織,因此我們可以計算這個距離。如果我想查詢一個值,我只需要尋找離這個值的鍵最近的鄰居節點,直到找到儲存這個值的節點。為了讓 Kademlia 節點支援這些功能,協議透過下面這些訊息來通訊。· PING - 用來檢測一個節點是否還在執行。· STORE - 在一個節點上儲存給定鍵的值。
· FINDNODE - 向給定 ID 返回所請求的最近節點。· FINDVALUE - 和 FINDNODE 一樣,區別在於,如果一個節點儲存著特定的值,它將會直接將值返回。這是對 Kademlia 的一個非常簡化的講解,中間跳過了各種重要的細節。想要更全面的瞭解,力薦原論文或者更深層次的設計規範。Discv4對背景做好鋪墊之後,終於來到 discv4(表示 discovery v4) 了,這是以太坊當前的節點發現協議。Discv4 協議本身是基於 Kademlia 的,但在某些部分做了改動。例如,discv4 中不再使用 DHT 中的值部分。Kademlia 主要用於網路的組織,因此我們可以使用路由表定位其他節點。但 discv4 中完全不使用 DHT 中的值部分,因此我們可以拋棄 Kademlia 中使用的命令 FINDVALUE 和 STORE。
前文中,Kademlia 的查詢方法描述了節點如何得到對等節點。節點向另一些節點發起請求,得到離自己更近的節點。重複此請求過程,直到無法找到任何新的節點。此外,discv4 新增了相互的終端驗證功能。這是為了確保發起 FINDNODE 請求的節點正在參與同一個節點發現協議。最後,所有的 discv4 節點都應該維護最新的 ENR 記錄。記錄裡包含一個節點的資訊。任何節點都可以使用特定於 discv4 的包,叫做 ENRRequest,去請求 ENR 記錄。如果你想知道關於 ENRs 的更多細節,請移步至我的另一篇博文 Network Addresses in Ethereum。然而,discv4 也引入了一些問題。讓我們來看看其中的幾個。首先,按照 discv4 目前的工作方式,是無法區分節點間的次級協議的。也就是說,如果一個以太坊節點將以太坊 Classic 節點,Swarm 或 Whisper 節點加入它的 DHT,那麼只有和這些節點發生多次通訊之後,才能發現這些節點的無效性。這種無法區分次級協議的能力使得它很難找到特定的節點,比如支援輕客戶端的以太坊節點。
其次,為了防禦重放攻擊,discv4 使用了時間戳。當某個主機的時鐘發生錯誤時,這種方式會導致各種各樣的問題。欲瞭解更多詳情,請查閱 discv4 規範的 “Known Issues” 部分。最後,終端的互驗證工作中也存在問題。因為資訊有丟包的可能,所以沒有辦法斷定兩個對等節點是否都已驗證過對方。也就是說,我們可能自認為已經被驗證過了,但跟我們通訊的對等節點卻並不這麼認為;他們可能會因此丟棄我們的 FINDNODE 包。最後,終端的互驗證工作中也存在問題。因為資訊有丟包的可能,所以沒有辦法斷定兩個對等節點是否都已驗證過對方。也就是說,我們可能自認為已經被驗證過了,但跟我們通訊的對等節點卻並不這麼認為;他們可能會因此丟棄我們的 FINDNODE 包。Discv5最後,讓我們來看一下 discv5。Discv5 是 discv4 的迭代版本,將作為 Eth 2.0 的節點發現協議。Discv5 旨在修復 discv4 中存在的諸多問題。第一個改變是 FINDNODE 的工作方式。傳統的 Kademlia 以及 discv5 都使用識別符號。而在 discv5 中,我們使用對數距離,也就是說,傳送 FINDNODE 請求後,響應中包含的節點,都與傳送方節點在特定的對數距離內。
對數距離指:先計算出距離,然後使用以 2 為底數的 log 函式,即 log2(A xor B)。其次一個很重要的改變就是 discv5 一直致力於解決的,存在於 discv4 的最大問題:次級協議的區分。Discv5 新增了主題表(topic tables)。主題表是先進先出的列表,表中包含提供特定服務的節點。節點透過在對等節點中註冊廣告將自己新增進這個列表。截至本文寫作之時,這個次級協議區分方案中的寫操作依然存在一些問題。對一個節點來說,目前沒有有效的方法將廣告發布在多個對等節點上,因此需要向每個對等節點傳送單獨的請求,這對於大規模網路來說效率很低。此外,一個節點向多少個對等節點上釋出廣告,以及向哪些對等節點投放都是不清楚的。更多詳情請查閱 devp2p#136 。Discv5 中還有很多小的改變,但是這些改變沒那麼重要,因此在這篇總結中就省略了。雖然 discv5 解決了一些 discv4 中存在的問題,但還有一些問題,discv5 仍沒有解決,比如不可靠的終端驗證。寫這篇博文之時,discv5 還沒有提出新的方法去提升終端驗證的處理過程。
正如你所見,discv5 的工作仍在進行中,目前還需要克服一些很大的挑戰。如果這個協議解決了這些問題,那麼它將會是對原始 Kademlia 實現的一個巨大提升。希望這篇文章能幫助你理解什麼是發現協議以及發現協議是如何工作的。如果你對整個協議感興趣,可以在 github 上查閱。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;