OSDN Git Service

fix long fork
authorshenao78 <shenao.78@163.com>
Thu, 26 Dec 2019 06:28:59 +0000 (14:28 +0800)
committershenao78 <shenao.78@163.com>
Thu, 26 Dec 2019 06:28:59 +0000 (14:28 +0800)
api/api.go
api/rollback.go [new file with mode: 0644]
protocol/block.go

index cc54ae8..e5316ae 100644 (file)
@@ -251,6 +251,7 @@ func (a *API) buildHandler() {
                m.Handle("/rescan-wallet", jsonHandler(a.rescanWallet))
                m.Handle("/wallet-info", jsonHandler(a.getWalletInfo))
                m.Handle("/recovery-wallet", jsonHandler(a.recoveryFromRootXPubs))
+               m.Handle("/rollback-block", jsonHandler(a.rollbackBlock))
        } else {
                log.Warn("Please enable wallet")
        }
diff --git a/api/rollback.go b/api/rollback.go
new file mode 100644 (file)
index 0000000..cc7a1e0
--- /dev/null
@@ -0,0 +1,12 @@
+package api
+
+func (a *API) rollbackBlock(req struct{
+       BlockHeight uint64 `json:"block_height"`
+}) Response {
+       for a.chain.BestBlockHeight() > req.BlockHeight {
+               if err := a.chain.DetachLast(); err != nil {
+                       return NewErrorResponse(err)
+               }
+       }
+       return NewSuccessResponse(nil)
+}
index 907dc07..0836b6b 100644 (file)
@@ -283,6 +283,52 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error {
        return nil
 }
 
+func (c *Chain) DetachLast() error {
+       utxoView := state.NewUtxoViewpoint()
+       consensusResult, err := c.getBestConsensusResult()
+       if err != nil {
+               return err
+       }
+
+       detachHeader := c.bestBlockHeader
+       detachHash := detachHeader.Hash()
+       b, err := c.store.GetBlock(&detachHash)
+       if err != nil {
+               return err
+       }
+
+       detachBlock := types.MapBlock(b)
+       if err := c.store.GetTransactionsUtxo(utxoView, detachBlock.Transactions); err != nil {
+               return err
+       }
+
+       txStatus, err := c.GetTransactionStatus(&detachBlock.ID)
+       if err != nil {
+               return err
+       }
+
+       if err := utxoView.DetachBlock(detachBlock, txStatus); err != nil {
+               return err
+       }
+
+       if err := consensusResult.DetachBlock(b); err != nil {
+               return err
+       }
+
+       for _, p := range c.subProtocols {
+               if err := p.DetachBlock(b); err != nil {
+                       return errors.Wrap(err, p.Name(), "sub protocol detach block")
+               }
+       }
+
+       blockHeader, err := c.store.GetBlockHeader(&detachHeader.PreviousBlockHash)
+       if err != nil {
+               return err
+       }
+
+       return c.setState(blockHeader, c.lastIrrBlockHeader, nil, utxoView, []*state.ConsensusResult{consensusResult})
+}
+
 // SaveBlock will validate and save block into storage
 func (c *Chain) saveBlock(block *types.Block) error {
        if err := c.validateSign(block); err != nil {