第10講 | 深入區塊鏈技術(二):P2P網絡


  在上一篇文章中,我大致講解了一下區塊鏈技術的幾個核心要素。P2P網絡協議、分布式一致性算法(共識機制)、加密簽名算法、賬戶與存儲模型。今天我們就來看看區塊鏈技術的第一個核心要素:P2P網絡。

  如果我們簡單來看P2P技術,它的應用領域已經非常廣泛了,從流媒體到點對點通訊、從文件共享到協同處理,多種領域都有它的身影出現。

  同樣的,P2P的網絡協議也有很多,比較常見的有BitTorrent、ED2K、Gnutella、Tor等,也就是我們常說的BT工具和電驢。

  比特幣、以太坊等眾多數字貨幣都實現了屬於自己的P2P網絡協議,但是這種模式並不同於以上討論的P2P網絡協議,所以我們今天討論的重點主要是區塊鏈技術的P2P技術,也就是比特幣和以太坊的P2P網絡。

  由於區塊鏈的P2P網絡技術知識繁多,我們主要提煉其中的四個內容進行講解:區塊鏈的網絡連接與拓撲結構、節點發現、局域網穿透與節點交互協議。

  希望讀完本篇可以讓你對目前成熟的區塊鏈P2P網絡的拓撲結構以及運行原理有個大體的認知。

網絡連接與拓撲結構

  1.網絡連接

  除去少數支持UDP協議的區塊鏈項目外,絕大部分的區塊鏈項目所使用的底層網絡協議依然是TCP/IP協議。

  所以從網絡協議的角度來看,區塊鏈其實是基於TCP/IP網絡協議的,這與HTTP協議、SMTP協議是處在同一層,也就是應用層。

  在“區塊鏈的常見誤區”這篇文章中,我們提到了“區塊鏈是否會顛覆互聯網”這一說法,如果要是認真分析的話,它顛覆的層面其實最多只到HTTP協議,不能再多了。

  以HTTP協議為代表的、與服務端的交互模式在區塊鏈上被徹底打破了,變更為完全的點對點拓撲結構,這也是以太坊提出的Web3.0的由來。

  比特幣的P2P網絡是一個非常復雜的結構,考慮到礦池內部的挖礦交互協議與輕節點。我們僅僅討論全節點這種場景下的P2P網絡發現與路由。

  比特幣的P2P網絡基於TCP構建,主網默認通信端口為8333。

  以太坊的P2P網絡則與比特幣不太相同,以太坊P2P網絡是一個完全加密的網絡,提供UDP和TCP兩種連接方式,主網默認TCP通信端口是30303,推薦的UDP發現端口為30301。

  2.拓撲結構

  P2P網絡拓撲結構有很多種,有些是中心化拓撲,有些是半中心化拓撲,有些是全分布式拓撲結構。

  比特幣全節點組成的網絡是一種全分布式的拓撲結構,節點與節點之間的傳輸過程更接近“泛洪算法”,即:交易從某個節點產生,接着廣播到臨近節點,臨近節點一傳十十傳百,直至傳播到全網。

  

  (比特幣全球節點圖,圖來自網絡)

  全節點與SPV簡化支付驗證客戶端之間的交互模式,更接近半中心化的拓撲結構,也就是SPV節點可以隨機選擇一個全節點進行連接,這個全節點會成為SPV節點的代理,幫助SPV節點廣播交易。

節點發現

  節點發現是任何區塊鏈節點接入區塊鏈P2P網絡的第一步。這與你孤身一人去陌生地方旅游一樣,如果沒有地圖和導航,那你只能拽附近的人問路,“拽附近的人問路”的這個動作就可以理解成節點發現。

  節點發現可分為初始節點發現,和啟動后節點發現。初始節點發現就是說你的全節點是剛下載的,第一次運行,什么節點數據都沒有。啟動后發現表示正在運行的錢包已經能跟隨網絡動態維護可用節點。

  1.初始節點發現

  在比特幣網絡中,初始節點發現一共有兩種方式。

  第一種叫做DNS-seed,又稱DNS種子節點,DNS就是中心化域名查詢服務,比特幣的社區維護者會維護一些域名。

  比如seed.bitcoin.sipa.be這個域名就是由比特幣的核心開發者Sipa維護的,如果我們通過nslookup會發現大約二十多個A紀錄的IPv4主機地址。

  我們通過nc命令嘗試連接域名下的某個主機的8333端口會發現連接成功,運行結構如下。

 1 ✘ chenhao@chenhaodeMacBook-Pro  ~  nc -nvv 149.202.179.35 8333
 2 found 0 associations
 3 found 1 connections:
 4      1: flags=82<CONNECTED,PREFERRED>
 5  outif en0
 6  src 192.168.1.104 port 62125
 7  dst 149.202.179.35 port 8333
 8  rank info not available
 9  TCP aux info available
