以太坊源码照抄 eth/handler
哈哈笑417
发表于 2023-1-5 18:37:02
162
0
0
eth主要的同步txs,block,header的入口都在这个文件里& f' V( q$ L7 e5 H6 Y
type ProtocolManager struct {
...
downloader *downloader.Downloader // 名字是downloader 其实是就是在接受到数据后插入数据库9 o: }5 Y% Q* X3 g; q/ I
fetcher *fetcher.Fetcher // 声明新的块
peers *peerSet
SubProtocols []p2p.Protocol
.../ Z! p. T% D7 L. ?8 U' m
方法 NewProtocolManager初始化一个ProtocolManager结构
这一步有一个重要的内容就是append(SubProtocols, p2p.Protocols{})' W/ u1 q) g2 N4 E3 t
manager.SubProtocols = append(manager.SubProtocols, p2p.Protocol{
Name: ProtocolName,
Version: version,
Length: ProtocolLengths,
Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
peer := manager.newPeer(int(version), p, rw)2 C3 _, B. n9 c4 F' {
select {& W! q2 ]0 W% ~/ \1 ^
case manager.newPeerCh
func pm.handle(); H- @" p4 |6 }7 o
这里newPeerCh接收到peer后调用pm.handle, 与pm同步txs,同时p同步pm.whiteList中的header& L9 _3 K2 |* C9 p
for number := range pm.whitelist {: ?3 c* ?; V0 \+ C
if err := p.RequestHeadersByNumber(number, 1, 0, false); err != nil {/ ]4 \/ e z9 d
return err
}' s0 o+ l0 P" `
}
同时进入循环处理来自peer的消息
for {: \# P2 B; M! L8 T0 ^4 j+ U* c
if err := pm.handleMsg(p); err != nil {0 E1 L- J8 n" H B5 H/ J3 l
p.Log().Debug("Ethereum message handling failed", "err", err)
return err$ ~1 d$ p8 `% l$ g& ^
}
}
func pm.handleMsg(p *peer); N* k& [+ B( P$ u. X% s! |, K
这个函数根据msg, err := p.rw.ReadMsg() msg的类型做出不同的处理,塞到fetcher 或者downloader中去等等- t& |0 c" [2 k: C6 w' ?
func.pm.BroadcastTxs(tx), D/ k# [; w' s, C# J6 O( i
找到pm.peers.PeersWithoutTx(tx.Hash()) 然后把tx塞给他) b8 h6 i! `; L t& x" b
这个函数在 接受到消息时就会被调用
func (pm *ProtocolManager) BroadcastBlock(block *types.Block, propagate bool)# z( h4 D6 c& I# T' v
这个就如题吧( _$ r# H' ?7 P5 [& G8 a; k5 o
参数propagate为true就选出前Math.sqrt(peersLen)个节点,传播出块消息参数propagate为false 简单向所有节点声明我有这个块
3 O" W V: |6 _5 B& |6 w5 u
调用:range pm.minedBlockSub.Chan() 如果管道里有消息会执行以下代码
pm.BroadcastBlock(ev.Block, true) // First propagate block to peers
pm.BroadcastBlock(ev.Block, false) // Only then announce to the rest. r1 c2 Q7 M O
成为第一个吐槽的人