博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
P2P网络数据处理流程
阅读量:5238 次
发布时间:2019-06-14

本文共 3736 字,大约阅读时间需要 12 分钟。

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数据的接收发送。

数据帧结构

123456 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加密然后就退出了。

在这个函数,发送给对方 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确定。

 

原文链接:

 

转载于:https://www.cnblogs.com/blockchain/p/9523964.html

你可能感兴趣的文章
NOIP2015 运输计划 树上差分+树剖
查看>>
P3950 部落冲突 树链剖分
查看>>
读书_2019年
查看>>
读书汇总贴
查看>>
微信小程序 movable-view组件应用:可拖动悬浮框_返回首页
查看>>
MPT树详解
查看>>
空间分析开源库GEOS
查看>>
RQNOJ八月赛
查看>>
前端各种mate积累
查看>>
jQuery 1.7 发布了
查看>>
Python(软件目录结构规范)
查看>>
Windows多线程入门のCreateThread与_beginthreadex本质区别(转)
查看>>
Nginx配置文件(nginx.conf)配置详解1
查看>>
linux php编译安装
查看>>
name phone email正则表达式
查看>>
721. Accounts Merge
查看>>
「Unity」委托 将方法作为参数传递
查看>>
重置GNOME-TERMINAL
查看>>
redis哨兵集群、docker入门
查看>>
hihoCoder 1233 : Boxes(盒子)
查看>>