天天看點

P2P網絡資料處理流程

P2P網絡資料處理流程

監聽(ListenLoop)+撥号(Dial) –> 建立連接配接(SetupConn) –> Enc 握手(doEncHandshake) –> 協定握手(doProtoHandshake) –> 添加Peer Addpeer –> Run Peer

1. Enc握手 doEncHandshake

P2P網絡資料處理流程

監聽時接收到Enc握手:receiverEncHandshake

撥号時發起初始End握手:initiatorEncHandshake

連結的發起者被稱為initiator(主動撥号),連結的被動接受者被成為receiver(被動監聽)。 這兩種模式下處理的流程是不同的,完成握手後, 生成了一個sec可以了解為拿到了對稱加密的密鑰。 然後建立了一個newRLPXFrameRW幀讀寫器,完成加密信道的建立過程。

initiatorEncHandshake 和receiverEncHandshake有些像,但邏輯處理是相反的過程。

P2P網絡資料處理流程
P2P網絡資料處理流程

makeAuthMsg

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

P2P網絡資料處理流程
  • 根據對端的ID計算出對端公鑰remotePub
  • 生成一個随機的初始值initNonce
  • 生成一個随機的私鑰
  • 使用自己的私鑰和對方的公鑰生成的一個共享秘密
  • 用共享秘密來加密這個initNonce
  • 這裡把發起者的公鑰告知對方

這一步,主要是建構authMsgV4結構體。

P2P網絡資料處理流程

sealEIP8

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

P2P網絡資料處理流程

readHandshakeMsg

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

P2P網絡資料處理流程

secrets

secrets函數是在handshake完成之後調用。它通過自己的随機私鑰和對端的公鑰來生成一個共享秘密,這個共享秘密是瞬時的(隻在目前這個連結中存在)。

P2P網絡資料處理流程

這個函數計算出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
      
normal = not chunked

  chunked-0 = First frame of a multi-frame packet

  chunked-n = Subsequent frames for multi-frame packet

  || is concatenate

  ^ is xor

 

Single-frame packet:

header || header-mac || frame || frame-mac

 

Multi-frame packet:

header || header-mac || frame-0 ||

[ header || header-mac || frame-n || ... || ]

header || header-mac || frame-last || frame-mac

 

header: frame-size || header-data || padding

frame-size: 3-byte integer size of frame, big endian encoded (excludes padding)

header-data:

    normal: rlp.list(protocol-type[, context-id])

    chunked-0: rlp.list(protocol-type, context-id, total-packet-size)

    chunked-n: rlp.list(protocol-type, context-id)

    values:

        protocol-type: < 2**16

        context-id: < 2**16 (optional for normal frames)

        total-packet-size: < 2**32

padding: zero-fill to 16-byte boundary

 

header-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ header-ciphertext).digest

 

frame:

    normal: rlp(packet-type) [|| rlp(packet-data)] || padding

    chunked-0: rlp(packet-type) || rlp(packet-data...)

    chunked-n: rlp(...packet-data) || padding

padding: zero-fill to 16-byte boundary (only necessary for last frame)

 

frame-mac: right128 of egress-mac.update(aes(mac-secret,egress-mac) ^ right128(egress-mac.update(frame-ciphertext).digest))

 

egress-mac: h256, continuously updated with egress-bytes*

ingress-mac: h256, continuously updated with ingress-bytes*           

2. 協定握手doProtoHandshake

這個方法比較簡單,加密信道已經建立完畢。 我們看到這裡隻是約定了是否使用Snappy加密然後就退出了。

P2P網絡資料處理流程

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

3. RLPX 資料分幀

P2P網絡資料處理流程

在完成Encode握手之後,調用newRLPXFrameRW方法建立rlpxFrameRW對象,這的對象提供ReadMsg和WriteMsg方法

ReadMsg

P2P網絡資料處理流程

)

1讀取幀頭header

2 驗證幀頭MAC

3 擷取幀體Frame大小

P2P網絡資料處理流程

4 讀取幀體資料

5 驗證幀體MAC資訊

P2P網絡資料處理流程
P2P網絡資料處理流程

6 解密幀體内容(NewCTR à XORKeyStream)

7 解碼幀體(RLP Decode)

8 解析幀體結構(msg.Size & msg.Payload)

P2P網絡資料處理流程

9 snappy解碼

WriteMsg

P2P網絡資料處理流程

1 RLP編碼msg.Code

2 如果snappy,就對讀取payload并進行snappy編碼

P2P網絡資料處理流程

3 寫幀頭header (32位元組)

4 寫幀頭MAC

P2P網絡資料處理流程

5 寫幀體資訊(ptype+payload+padding)

6 寫幀體MAC

4. runPeer

P2P網絡資料處理流程

newPeerHook,建立peer的鈎子函數

廣播PeerEventTypeAdd事件

運作protocol

廣播PeerEventTypeDrop事件

删除peer

run protocol

P2P網絡資料處理流程

1 啟動協程readLoop,讀取消息并根據msg.Code處理消息:

pingMsg->pongMsg

discMsg->RLP解碼msg.Payload傳回reason

其他協定消息處理,根據msg.Code的取值範圍,把msg分給注冊的協定進行處理。

P2P網絡資料處理流程

2 啟動協程pingLoop

根據pingInterval(15秒)定時發送pingMsg消息

P2P網絡資料處理流程

3 啟動協定

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

P2P網絡資料處理流程

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

P2P網絡資料處理流程