network: get blocks directly from the chain for rebroadcasting

Simplify network<->consensus relations, also broadcast blocks received by
other means like RPC.
This commit is contained in:
Roman Khimov 2020-05-07 23:00:38 +03:00
parent 462022bbdd
commit b7d2b659b4
2 changed files with 25 additions and 20 deletions

View file

@ -71,9 +71,6 @@ type Config struct {
// Broadcast is a callback which is called to notify server // Broadcast is a callback which is called to notify server
// about new consensus payload to sent. // about new consensus payload to sent.
Broadcast func(p *Payload) Broadcast func(p *Payload)
// RelayBlock is a callback that is called to notify server
// about the new block that needs to be broadcasted.
RelayBlock func(b *coreb.Block)
// Chain is a core.Blockchainer instance. // Chain is a core.Blockchainer instance.
Chain blockchainer.Blockchainer Chain blockchainer.Blockchainer
// RequestTx is a callback to which will be called // RequestTx is a callback to which will be called
@ -348,8 +345,6 @@ func (s *service) processBlock(b block.Block) {
if _, errget := s.Chain.GetBlock(bb.Hash()); errget != nil { if _, errget := s.Chain.GetBlock(bb.Hash()); errget != nil {
s.log.Warn("error on add block", zap.Error(err)) s.log.Warn("error on add block", zap.Error(err))
} }
} else {
s.Config.RelayBlock(bb)
} }
} }

View file

@ -106,16 +106,14 @@ func NewServer(config ServerConfig, chain blockchainer.Blockchainer, log *zap.Lo
if !s.consensusStarted.Load() { if !s.consensusStarted.Load() {
s.tryStartConsensus() s.tryStartConsensus()
} }
s.relayBlock(b)
}) })
srv, err := consensus.NewService(consensus.Config{ srv, err := consensus.NewService(consensus.Config{
Logger: log, Logger: log,
Broadcast: s.handleNewPayload, Broadcast: s.handleNewPayload,
RelayBlock: s.relayBlock, Chain: chain,
Chain: chain, RequestTx: s.requestTx,
RequestTx: s.requestTx, Wallet: config.Wallet,
Wallet: config.Wallet,
TimePerBlock: config.TimePerBlock, TimePerBlock: config.TimePerBlock,
}) })
@ -171,6 +169,7 @@ func (s *Server) Start(errChan chan error) {
s.discovery.BackFill(s.Seeds...) s.discovery.BackFill(s.Seeds...)
go s.broadcastTxLoop() go s.broadcastTxLoop()
go s.relayBlocksLoop()
go s.bQueue.run() go s.bQueue.run()
go s.transport.Accept() go s.transport.Accept()
setServerAndNodeVersions(s.UserAgent, strconv.FormatUint(uint64(s.id), 10)) setServerAndNodeVersions(s.UserAgent, strconv.FormatUint(uint64(s.id), 10))
@ -795,14 +794,25 @@ func (s *Server) broadcastHPMessage(msg *Message) {
s.iteratePeersWithSendMsg(msg, Peer.EnqueueHPPacket, nil) s.iteratePeersWithSendMsg(msg, Peer.EnqueueHPPacket, nil)
} }
// relayBlock tells all the other connected nodes about the given block. // relayBlocksLoop subscribes to new blocks in the ledger and broadcasts them
func (s *Server) relayBlock(b *block.Block) { // to the network. Intended to be run as a separate goroutine.
msg := NewMessage(CMDInv, payload.NewInventory(payload.BlockType, []util.Uint256{b.Hash()})) func (s *Server) relayBlocksLoop() {
// Filter out nodes that are more current (avoid spamming the network ch := make(chan *block.Block, 2) // Some buffering to smooth out possible egressing delays.
// during initial sync). s.chain.SubscribeForBlocks(ch)
s.iteratePeersWithSendMsg(msg, Peer.EnqueuePacket, func(p Peer) bool { for {
return p.Handshaked() && p.LastBlockIndex() < b.Index select {
}) case <-s.quit:
s.chain.UnsubscribeFromBlocks(ch)
return
case b := <-ch:
msg := NewMessage(CMDInv, payload.NewInventory(payload.BlockType, []util.Uint256{b.Hash()}))
// Filter out nodes that are more current (avoid spamming the network
// during initial sync).
s.iteratePeersWithSendMsg(msg, Peer.EnqueuePacket, func(p Peer) bool {
return p.Handshaked() && p.LastBlockIndex() < b.Index
})
}
}
} }
// verifyAndPoolTX verifies the TX and adds it to the local mempool. // verifyAndPoolTX verifies the TX and adds it to the local mempool.