OSDN Git Service

keep last irreversible block on the main chain fix_LIB
authorWei Wang <apollo.mobility@gmail.com>
Fri, 5 Jul 2019 09:59:58 +0000 (17:59 +0800)
committerWei Wang <apollo.mobility@gmail.com>
Fri, 5 Jul 2019 10:02:10 +0000 (18:02 +0800)
Only update the LIB pointer when newly irreversible block is on the main
chain. Emit warning otherwise.

netsync/chainmgr/block_keeper.go
netsync/chainmgr/handle.go
protocol/bbft.go
protocol/block.go
protocol/protocol.go
test/mock/chain.go

index d1407e9..24b4ef3 100644 (file)
@@ -190,7 +190,7 @@ func (bk *blockKeeper) syncWorker() {
                                continue
                        }
 
-                       if err := bk.peers.BroadcastNewStatus(bk.chain.BestBlockHeader(), bk.chain.BestIrreversibleHeader()); err != nil {
+                       if err := bk.peers.BroadcastNewStatus(bk.chain.BestBlockHeader(), bk.chain.LastIrreversibleHeader()); err != nil {
                                log.WithFields(log.Fields{"module": logModule, "err": err}).Error("fail on syncWorker broadcast new status")
                        }
                case <-bk.quit:
index 2a77d01..6e37389 100644 (file)
@@ -25,7 +25,7 @@ const (
 // Chain is the interface for Bytom core
 type Chain interface {
        BestBlockHeader() *types.BlockHeader
-       BestIrreversibleHeader() *types.BlockHeader
+       LastIrreversibleHeader() *types.BlockHeader
        BestBlockHeight() uint64
        GetBlockByHash(*bc.Hash) (*types.Block, error)
        GetBlockByHeight(uint64) (*types.Block, error)
@@ -351,7 +351,7 @@ func (m *Manager) SendStatus(peer peers.BasePeer) error {
                return errors.New("invalid peer")
        }
 
-       if err := p.SendStatus(m.chain.BestBlockHeader(), m.chain.BestIrreversibleHeader()); err != nil {
+       if err := p.SendStatus(m.chain.BestBlockHeader(), m.chain.LastIrreversibleHeader()); err != nil {
                m.peers.RemovePeer(p.ID())
                return err
        }
index 0d00737..75a6fab 100644 (file)
@@ -67,7 +67,10 @@ func (c *Chain) IsBlocker(prevBlockHash *bc.Hash, pubKey string, timeStamp uint6
 // return whether a block become irreversible, if so, the chain module must update status
 func (c *Chain) ProcessBlockSignature(signature, xPub []byte, blockHash *bc.Hash) error {
        xpubStr := hex.EncodeToString(xPub[:])
-       blockHeader, _ := c.store.GetBlockHeader(blockHash)
+       blockHeader, err := c.store.GetBlockHeader(blockHash)
+       if err != nil {
+               return err
+       }
 
        // save the signature if the block is not exist
        if blockHeader == nil {
@@ -99,7 +102,7 @@ func (c *Chain) ProcessBlockSignature(signature, xPub []byte, blockHash *bc.Hash
 
 // validateSign verify the signatures of block, and return the number of correct signature
 // if some signature is invalid, they will be reset to nil
-// if the block has not the signature of blocker, it will return error
+// if the block does not have the signature of blocker, it will return error
 func (c *Chain) validateSign(block *types.Block) error {
        consensusNodeMap, err := c.getConsensusNodes(&block.PreviousBlockHash)
        if err != nil {
@@ -222,15 +225,21 @@ func (c *Chain) SignBlock(block *types.Block) ([]byte, error) {
 
 func (c *Chain) updateBlockSignature(blockHeader *types.BlockHeader, nodeOrder uint64, signature []byte) error {
        blockHeader.Set(nodeOrder, signature)
-       if err := c.store.SaveBlockHeader(blockHeader); err != nil {
-               return err
-       }
 
-       if c.isIrreversible(blockHeader) && blockHeader.Height > c.bestIrrBlockHeader.Height {
-               if err := c.store.SaveChainStatus(c.bestBlockHeader, blockHeader, []*types.BlockHeader{}, state.NewUtxoViewpoint(), []*state.VoteResult{}); err != nil {
-                       return err
+       if c.isIrreversible(blockHeader) && blockHeader.Height > c.lastIrrBlockHeader.Height {
+               if c.InMainChain(blockHeader.Hash()) {
+                       if err := c.store.SaveChainStatus(c.bestBlockHeader,
+                               blockHeader,
+                               []*types.BlockHeader{},
+                               state.NewUtxoViewpoint(),
+                               []*state.VoteResult{}); err != nil {
+                               return err
+                       }
+                       c.lastIrrBlockHeader = blockHeader
+               } else {
+                       // block is on a forked chain. Do nothing.
+                       log.WithFields(log.Fields{"module": logModule}).Warn("majority votes received on forked chain")
                }
-               c.bestIrrBlockHeader = blockHeader
        }
        return nil
 }
index 0eafe27..cf76749 100644 (file)
@@ -110,7 +110,7 @@ func (c *Chain) connectBlock(block *types.Block) (err error) {
                return err
        }
 
-       irrBlockHeader := c.bestIrrBlockHeader
+       irrBlockHeader := c.lastIrrBlockHeader
        if c.isIrreversible(&block.BlockHeader) && block.Height > irrBlockHeader.Height {
                irrBlockHeader = &block.BlockHeader
        }
@@ -167,7 +167,7 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error {
                log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("detach from mainchain")
        }
 
-       irrBlockHeader := c.bestIrrBlockHeader
+       irrBlockHeader := c.lastIrrBlockHeader
        for _, attachBlockHeader := range attachBlockHeaders {
                attachHash := attachBlockHeader.Hash()
                b, err := c.store.GetBlock(&attachHash)
@@ -205,7 +205,9 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error {
                log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("attach from mainchain")
        }
 
-       if len(detachBlockHeaders) > 0 && detachBlockHeaders[len(detachBlockHeaders)-1].Height <= c.bestIrrBlockHeader.Height && irrBlockHeader.Height <= c.bestIrrBlockHeader.Height {
+       if len(detachBlockHeaders) > 0 &&
+               detachBlockHeaders[len(detachBlockHeaders)-1].Height <= c.lastIrrBlockHeader.Height &&
+               irrBlockHeader.Height <= c.lastIrrBlockHeader.Height {
                return errors.New("rollback block below the height of irreversible block")
        }
        voteResults = append(voteResults, voteResult.Fork())
index 39ef664..a0ca065 100644 (file)
@@ -26,8 +26,8 @@ type Chain struct {
        eventDispatcher *event.Dispatcher
 
        cond               sync.Cond
-       bestBlockHeader    *types.BlockHeader
-       bestIrrBlockHeader *types.BlockHeader
+       bestBlockHeader    *types.BlockHeader // the last block on current main chain
+       lastIrrBlockHeader *types.BlockHeader // the last irreversible block
 }
 
 // NewChain returns a new Chain using store as the underlying storage.
@@ -56,7 +56,7 @@ func NewChain(store Store, txPool *TxPool, eventDispatcher *event.Dispatcher) (*
                return nil, err
        }
 
-       c.bestIrrBlockHeader, err = c.store.GetBlockHeader(storeStatus.IrreversibleHash)
+       c.lastIrrBlockHeader, err = c.store.GetBlockHeader(storeStatus.IrreversibleHash)
        if err != nil {
                return nil, err
        }
@@ -101,7 +101,7 @@ func (c *Chain) BestBlockHeight() uint64 {
        return c.bestBlockHeader.Height
 }
 
-// BestBlockHash return the hash of the chain tail block
+// BestBlockHash return the hash of the main chain tail block
 func (c *Chain) BestBlockHash() *bc.Hash {
        c.cond.L.Lock()
        defer c.cond.L.Unlock()
@@ -109,11 +109,11 @@ func (c *Chain) BestBlockHash() *bc.Hash {
        return &bestHash
 }
 
-// BestIrreversibleHeader returns the chain best irreversible block header
-func (c *Chain) BestIrreversibleHeader() *types.BlockHeader {
+// LastIrreversibleHeader returns the chain last irreversible block header
+func (c *Chain) LastIrreversibleHeader() *types.BlockHeader {
        c.cond.L.Lock()
        defer c.cond.L.Unlock()
-       return c.bestIrrBlockHeader
+       return c.lastIrrBlockHeader
 }
 
 // BestBlockHeader returns the chain best block header
@@ -145,7 +145,7 @@ func (c *Chain) setState(blockHeader, irrBlockHeader *types.BlockHeader, mainBlo
        }
 
        c.bestBlockHeader = blockHeader
-       c.bestIrrBlockHeader = irrBlockHeader
+       c.lastIrrBlockHeader = irrBlockHeader
 
        blockHash := blockHeader.Hash()
        log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("chain best status has been update")
index 2b85ff0..700891f 100644 (file)
@@ -37,7 +37,7 @@ func (c *Chain) BestBlockHeight() uint64 {
        return c.bestBlockHeader.Height
 }
 
-func (c *Chain) BestIrreversibleHeader() *types.BlockHeader {
+func (c *Chain) LastIrreversibleHeader() *types.BlockHeader {
        return c.bestBlockHeader
 }