+ 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")
+ }
+
+ consensusResults = append(consensusResults, consensusResult.Fork())
+ 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