P2P網絡數據處理流程
監聽(ListenLoop)+撥號(Dial) –> 建立連接(SetupConn) –> Enc 握手(doEncHandshake) –> 協議握手(doProtoHandshake) –> 添加Peer Addpeer –> Run Peer
1. Enc握手 doEncHandshake

監聽時接收到Enc握手:receiverEncHandshake
撥號時發起初始End握手:initiatorEncHandshake
鏈接的發起者被稱為initiator(主動撥號),鏈接的被動接受者被成為receiver(被動監聽)。 這兩種模式下處理的流程是不同的,完成握手后, 生成了一個sec可以理解為拿到了對稱加密的密鑰。 然后創建了一個newRLPXFrameRW幀讀寫器,完成加密信道的創建過程。
initiatorEncHandshake 和receiverEncHandshake有些像,但邏輯處理是相反的過程。


makeAuthMsg
makeAuthMsg這個方法創建了handshake message。 首先對端的公鑰可以通過對端的ID來獲取。對端的公鑰對於發起者來說是知道的;對於接收者來說是不知道的。

- 根據對端的ID計算出對端公鑰remotePub
- 生成一個隨機的初始值initNonce
- 生成一個隨機的私鑰
- 使用自己的私鑰和對方的公鑰生成的一個共享秘密
- 用共享秘密來加密這個initNonce
- 這里把發起者的公鑰告知對方
這一步,主要是構建authMsgV4結構體。

sealEIP8
sealEIP8對msg進行rlp的編碼,填充一下數據,然后使用對方的公鑰把數據進行加密。

readHandshakeMsg
readHandshakeMsg有兩個地方調用: 一個是在initiatorEncHandshake,另外一個就是在receiverEncHandshake。 這個方法比較簡單, 首先用一種格式嘗試解碼,如果不行就換另外一種。基本上就是使用自己的私鑰進行解碼然后調用rlp解碼成結構體。 結構體的描述就是authRespV4,里面最重要的就是對端的隨機公鑰。 雙方通過自己的私鑰和對端的隨機公鑰可以得到一樣的共享秘密。 而這個共享秘密是第三方拿不到的。

secrets
secrets函數是在handshake完成之后調用。它通過自己的隨機私鑰和對端的公鑰來生成一個共享秘密,這個共享秘密是瞬時的(只在當前這個鏈接中存在)。

這個函數計算出IngressMAC和EgressMAC用於rlpxFrameRW中ReadMsg,WriteMsg數據的接收發送。
數據幀結構
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
|
2. 協議握手doProtoHandshake
這個方法比較簡單,加密信道已經創建完畢。 我們看到這里只是約定了是否使用Snappy加密然后就退出了。

在這個函數,發送給對方 handshakeMsg = 0x00,在readProtocolHandshake中讀取接收對方發過來的handshakeMsg。
3. RLPX 數據分幀

在完成Encode握手之后,調用newRLPXFrameRW方法創建rlpxFrameRW對象,這的對象提供ReadMsg和WriteMsg方法
ReadMsg
)
1讀取幀頭header
2 驗證幀頭MAC
3 獲取幀體Frame大小

4 讀取幀體數據
5 驗證幀體MAC信息


6 解密幀體內容(NewCTR à XORKeyStream)
7 解碼幀體(RLP Decode)
8 解析幀體結構(msg.Size & msg.Payload)

9 snappy解碼
WriteMsg

1 RLP編碼msg.Code
2 如果snappy,就對讀取payload並進行snappy編碼

3 寫幀頭header (32字節)
4 寫幀頭MAC

5 寫幀體信息(ptype+payload+padding)
6 寫幀體MAC
4. runPeer

newPeerHook,建立peer的鈎子函數
廣播PeerEventTypeAdd事件
運行protocol
廣播PeerEventTypeDrop事件
刪除peer
run protocol

1 啟動協程readLoop,讀取消息並根據msg.Code處理消息:
pingMsg->pongMsg
discMsg->RLP解碼msg.Payload返回reason
其他協議消息處理,根據msg.Code的取值范圍,把msg分給注冊的協議進行處理。

2 啟動協程pingLoop
根據pingInterval(15秒)定時發送pingMsg消息

3 啟動協議
startProtocols主要功能是啟動協程運行注冊協議的run函數proto.Run(p, rw),這個rw參數類型是protoRW,它實現的ReadMsg和WriteMsg增加msg.Code取值范圍的處理。不同的protocol有不同的code取值范圍,根據offset和Length確定。

原文鏈接:http://wangxiaoming.com/blog/2018/06/28/HPB-48-ETH-P2P-Net/
