以太坊源码照抄 eth/handler
哈哈笑417
发表于 2023-1-5 18:37:02
170
0
0
eth主要的同步txs,block,header的入口都在这个文件里
type ProtocolManager struct {
..., n$ J" ]6 \2 f( K/ `0 i5 S2 X
downloader *downloader.Downloader // 名字是downloader 其实是就是在接受到数据后插入数据库
fetcher *fetcher.Fetcher // 声明新的块; I' S* Z: P% W
peers *peerSet3 I- @7 b- { M1 w
SubProtocols []p2p.Protocol
...
方法 NewProtocolManager初始化一个ProtocolManager结构
这一步有一个重要的内容就是append(SubProtocols, p2p.Protocols{})
manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
Name: ProtocolName,
Version: version,/ R" J0 T9 g. p0 ?
Length: ProtocolLengths,
Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {7 A' t. B) y3 O/ f% w. t5 k4 p
peer := manager.newPeer(int(version), p, rw)6 U6 {# _8 D! |* K5 o9 Y6 c5 ?4 z
select {2 u. m+ |5 P+ K
case manager.newPeerCh " u8 U4 r/ h a6 y; W) p
func pm.handle(). Z( R: ~' K% x0 s" v) k
这里newPeerCh接收到peer后调用pm.handle, 与pm同步txs,同时p同步pm.whiteList中的header
for number := range pm.whitelist {
if err := p.RequestHeadersByNumber(number, 1, 0, false); err != nil {
return err) h) a- A* O0 }
}
}5 a4 T1 O' ~, m [. d# ~# h. J
同时进入循环处理来自peer的消息
for {
if err := pm.handleMsg(p); err != nil {+ u8 `3 a O" S0 s3 o7 P
p.Log().Debug("Ethereum message handling failed", "err", err)
return err
}
}
func pm.handleMsg(p *peer). m# C' |2 R3 p
这个函数根据msg, err := p.rw.ReadMsg() msg的类型做出不同的处理,塞到fetcher 或者downloader中去等等
func.pm.BroadcastTxs(tx)5 S/ z2 m( l8 i2 c5 t0 m
找到pm.peers.PeersWithoutTx(tx.Hash()) 然后把tx塞给他& ?8 w V4 C- V
这个函数在 接受到消息时就会被调用
func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool)
这个就如题吧1 L# }' o: L3 k
参数propagate为true就选出前Math.sqrt(peersLen)个节点,传播出块消息参数propagate为false 简单向所有节点声明我有这个块
7 a( m+ s" {) z1 D
调用:range pm.minedBlockSub.Chan() 如果管道里有消息会执行以下代码$ y0 @+ W- V: q. ^* J
pm.BroadcastBlock(ev.Block, true) // First propagate block to peers
pm.BroadcastBlock(ev.Block, false) // Only then announce to the rest
成为第一个吐槽的人