10 Connection to 149.202.179.35 port 8333 [tcp/*] succeeded!

  好的,到目前為止我們已經手動做了一遍初始節點發現的工作,這些操作是由比特幣的代碼完成的。

  第二種方式就是,代碼中硬編碼( hard-code )了一些地址,這些地址我們稱之為種子節點(seed-node),當所有的種子節點全部失效時,全節點會嘗試連接這些種子節點。

  用在以太坊中,思路也大致相同,也是在代碼中硬編碼(hard-code)了一些種子節點做類似的工作。

  2.啟動后節點發現

  在Bitcoin 的網絡中,一個節點可以將自己維護的對等節點列表(peer list)發送給臨近節點,所以在初始節點發現之后,你的節點要做的第一件事情就是向對方要列表:“快把你的節點列表給我復制一份。”

  所以在每次需要發送協議消息的時候,它會花費固定的時間嘗試和已存的節點列表中的節點建立鏈接,如果有任何一個節點在超時之前可以連接上,就不用去DNS seed 獲取地址,一般來說,這種可能性很小,尤其是全節點數目非常多的情況下。

  而在以太坊網絡中,也會維護類似的一個節點列表(NodeTable),但是這個節點列表與比特幣的簡單維護不同,它采用了P2P網絡協議中一個成熟的算法,叫做Kademlia網絡,簡稱KAD網絡。

  它使用了DHT來定位資源,全稱Distributed Hash Table,中文名為分布式哈希表。KAD網絡會維護一個路由表,用於快速定位目標節點。由於KAD網絡基於UDP通信協議,所以以太坊節點的節點發現是基於UDP的,如果找到節點以后,數據交互又會切換到TCP協議上。

  3.黑名單與長連接

  公有區塊鏈面臨的網絡環境是非常開放的,任何人只要下載好錢包,打開運行就進入了這個P2P網絡,這也會帶來被攻擊的可能。

  所以在比特幣的代碼中,會有一段去控制邏輯,你可以手動將你認為可疑的節點移除並加入禁止列表,同時去配置可信的節點。當然,以上並不屬於客戶端的標准協議的一部分,任何人都可以實現屬於自己的P2P網絡層。

  以太坊上有針對賬戶進行的黑名單處理,但是這屬於業務層。我沒有找到很詳盡的資料,所以你有興趣的話,可以自己嘗試一下。

  不過總的來說,黑名單我們也可以通過操作系統的防火牆去處理,這並不算一個特別棘手的問題。

局域網穿透

  前面我們說到了區塊鏈的P2P網絡結構是一種全分布式的拓撲結構。但是,如今我們的網絡環境是由局域網和互聯網組成的。也就是說,當你在局域網運行一個區塊鏈節點,在公網是發現不了的,公網上的節點只能被動接受連接,並不能主動發起連接。

  如果這個局域網是你可以控制的,那么很好說,咱們只需要在VPC網絡中配置路由,將公網IP和端口映射到局域網中你的IP和端口即可。

  這個條件是非常苛刻的,那么到底有沒有一種方案可以自行建立映射呢?答案是:有,就是NAT技術和UPnP協議。

  NAT技術非常常見,這里使用的是源NAT,簡而言之就是替換TCP報文中的源地址並映射到內網地址。

  UPnP是通用即插即用(Universal Plug and Play)的縮寫,它主要用於設備的智能互聯互通,所有在網絡上的設備馬上就能知道有新設備加入。

  這些設備彼此之間能互相通信,更能直接使用或者控制它,一切都不需要人工設置。有關UPnP的資料比較多,這里就不贅述了,你可以自行搜索相關的信息。

  比特幣和以太坊均使用了UPnP協議作為局域網穿透工具,只要局域網中的路由設備支持NAT網關功能、支持UPnP協議,即可將你的區塊鏈節點自動映射到公網上。

節點交互協議

  一旦節點建立連接以后,節點之間的交互是遵循一些特定的命令,這些命令寫在消息的頭部,消息體寫的則是消息內容。

  命令分為兩種,一種是請求命令,一種是數據交互命令。

  節點連接完成要做的第一件事情叫做握手操作。這一點在比特幣和以太坊上的流程是差不多的,就是相互問候一下,提供一些簡要信息。

  比如先交換一下版本號,看看是否兼容。只是以太坊為握手過程提供了對稱加密,而比特幣沒有。

  握手完畢之后,無論交互什么信息,都是需要保持長連接的,在比特幣上有PING/PONG這兩種類型的消息,這很明顯就是用於保持節點之間長連接的心跳而設計的;而在以太坊的設計中,將PING/PONG協議移到了節點發現的過程中。

  請求命令一般分為發起者請求,比如比特幣中的 getaddr 命令是為了獲取對方的可用節點列表,inv命令則提供了數據傳輸,消息體中會包含一個數據向量。

  我們說區塊鏈最重要的功能就是同步區塊鏈,而同步區塊恰巧是最考驗P2P網絡能力的。區塊同步方式分為兩種,第一種叫做HeaderFirst,它提供了區塊頭先同步,同步完成以后再從其他節點獲得區塊體。

  第二種叫做BlockFirst,這種區塊同步的方式比較簡單粗暴,就是從其他節點獲取區塊必須是完整的。第一種方案提供了較好的交互過程,減輕了網絡負擔。這兩種同步方式會直接體現在節點交互協議上,他們使用的命令邏輯完全不同。

總結

  今天我與你分享了區塊鏈的P2P網絡結構與節點交互過程,一般P2P網絡技術要解決兩個主要問題,第一是資源定位,第二是資源獲取,這一篇文章也是主要圍繞這兩點展開,其中節點發現和局域網穿透是屬於資源定位問題,節點交互協議是屬於資源獲取問題。

  在這一篇文章中,我僅以比特幣和以太坊為例進行分享,雖然區塊鏈項目比較多,但是他們要做的事情大多是類似的,比如以太坊是改進版的實現,而比特幣使用了簡單版實現。

  P2P網絡模塊作為所有區塊鏈的最底層模塊,直接決定了整個區塊鏈網絡的穩定性。區塊鏈網絡是一個網狀分布式的結構,與互聯網結構有點相似,那么,親愛的讀者,我們是不是可以設計一個節點爬蟲,去爬全網節點呢?你可以給我留言,我們一起討論。

  感謝你的收聽,我們下次再見。

--------文章來自《極客時間》深入淺出區塊鏈專欄


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM