forked from TrueCloudLab/neoneo-go
network: fix block relaying, don't spit out useless errors
We can only add one block of the given height and we have two competing goroutines to do that --- consensus and block queue. Whomever adds the block first shouldn't trigger an error in another one. Fix block relaying for blocks added via the block queue also, previously one consensus-generated blocks were broadcasted.
This commit is contained in:
parent
f9963cca37
commit
b9b77ac1be
4 changed files with 24 additions and 9 deletions
|
@ -335,7 +335,11 @@ func (s *service) processBlock(b block.Block) {
|
||||||
bb.Script = *(s.getBlockWitness(bb))
|
bb.Script = *(s.getBlockWitness(bb))
|
||||||
|
|
||||||
if err := s.Chain.AddBlock(bb); err != nil {
|
if err := s.Chain.AddBlock(bb); err != nil {
|
||||||
|
// The block might already be added via the regular network
|
||||||
|
// interaction.
|
||||||
|
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 {
|
} else {
|
||||||
s.Config.RelayBlock(bb)
|
s.Config.RelayBlock(bb)
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,10 @@ type blockQueue struct {
|
||||||
queue *queue.PriorityQueue
|
queue *queue.PriorityQueue
|
||||||
checkBlocks chan struct{}
|
checkBlocks chan struct{}
|
||||||
chain core.Blockchainer
|
chain core.Blockchainer
|
||||||
|
relayF func(*block.Block)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newBlockQueue(capacity int, bc core.Blockchainer, log *zap.Logger) *blockQueue {
|
func newBlockQueue(capacity int, bc core.Blockchainer, log *zap.Logger, relayer func(*block.Block)) *blockQueue {
|
||||||
if log == nil {
|
if log == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -24,6 +25,7 @@ func newBlockQueue(capacity int, bc core.Blockchainer, log *zap.Logger) *blockQu
|
||||||
queue: queue.NewPriorityQueue(capacity, false),
|
queue: queue.NewPriorityQueue(capacity, false),
|
||||||
checkBlocks: make(chan struct{}, 1),
|
checkBlocks: make(chan struct{}, 1),
|
||||||
chain: bc,
|
chain: bc,
|
||||||
|
relayF: relayer,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,11 +47,16 @@ func (bq *blockQueue) run() {
|
||||||
if minblock.Index == bq.chain.BlockHeight()+1 {
|
if minblock.Index == bq.chain.BlockHeight()+1 {
|
||||||
err := bq.chain.AddBlock(minblock)
|
err := bq.chain.AddBlock(minblock)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// The block might already be added by consensus.
|
||||||
|
if _, errget := bq.chain.GetBlock(minblock.Hash()); errget != nil {
|
||||||
bq.log.Warn("blockQueue: failed adding block into the blockchain",
|
bq.log.Warn("blockQueue: failed adding block into the blockchain",
|
||||||
zap.String("error", err.Error()),
|
zap.String("error", err.Error()),
|
||||||
zap.Uint32("blockHeight", bq.chain.BlockHeight()),
|
zap.Uint32("blockHeight", bq.chain.BlockHeight()),
|
||||||
zap.Uint32("nextIndex", minblock.Index))
|
zap.Uint32("nextIndex", minblock.Index))
|
||||||
}
|
}
|
||||||
|
} else if bq.relayF != nil {
|
||||||
|
bq.relayF(minblock)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
func TestBlockQueue(t *testing.T) {
|
func TestBlockQueue(t *testing.T) {
|
||||||
chain := &testChain{}
|
chain := &testChain{}
|
||||||
// notice, it's not yet running
|
// notice, it's not yet running
|
||||||
bq := newBlockQueue(0, chain, zaptest.NewLogger(t))
|
bq := newBlockQueue(0, chain, zaptest.NewLogger(t), nil)
|
||||||
blocks := make([]*block.Block, 11)
|
blocks := make([]*block.Block, 11)
|
||||||
for i := 1; i < 11; i++ {
|
for i := 1; i < 11; i++ {
|
||||||
blocks[i] = &block.Block{Base: block.Base{Index: uint32(i)}}
|
blocks[i] = &block.Block{Base: block.Base{Index: uint32(i)}}
|
||||||
|
|
|
@ -90,7 +90,6 @@ func NewServer(config ServerConfig, chain core.Blockchainer, log *zap.Logger) (*
|
||||||
s := &Server{
|
s := &Server{
|
||||||
ServerConfig: config,
|
ServerConfig: config,
|
||||||
chain: chain,
|
chain: chain,
|
||||||
bQueue: newBlockQueue(maxBlockBatch, chain, log),
|
|
||||||
id: randomID(),
|
id: randomID(),
|
||||||
quit: make(chan struct{}),
|
quit: make(chan struct{}),
|
||||||
register: make(chan Peer),
|
register: make(chan Peer),
|
||||||
|
@ -99,6 +98,7 @@ func NewServer(config ServerConfig, chain core.Blockchainer, log *zap.Logger) (*
|
||||||
connected: atomic.NewBool(false),
|
connected: atomic.NewBool(false),
|
||||||
log: log,
|
log: log,
|
||||||
}
|
}
|
||||||
|
s.bQueue = newBlockQueue(maxBlockBatch, chain, log, s.relayBlock)
|
||||||
|
|
||||||
srv, err := consensus.NewService(consensus.Config{
|
srv, err := consensus.NewService(consensus.Config{
|
||||||
Logger: log,
|
Logger: log,
|
||||||
|
@ -734,7 +734,11 @@ func (s *Server) broadcastHPMessage(msg *Message) {
|
||||||
// relayBlock tells all the other connected nodes about the given block.
|
// relayBlock tells all the other connected nodes about the given block.
|
||||||
func (s *Server) relayBlock(b *block.Block) {
|
func (s *Server) relayBlock(b *block.Block) {
|
||||||
msg := s.MkMsg(CMDInv, payload.NewInventory(payload.BlockType, []util.Uint256{b.Hash()}))
|
msg := s.MkMsg(CMDInv, payload.NewInventory(payload.BlockType, []util.Uint256{b.Hash()}))
|
||||||
s.broadcastMessage(msg)
|
// 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.
|
||||||
|
|
Loading…
Reference in a new issue