X-Git-Url: http://git.osdn.net/view?p=bytom%2Fvapor.git;a=blobdiff_plain;f=protocol%2Fblock.go;h=6799969c4256739a687893aec36bd8d85dc64355;hp=c1dc2651fa9b8a281d04ab127216f912b79e193b;hb=aece9c02c1f342d7ec301981c2afa4b8d1fe0e6a;hpb=3bf61490e8df4a17777877b56176ce608f4ccc26 diff --git a/protocol/block.go b/protocol/block.go index c1dc2651..6799969c 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -138,6 +138,7 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { return err } + txsToRestore := map[bc.Hash]*types.Tx{} for _, detachBlockHeader := range detachBlockHeaders { detachHash := detachBlockHeader.Hash() b, err := c.store.GetBlock(&detachHash) @@ -163,10 +164,15 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { return err } + for _, tx := range b.Transactions { + txsToRestore[tx.ID] = tx + } + blockHash := blockHeader.Hash() log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("detach from mainchain") } + txsToRemove := map[bc.Hash]*types.Tx{} irrBlockHeader := c.lastIrrBlockHeader for _, attachBlockHeader := range attachBlockHeaders { attachHash := attachBlockHeader.Hash() @@ -201,6 +207,14 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { irrBlockHeader = attachBlockHeader } + for _, tx := range b.Transactions { + if _, ok := txsToRestore[tx.ID]; !ok { + txsToRemove[tx.ID] = tx + } else { + delete(txsToRestore, tx.ID) + } + } + blockHash := blockHeader.Hash() log.WithFields(log.Fields{"module": logModule, "height": blockHeader.Height, "hash": blockHash.String()}).Debug("attach from mainchain") } @@ -210,8 +224,29 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { irrBlockHeader.Height <= c.lastIrrBlockHeader.Height { return errors.New("rollback block below the height of irreversible block") } + consensusResults = append(consensusResults, consensusResult.Fork()) - return c.setState(blockHeader, irrBlockHeader, attachBlockHeaders, utxoView, consensusResults) + if err := c.setState(blockHeader, irrBlockHeader, attachBlockHeaders, utxoView, consensusResults); err != nil { + return err + } + + for txHash := range txsToRemove { + c.txPool.RemoveTransaction(&txHash) + } + + for _, tx := range txsToRestore { + // the number of restored Tx should be very small or most of time ZERO + // Error returned from validation is ignored, tx could still be lost if validation fails. + // TODO: adjust tx timestamp so that it won't starve in pool. + if _, err := c.validateTx(tx, blockHeader); err != nil { + log.WithFields(log.Fields{"module": logModule, "tx_id": tx.Tx.ID.String(), "error": err}).Info("restore tx fail") + } + } + + if len(txsToRestore) > 0 { + log.WithFields(log.Fields{"module": logModule, "num": len(txsToRestore)}).Debug("restore txs back to pool") + } + return nil } // SaveBlock will validate and save block into storage @@ -230,11 +265,7 @@ func (c *Chain) saveBlock(block *types.Block) error { return err } - if err := consensusResult.AttachCoinbaseReward(block); err != nil { - return err - } - - rewards, err := consensusResult.GetCoinbaseRewards(block.Height) + rewards, err := consensusResult.GetCoinbaseRewards(parent.Height) if err != nil { return err } @@ -322,6 +353,8 @@ func (c *Chain) processBlock(block *types.Block) (bool, error) { return c.orphanManage.BlockExist(&blockHash), nil } + c.markTransactions(block.Transactions...) + if _, err := c.store.GetBlockHeader(&block.PreviousBlockHash); err != nil { c.orphanManage.Add(block) return true, nil