Libp2p學習
參考資料:libp2p-specifications : https://github.com/libp2p/specs
持續更新ing
1. 介紹
Libp2p的實現目標是:
- 支持各種各樣的傳輸方式:
- 傳輸:TCP,UDP,SCTP,UDP,uTP,QUIC,SSH,etc.
- 安全傳輸:TLS,DTLS,CurveCP,SSH
- 有效使用sockets(連接重用)
- 允許端點之間的交流可以在一個socket上復用(避免過多的握手)
- 允許端點之間通過一個協商過程使用多協議以及各自的版本
- 向后兼容
- 在現在的系統中可以運行
- 充分使用當前網絡技術的能力
- 實現NAT轉換
- 實現連接中繼
- 實現加密通道
- 充分使用基礎傳輸(例如原生的流復用等)
傳統的7層OSI模型表征不適合libp2p。Libp2p根據協議的角色(功能)進行划分。不同的lip2p協議可以具有相同的功能,例如,bootstrap lists,mDNS,DHT discovery,PEX都進行節點發現,但他們可以同時存在甚至協同工作。而在OSI中,每一層通常都只有一個協議。
2. 基礎
libp2p使用了multiaddr,一個自描述的地址形式,可以理解為不同協議不同地址類型的一個封裝。這使得libp2p可以不透明的處理系統中的所有地址,支持網絡層中的各種傳輸協議。
libp2p的協議是多個協議的集合。為了節約資源並使連接更容易,libp2p可以通過一個端口執行所有操作,它可以通過點對點連接復用其眾多協議。這種多路復用適用於可信賴的流連接或者不可信賴的數據報。libp2p的目標是變得更加模塊化和靈活,以適應於各種應用場景。
libp2p中的交流可以是加密、簽名或者是明文。它使用了TLS這樣的加密模型,但並不是整個TLS。它只使用了TLS模型中用於加密的最小的一部分。
由於對稱NAT,容器以及虛擬機NAT和其他的不能繞過的NAT,libp2p必須使用中繼通信來建立一個全連接圖。中繼應該是可選的,能夠被用戶關閉。連接中繼應該作為transport實現,以對上層透明。
libp2p中支持結構化、非結構化、混合以及中心化的網絡拓撲結構。它也解決了網絡中資源的發現問題。高效的消息傳輸協議可以提供低延遲的傳輸或更大更復雜的網絡拓撲結構。libp2p試圖利用Multicast和PubSub一起來滿足該需求。libp2p也支持命名。
3. 架構
libp2p根據Unix哲學來設計,創建了易於理解和測試的小組件。這些組件應當可以被交換以適用於不同的技術或者場景,同時也應當能夠隨着時間來對它們進行不斷的升級與更新。
雖然不同的節點可能會支持不同的協議,但任何一個節點都可以充當dialer或者listener。建立的連接可以被連接兩端的節點重用,消除了客戶端和服務端之間的差別。
libp2p的接口將許多節點之間通信所必需的子系統連接起來。這些子系統的主要工作區域有:
- 節點路由:決定哪些節點用於路由特定的消息。這個路由的過程可以是遞歸、迭代的完成的,也可以是以廣播、組播的形式完成。
- Swarm:處理libp2p中所有和"開啟一個流"相關的事情,包括協議復用、流復用、NAT轉換和連接中繼。
- 分布式記錄存儲:用於存儲和分發記錄的系統。記錄是其他系統用於發信號、建立鏈接、宣布節點或內容等等的小條目。在更廣泛的互聯網中,它們與DNS的作用類似。
- 發現:找到網絡中的其他節點
系統架構如下圖所示:
┌─────────────────────────────────────────────────────────────────────────────────┐
│ libp2p │
└─────────────────────────────────────────────────────────────────────────────────┘
┌─────────────────┐┌─────────────────┐┌──────────────────────────┐┌───────────────┐
│ Peer Routing ││ Swarm ││ Distributed Record Store ││ Discovery │
└─────────────────┘└─────────────────┘└──────────────────────────┘└───────────────┘
3.1 節點路由
節點路由子系統暴露出一些接口,用來確定一條消息應該被路由到DHT中的哪些節點。它接受一個key,且返回一個或多個PeerInfo對象。以下是兩個節點路由子系統的實例,第一個基於Kademlia DHT,第二個基於mDNS。然而,只要實現了同樣的功能和接口,其他的節點路由機制也可以被實現。
kad-routing實現了Kademlia路由表,每個節點都保存着一個k桶集合,每個k桶中都包含着幾個來自網絡中其他節點的PeerInfo對象。
mDNS-routing使用mDNS探測來識別局域網節點是否有指定的key或者他們是否在線。
3.2 Swarm
流復用器必須實現指定的接口:interface-stream-muxer
協議復用是在應用層實現的,而不是傳統的端口層(不同的服務/協議監聽不同的端口)。這使得我們能夠在一個socket上復用多個協議,從而節省了對多個端口進行NAT轉換的消耗。協議復用是通過multistream
完成的,multistream
是一個協議,它使用multicodec
來協調不同類型的流或協議。
關於中繼:
由於NAT,反向代理,防火牆或不支持相同的傳輸(例如,go-ipfs與browser-ipfs),中繼在某些情況下是很有必要的。中繼連接使用起來和常規的連接差不多,也同樣是端對端加密的。中繼線路既是隧道傳輸,也是Swarm協議。傳輸是建立與接受連接的工具,swarm協議是中繼連接的工具。
3.3 分布式記錄存儲
此部分原文中無內容,我也暫時懶得去看。
3.4 發現
mDNS-discovery:
mDNS-discovery是一種局域網上使用mDNS的發現協議。它發出mDNS信標來探測是否有更多可獲得的節點。由於低延遲的特性,局域網節點是非常適用p2p協議的。
mDNS-discovery是一個獨立的協議,不依賴於任何其它的libp2p協議。mDNS-discovery能夠發現局域網中可用的節點,而不需要依賴於其它的基礎組件。在內網、不與Internet骨干網連接的網絡、暫時失去連接的網絡中,這樣做是非常有用的。
mDNS-discovery可以按照服務配置(例如,僅僅發現加入特定協議的節點,比如ipfs),也支持私有網絡(發現屬於同一個私有網絡的節點)。
libp2p開發者正在探索讓mDNS-discovery信標加密的方法(這樣可以讓局域網中的其他節點無法識別正在使用的服務),盡管mDNS的性質總會暴露出本地IP地址。
random-walk:
Random-walk是DHT(以及其它有路由表的協議)的發現協議。它會進行隨機DHT查詢,以便快速了解到大量的節點。這使得DHT(或其他協議)收斂的更快,其代價是一開始時的小負載。
boostrap-list:
Bootstrap-List是一種發現協議,它使用本地存儲來緩存網絡中可用的、高度穩定且可信的節點地址。這允許協議發現網絡的其余部分。這本質上和DNS引導自身的方式基本相同。
這個列表應該被存儲到長期本地存儲中,無論這對本地節點意味着什么(例如,對磁盤而言)。該協議可以發送一個硬編碼的默認列表,也可以附帶標准代碼分發(如DNS,好吧這一段可以看看原文?翻譯不出來…)。在大多數情況下(包括IPFS),bootstrap列表應該是用戶可配置的,因為用戶可能希望建立單獨的網絡,或者信任特定的節點。
4. 接口
libp2p是多個協議的集合,它們共同協作,提供了可以與其它網絡可尋址進程通信的通用實體接口。實現方式為:將當前存在的協議和實現填充進一組確定的接口中:Peer Routing,Discovery,Stream Muxing,Transports,Connections等。
**libp2p: **libp2p是頂層模塊,它為其它構成libp2p實例的模塊提供接口,接口中必須包括對其它節點的撥號(dial)、對所有我們想要支持的模塊的插拔。
**Peer Routing: ** 該模塊為一個libp2p節點提供了找到另一個節點的PeerInfo的方式,這樣它就可以向另一個節點發起撥號。最基本的功能為:一個Peer Routing模塊應該有這樣一個接口:輸入一個"key",返回一個PeerInfo的集合。
Peer Discovery: 該模塊應該返回PeerInfo對象,因為它找到了一些新的節點,這些節點應該被我們的Peer Routing模塊考慮進去。
Swarm、Transport、Connection、Stream Muxing、Distributed Record Store略。
5. 性質
5.1 通信模塊-Streams
網絡層處理所有關於連接到一個節點的問題,並且暴漏出簡單的雙向流。用戶既可以打開一個新的流(NewStream),也可以注冊一個流處理器(SetStreamHandler)。之后用戶可以自由的實現他想要的任何消息傳遞協議。這使得構造一個p2p協議更簡單,因為連接、多傳輸支持、流控制等的復雜度得到了處理。