diff --git a/pkg/core/blockchain.go b/pkg/core/blockchain.go index 5696e6bd7..0f277b504 100644 --- a/pkg/core/blockchain.go +++ b/pkg/core/blockchain.go @@ -672,7 +672,7 @@ func (bc *Blockchain) Reset(height uint32) error { } func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) error { - // Cache isn't yet initialized, so retrieve header right from DAO. + // Cache isn't yet initialized, so retrieve header height right from DAO. currHeight, err := bc.dao.GetCurrentBlockHeight() if err != nil { return fmt.Errorf("failed to retrieve current block height: %w", err) @@ -723,9 +723,10 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) fallthrough case stateJumpStarted: bc.log.Info("trying to reset blocks, transactions and AERs") - // Remove headers/blocks/transactions/aers from currHeight down to height (not including height itself). - for i := height + 1; i <= hHeight; i++ { - err := cache.PurgeBlock(bc.headerHashes[i]) + // Remove blocks/transactions/aers from currHeight down to height (not including height itself). + // Keep headers for now, they'll be removed later. + for i := height + 1; i <= currHeight; i++ { + err := cache.DeleteBlock(bc.GetHeaderHash(int(i))) if err != nil { return fmt.Errorf("error while removing block %d: %w", i, err) } @@ -836,6 +837,9 @@ func (bc *Blockchain) resetStateInternal(height uint32, stage stateChangeStage) case newStorageItemsAdded: // Reset SYS-prefixed and IX-prefixed information. bc.log.Info("trying to reset headers information") + for i := height + 1; i <= hHeight; i++ { + cache.PurgeHeader(bc.GetHeaderHash(int(i))) + } cache.DeleteHeaderHashes(height+1, headerBatchCount) cache.StoreAsCurrentBlock(b) cache.PutCurrentHeader(b.Hash(), height) diff --git a/pkg/core/dao/dao.go b/pkg/core/dao/dao.go index 14f4df1d6..f802dab52 100644 --- a/pkg/core/dao/dao.go +++ b/pkg/core/dao/dao.go @@ -759,31 +759,15 @@ func (dao *Simple) StoreAsBlock(block *block.Block, aer1 *state.AppExecResult, a // DeleteBlock removes the block from dao. It's not atomic, so make sure you're // using private MemCached instance here. func (dao *Simple) DeleteBlock(h util.Uint256) error { - return dao.deleteBlock(h, true) -} - -// PurgeBlock completely removes specified block (or just block header) from dao. -// It differs from DeleteBlock in that it removes header anyway. It's not atomic, -// so make sure you're using private MemCached instance here. -func (dao *Simple) PurgeBlock(h util.Uint256) error { - return dao.deleteBlock(h, false) -} - -func (dao *Simple) deleteBlock(h util.Uint256, keepHeader bool) error { key := dao.makeExecutableKey(h) b, err := dao.getBlock(key) if err != nil { return err } - - if keepHeader { - err = dao.storeHeader(key, &b.Header) - if err != nil { - return err - } - } else { - dao.Store.Delete(key) + err = dao.storeHeader(key, &b.Header) + if err != nil { + return err } for _, tx := range b.Transactions { @@ -801,6 +785,14 @@ func (dao *Simple) deleteBlock(h util.Uint256, keepHeader bool) error { return nil } +// PurgeHeader completely removes specified header from dao. It differs from +// DeleteBlock in that it removes header anyway and does nothing except removing +// header. It does no checks for header existence. +func (dao *Simple) PurgeHeader(h util.Uint256) { + key := dao.makeExecutableKey(h) + dao.Store.Delete(key) +} + // StoreHeader saves the block header into the store. func (dao *Simple) StoreHeader(h *block.Header) error { return dao.storeHeader(dao.makeExecutableKey(h.Hash()), h)