以太坊(ethereum)实现研究我爱编程以太坊

p2p分析

2018-04-16  本文已影响18人  古则

1.数据结构

image.png
//eth/handler.go
type ProtocolManager struct {
    networkId uint64

    fastSync  uint32 // Flag whether fast sync is enabled (gets disabled if we already have blocks)
    acceptTxs uint32 // Flag whether we're considered synchronised (enables transaction processing)

    txpool      txPool
    blockchain  *core.BlockChain
    chainconfig *params.ChainConfig
    maxPeers    int

    downloader *downloader.Downloader
    fetcher    *fetcher.Fetcher
    peers      *peerSet

    SubProtocols []p2p.Protocol

    eventMux      *event.TypeMux
    txCh          chan core.TxPreEvent
    txSub         event.Subscription
    minedBlockSub *event.TypeMuxSubscription

    // channels for fetcher, syncer, txsyncLoop
    newPeerCh   chan *peer
    txsyncCh    chan *txsync
    quitSync    chan struct{}
    noMorePeers chan struct{}

    // wait group is used for graceful shutdowns during downloading
    // and processing
    wg sync.WaitGroup
}

//eth/peer.go
type peerSet struct {
    peers  map[string]*peer
    lock   sync.RWMutex
    closed bool
}

type peer struct {
    id string

    *p2p.Peer
    rw p2p.MsgReadWriter

    version  int         // Protocol version negotiated
    forkDrop *time.Timer // Timed connection dropper if forks aren't validated in time

    head common.Hash
    td   *big.Int
    lock sync.RWMutex

    knownTxs    *set.Set // Set of transaction hashes known to be known by this peer
    knownBlocks *set.Set // Set of block hashes known to be known by this peer
}

ProtocolManager主要成员包括:

2.启动

在geth启动(见https://www.jianshu.com/p/f04fd9095e74)过程中,在方法eth.New中,有

//eth/backend.go
if eth.protocolManager, err = NewProtocolManager(eth.chainConfig, config.SyncMode, config.NetworkId, eth.eventMux, eth.txPool, eth.engine, eth.blockchain, chainDb); err != nil {
        return nil, err
    }

此处就是p2p的初始化
在eth.New(返回*Ethereum)后,ethereum启动时会随之启动p2p

//eth/backend.go
// Start implements node.Service, starting all internal goroutines needed by the
// Ethereum protocol implementation.
func (s *Ethereum) Start(srvr *p2p.Server) error {
    // Start the bloom bits servicing goroutines
    s.startBloomHandlers()

    // Start the RPC service
    s.netRPCService = ethapi.NewPublicNetAPI(srvr, s.NetVersion())

    // Figure out a max peers count based on the server limits
    maxPeers := srvr.MaxPeers
    if s.config.LightServ > 0 {
        if s.config.LightPeers >= srvr.MaxPeers {
            return fmt.Errorf("invalid peer config: light peer count (%d) >= total peer count (%d)", s.config.LightPeers, srvr.MaxPeers)
        }
        maxPeers -= s.config.LightPeers
    }
    // Start the networking layer and the light server if requested
    s.protocolManager.Start(maxPeers)
    if s.lesServer != nil {
        s.lesServer.Start(srvr)
    }
    return nil
}

ProtocolManager的start函数代码如下

func (pm *ProtocolManager) Start(maxPeers int) {
    pm.maxPeers = maxPeers

    // broadcast transactions
    pm.txCh = make(chan core.TxPreEvent, txChanSize)
    pm.txSub = pm.txpool.SubscribeTxPreEvent(pm.txCh)
    go pm.txBroadcastLoop()

    // broadcast mined blocks
    pm.minedBlockSub = pm.eventMux.Subscribe(core.NewMinedBlockEvent{})
    go pm.minedBroadcastLoop()

    // start sync handlers
    go pm.syncer()
    go pm.txsyncLoop()
}
image.png

以上这四段相对独立的业务流程的逻辑分别是:

以上四段流程就是ProtocolManager向相邻peer主动发起的通信过程。尽管上述各函数细节从文字阅读起来容易模糊,不过最重要的内容还是值得留意下的:本个体(peer)向其他peer主动发起的通信中,按照数据类型可分两类:交易tx和区块block;而按照通信方式划分,亦可分为广播新的单个数据和同步一组同类型数据,这样简单的两两配对,便可组成上述四段流程。

上一篇下一篇

猜你喜欢

热点阅读