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()
return err
}
- return nil
+ return chain.Rollback(targetHeight)
}
func initNodeConfig(config *cfg.Config) error {
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 {
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{}
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 {
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
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
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 {
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