From: ipqhjjybj <250657661@qq.com> Date: Thu, 20 Feb 2020 09:01:13 +0000 (+0800) Subject: Rollback pr3 (#496) X-Git-Url: http://git.osdn.net/view?a=commitdiff_plain;h=d4e0711c484ad296e529b6543f46bb99c937fb2b;p=bytom%2Fvapor.git Rollback pr3 (#496) * rollback chain * fix test ci * delete irrblock judge * update rollblock * delete test case * fix bad delete * change rollback * delete one test * add tip * change rollback * fix one err * remove fmt * remove one test * rename * rename variable Co-authored-by: Poseidon --- diff --git a/database/store.go b/database/store.go index 97cece79..4ffc65dc 100644 --- a/database/store.go +++ b/database/store.go @@ -156,6 +156,18 @@ func GetConsensusResult(db dbm.DB, seq uint64) (*state.ConsensusResult, error) { return consensusResult, nil } +// DeleteConsensusResult delete a consensusResult from cache and database +func (s *Store) DeleteConsensusResult(seq uint64) error { + consensusResult, err := GetConsensusResult(s.db, seq) + if err != nil { + return err + } + + s.db.Delete(calcConsensusResultKey(seq)) + s.cache.removeConsensusResult(consensusResult) + return nil +} + // DeleteBlock delete a new block in the protocol. func (s *Store) DeleteBlock(block *types.Block) error { blockHash := block.Hash() diff --git a/node/node.go b/node/node.go index 1ecb0e49..7640e8eb 100644 --- a/node/node.go +++ b/node/node.go @@ -203,7 +203,7 @@ func Rollback(config *cfg.Config, targetHeight uint64) error { return err } - return nil + return chain.Rollback(targetHeight) } func initNodeConfig(config *cfg.Config) error { diff --git a/protocol/block.go b/protocol/block.go index 6710fb54..09e72df7 100644 --- a/protocol/block.go +++ b/protocol/block.go @@ -172,6 +172,78 @@ func (c *Chain) detachBlock(detachBlockHeader *types.BlockHeader, consensusResul return block, nil } +func (c *Chain) syncSubProtocols() error { + for _, p := range c.subProtocols { + if err := c.syncProtocolStatus(p); err != nil { + return errors.Wrap(err, p.Name(), "sync sub protocol status") + } + } + return nil +} + +// Rollback rollback the chain from one blockHeight to targetBlockHeight +// WARNING: we recommend to use this only in commond line +func (c *Chain) Rollback(targetHeight uint64) error { + c.cond.L.Lock() + defer c.cond.L.Unlock() + + utxoView := state.NewUtxoViewpoint() + consensusResult, err := c.getBestConsensusResult() + if err != nil { + return err + } + + if err = c.syncSubProtocols(); err != nil { + return err + } + + targetBlockHeader, err := c.GetHeaderByHeight(targetHeight) + if err != nil { + return err + } + + _, deletedBlockHeaders, err := c.calcReorganizeChain(targetBlockHeader, c.bestBlockHeader) + if err != nil { + return err + } + + deletedBlocks := []*types.Block{} + for _, deletedBlockHeader := range deletedBlockHeaders { + block, err := c.detachBlock(deletedBlockHeader, consensusResult, utxoView) + if err != nil { + return err + } + + deletedBlocks = append(deletedBlocks, block) + } + + setIrrBlockHeader := c.lastIrrBlockHeader + if c.lastIrrBlockHeader.Height > targetBlockHeader.Height { + setIrrBlockHeader = targetBlockHeader + } + + startSeq := state.CalcVoteSeq(c.bestBlockHeader.Height) + + if err = c.setState(targetBlockHeader, setIrrBlockHeader, nil, utxoView, []*state.ConsensusResult{consensusResult.Fork()}); err != nil { + return err + } + + for _, block := range deletedBlocks { + if err := c.store.DeleteBlock(block); err != nil { + return err + } + } + + endSeq := state.CalcVoteSeq(targetHeight) + for nowSeq := startSeq; nowSeq > endSeq; nowSeq-- { + if err := c.store.DeleteConsensusResult(nowSeq); err != nil { + return err + } + } + + return nil +} + func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { attachBlockHeaders, detachBlockHeaders, err := c.calcReorganizeChain(blockHeader, c.bestBlockHeader) if err != nil { @@ -185,10 +257,8 @@ func (c *Chain) reorganizeChain(blockHeader *types.BlockHeader) error { return err } - for _, p := range c.subProtocols { - if err := c.syncProtocolStatus(p); err != nil { - return errors.Wrap(err, p.Name(), "sync sub protocol status") - } + if err = c.syncSubProtocols(); err != nil { + return err } txsToRestore := map[bc.Hash]*types.Tx{} diff --git a/protocol/block_test.go b/protocol/block_test.go index ff2b40c6..ba13dbe6 100644 --- a/protocol/block_test.go +++ b/protocol/block_test.go @@ -26,6 +26,7 @@ func (s *mStore) GetUtxo(*bc.Hash) (*storage.UtxoEntry, error) { func (s *mStore) GetConsensusResult(uint64) (*state.ConsensusResult, error) { return nil, nil } func (s *mStore) GetMainChainHash(uint64) (*bc.Hash, error) { return nil, nil } func (s *mStore) GetBlockHashesByHeight(uint64) ([]*bc.Hash, error) { return nil, nil } +func (s *mStore) DeleteConsensusResult(seq uint64) error { return nil } func (s *mStore) DeleteBlock(*types.Block) error { return nil } func (s *mStore) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil } func (s *mStore) SaveBlockHeader(blockHeader *types.BlockHeader) error { diff --git a/protocol/consensus_node_manager_test.go b/protocol/consensus_node_manager_test.go index db3ab8ea..56471265 100644 --- a/protocol/consensus_node_manager_test.go +++ b/protocol/consensus_node_manager_test.go @@ -735,6 +735,10 @@ func (s *dummyStore) GetBlockHashesByHeight(uint64) ([]*bc.Hash, error) { return nil, nil } +func (s *dummyStore) DeleteConsensusResult(seq uint64) error { + return nil +} + func (s *dummyStore) SaveBlock(block *types.Block, _ *bc.TransactionStatus) error { hash := block.Hash() s.blocks[hash.String()] = block diff --git a/protocol/store.go b/protocol/store.go index c4da6e34..275efdb8 100644 --- a/protocol/store.go +++ b/protocol/store.go @@ -27,6 +27,7 @@ type Store interface { GetMainChainHash(uint64) (*bc.Hash, error) GetBlockHashesByHeight(uint64) ([]*bc.Hash, error) + DeleteConsensusResult(uint64) error DeleteBlock(*types.Block) error SaveBlock(*types.Block, *bc.TransactionStatus) error SaveBlockHeader(*types.BlockHeader) error diff --git a/protocol/txpool_test.go b/protocol/txpool_test.go index 544d1fa3..50e448e5 100644 --- a/protocol/txpool_test.go +++ b/protocol/txpool_test.go @@ -122,6 +122,7 @@ func (s *mockStore) GetConsensusResult(uint64) (*state.ConsensusResult, error) func (s *mockStore) GetMainChainHash(uint64) (*bc.Hash, error) { return nil, nil } func (s *mockStore) GetBlockHashesByHeight(uint64) ([]*bc.Hash, error) { return nil, nil } func (s *mockStore) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil } +func (s *mockStore) DeleteConsensusResult(seq uint64) error { return nil } func (s *mockStore) DeleteBlock(*types.Block) error { return nil } func (s *mockStore) SaveBlockHeader(*types.BlockHeader) error { return nil } func (s *mockStore) SaveChainStatus(*types.BlockHeader, *types.BlockHeader, []*types.BlockHeader, *state.UtxoViewpoint, []*state.ConsensusResult) error { @@ -675,6 +676,7 @@ func (s *mockStore1) GetMainChainHash(uint64) (*bc.Hash, error) func (s *mockStore1) GetBlockHashesByHeight(uint64) ([]*bc.Hash, error) { return nil, nil } func (s *mockStore1) DeleteBlock(*types.Block) error { return nil } func (s *mockStore1) SaveBlock(*types.Block, *bc.TransactionStatus) error { return nil } +func (s *mockStore1) DeleteConsensusResult(seq uint64) error { return nil } func (s *mockStore1) SaveBlockHeader(*types.BlockHeader) error { return nil } func (s *mockStore1) SaveChainStatus(*types.BlockHeader, *types.BlockHeader, []*types.BlockHeader, *state.UtxoViewpoint, []*state.ConsensusResult) error { return nil