以太坊原始碼分析(14)P2P分析
#概述
Kademlia(簡稱Kad)是一種分散式雜湊表技術,用於建立p2p網路拓撲結構。
基本原理就是以兩個節點ID的異或值作為兩節點間的距離d,每個節點都將其他節點的資訊儲存到稱之為K桶的表結構中,該表結構按照d的為1的最高bit位分層(可理解為桶索引),每層中儲存最多K個節點資訊。如下:
| I | 距離範圍 | 鄰居 |
|:---:|:---------:|:-----------:|
| 0 |[2^0, 2^1 ) | (IP,UDP,NodeID) <br>...|
| i |[2^i, 2^i+1 ) | (IP,UDP,NodeID) <br>...|
節點查詢時,通過詢問距離自己最近的a個節點,讓對方返回距離目標最近的a個節點,重複這個過程直到找到目標節點或者能問的都問了一遍。
參考資料:
[references/Kademlia協議原理簡介.pdf](references/Kademlia協議原理簡介.pdf)
[https://www.jianshu.com/p/f2c31e632f1d](https://www.jianshu.com/p/f2c31e632f1d)
#以太坊中的實現概述
##幾個概念
1. 計算距離的ID值,位數代表了有多少個K桶,經典演算法中是160位的。在以太坊中,NodeID為節點的PublicKey,__參與距離計算的是NodeID的sha3雜湊值,長度256位__。
2. K桶的項數不超過K,K值是為平衡系統效能和網路負載而設定的一個常數,但必須是偶數。eth中K=16。
3. 查詢鄰居節點時,返回節點數最多是a個,a也是為了系統優化而定的引數,eth中 a=3。
##資料結構及儲存
* p2p模組使用獨立的leveldb持久化儲存所有的鄰居節點資訊,從而節點重新啟動時能直接利用歷史上已找到的節點。
* 儲存的key為NodeID,value為Node結構體,包含IP、UDP、TCP、ID(即NodeID)等資訊。
##p2p網路維護的實現
table.go主要實現了p2p的Kademlia協議。其中定義了K桶的結構並實現節點的維護策略。
###啟動過程
節點啟動時,初始化配置資訊後,會啟動p2p server,在server啟動過程中,會執行udp物件建立、table物件建立、監聽udp埠等處理。table物件建立中就包含了啟動goroutine執行節點發現及維護的服務。
1. 從leveldb中隨機選取若干種子節點(新節點第一次啟動時,使用啟動引數或原始碼中提供的啟動節點作為種子節點),出入桶結構中(記憶體);
2. 啟動後臺過期goroutine,負責從leveldb中刪除過期的資料(stale data);
3. 啟動loop,後臺執行節點重新整理、重驗證等處理。下面寫的步驟就在這個goroutine中;主要就是doRefresh:
4. 載入種子節點
5. 以自身為目標執行查詢
6. 迴圈3遍:隨機生成目標,執行查詢。
###鄰居節點發現流程 table.lookup
~~~
1. 在本地K桶中查詢距離target最近的一批節點,最多bucketSize個(16個);記為result;(節點加入result的邏輯:從列表中查詢節點i,使得d(i,target) > d(n,target);如果列表中還有空間,直接加入節點n;如果找到了有效的i,則用n替換i位置的節點)
2. 如果步驟1沒有找到節點,則等待重新整理完成(遺留:這裡尚未看懂);
3. 從result中併發發起alpha個(3個)查詢,向對方詢問距離target最近的若干節點(udp.findnode);
4. 若查詢失敗,更新失敗節點資訊,若該節點總失敗次數達到maxFindnodeFailures次(5次),則從本地移除該節點資訊;
5. 若查詢成功,對返回的節點執行bondall處理(__注意:這裡會執行更新K桶的操作,不管pingpong是否成功,都會加入K桶。__如果某個節點總是連不上,會被重新整理機制刪掉的),去掉不線上節點;對線上節點建立連線;
6. 對線上節點,如果未見過,則按照步驟1的規則加入result中;
7. 迴圈從3開始的步驟,直到result中的所有節點都查詢過了;
8. 返回result中的節點。
~~~
###節點連線及本地K桶維護流程 table.bond
在lookup中會對返回的節點執行bondall處理,bondall中主要是對每個節點執行bond處理。
bond確保本地節點和給定的遠端節點有一個連線,如果連線成功,會放到本地一個連線table中。在執行findnode之前,必須有連線已建立。活躍的連線數有一定限制,以便限制網路負載佔用。
不管pingpong是否成功,節點都會更新到本地K桶中。
~~~
1. 如果節點有一段時間沒出現了或者對他執行findnode失敗過,則執行pingpong;
2. 無論前述步驟是否執行或執行是否成功,都執行更新節點到K桶的處理。
~~~
__節點n更新到本地K桶:__
1. 獲取n對應的K桶:設距離為d,計算log2(d)。實現上是獲取d二進位制表示時的最高位1所在的位置。若結果≤ bucketMinDistance(239),返回K[0],否則返回 K[結果-bucketMinDistance-1];
2. 如果n在K桶中已經存在,則將其移到最前面;否則如果K桶未滿,則加進去;
3. 如果n沒進入K桶中,則將其維護進候選列表中。
~~~
// add attempts to add the given node its corresponding bucket. If the
// bucket has space available, adding the node succeeds immediately.
// Otherwise, the node is added if the least recently active node in
// the bucket does not respond to a ping packet.
//
// The caller must not hold tab.mutex.
func (tab *Table) add(new *Node) {
tab.mutex.Lock()
defer tab.mutex.Unlock()
b := tab.bucket(new.sha)
if !tab.bumpOrAdd(b, new) {
// Node is not in table. Add it to the replacement list.
tab.addReplacement(b, new)
}
}
~~~
網址:http://www.qukuailianxueyuan.io/
欲領取造幣技術與全套虛擬機器資料
區塊鏈技術交流QQ群:756146052 備註:CSDN
尹成學院微信:備註:CSDN
相關文章
- 以太坊原始碼分析(36)ethdb原始碼分析原始碼
- 以太坊原始碼分析(38)event原始碼分析原始碼
- 以太坊原始碼分析(41)hashimoto原始碼分析原始碼
- 以太坊原始碼分析(43)node原始碼分析原始碼
- 以太坊原始碼分析(52)trie原始碼分析原始碼
- 以太坊原始碼分析(51)rpc原始碼分析原始碼RPC
- 以太坊原始碼分析(18)以太坊交易執行分析原始碼
- 以太坊原始碼分析(37)eth以太坊協議分析原始碼協議
- 以太坊原始碼分析(20)core-bloombits原始碼分析原始碼OOM
- 以太坊原始碼分析(24)core-state原始碼分析原始碼
- 以太坊原始碼分析(29)core-vm原始碼分析原始碼
- 以太坊原始碼分析(5)accounts程式碼分析原始碼
- 死磕以太坊原始碼分析之p2p節點發現原始碼
- 以太坊原始碼分析(8)區塊分析原始碼
- 以太坊原始碼分析(9)cmd包分析原始碼
- 以太坊原始碼分析(13)RPC分析原始碼RPC
- 以太坊原始碼分析(16)挖礦分析原始碼
- 以太坊原始碼分析(23)core-state-process原始碼分析原始碼
- 以太坊原始碼分析(34)eth-downloader原始碼分析原始碼
- 以太坊原始碼分析(35)eth-fetcher原始碼分析原始碼
- 以太坊交易池原始碼分析原始碼
- 以太坊原始碼分析(10)CMD深入分析原始碼
- 以太坊原始碼分析(12)交易資料分析原始碼
- 以太坊原始碼分析(19)core-blockchain分析原始碼Blockchain
- 以太坊原始碼分析(26)core-txpool交易池原始碼分析原始碼
- 以太坊原始碼分析(28)core-vm-stack-memory原始碼分析原始碼
- 以太坊原始碼分析(30)eth-bloombits和filter原始碼分析原始碼OOMFilter
- 以太坊原始碼分析(31)eth-downloader-peer原始碼分析原始碼
- 以太坊原始碼分析(32)eth-downloader-peer原始碼分析原始碼
- 以太坊原始碼分析(33)eth-downloader-statesync原始碼分析原始碼
- 以太坊原始碼分析(6)accounts賬戶管理分析原始碼
- 以太坊原始碼分析(39)geth啟動流程分析原始碼
- 以太坊原始碼分析(9)CMD實際操作分析原始碼
- 以太坊原始碼分析(27)core-vm-jumptable-instruction原始碼分析原始碼Struct
- 以太坊原始碼分析(44)p2p-database.go原始碼分析原始碼DatabaseGo
- 以太坊原始碼分析(45)p2p-dial.go原始碼分析原始碼Go
- 以太坊原始碼分析(46)p2p-peer.go原始碼分析原始碼Go
- 以太坊原始碼分析(48)p2p-server.go原始碼分析原始碼ServerGo