feat: support rewind for versa db
fix: rewind ancient store
This commit is contained in:
parent
3e8e74d5c2
commit
0af2fb4324
@ -424,6 +424,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||||||
// Make sure the state associated with the block is available, or log out
|
// Make sure the state associated with the block is available, or log out
|
||||||
// if there is no available state, waiting for state sync.
|
// if there is no available state, waiting for state sync.
|
||||||
head := bc.CurrentBlock()
|
head := bc.CurrentBlock()
|
||||||
|
if bc.triedb.Scheme() != rawdb.VersionScheme {
|
||||||
if !bc.HasState(head.Root) {
|
if !bc.HasState(head.Root) {
|
||||||
if head.Number.Uint64() == 0 {
|
if head.Number.Uint64() == 0 {
|
||||||
// The genesis state is missing, which is only possible in the path-based
|
// The genesis state is missing, which is only possible in the path-based
|
||||||
@ -465,7 +466,11 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
log.Warn("versa db no recovery, rewind in load state")
|
||||||
|
}
|
||||||
// Ensure that a previous crash in SetHead doesn't leave extra ancients
|
// Ensure that a previous crash in SetHead doesn't leave extra ancients
|
||||||
|
if bc.triedb.Scheme() != rawdb.VersionScheme {
|
||||||
if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 {
|
if frozen, err := bc.db.BlockStore().ItemAmountInAncient(); err == nil && frozen > 0 {
|
||||||
frozen, err = bc.db.BlockStore().Ancients()
|
frozen, err = bc.db.BlockStore().Ancients()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -500,6 +505,24 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
//TODO:: need consider the offline and inline prune block
|
||||||
|
frozen, err := bc.db.BlockStore().Ancients()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items, err := bc.db.BlockStore().ItemAmountInAncient()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
fullBlock := bc.CurrentBlock()
|
||||||
|
log.Info("version mode rewind ancient store", "target", fullBlock.Number.Uint64(), "old head", frozen, "items", items, "offset", bc.db.BlockStore().AncientOffSet())
|
||||||
|
if frozen >= fullBlock.Number.Uint64() {
|
||||||
|
if _, err = bc.db.BlockStore().TruncateTail(fullBlock.Number.Uint64()); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// The first thing the node will do is reconstruct the verification data for
|
// The first thing the node will do is reconstruct the verification data for
|
||||||
// the head block (ethash cache or clique voting snapshot). Might as well do
|
// the head block (ethash cache or clique voting snapshot). Might as well do
|
||||||
// it in advance.
|
// it in advance.
|
||||||
@ -702,6 +725,38 @@ func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 {
|
|||||||
// loadLastState loads the last known chain state from the database. This method
|
// loadLastState loads the last known chain state from the database. This method
|
||||||
// assumes that the chain manager mutex is held.
|
// assumes that the chain manager mutex is held.
|
||||||
func (bc *BlockChain) loadLastState() error {
|
func (bc *BlockChain) loadLastState() error {
|
||||||
|
// TODO:: before versa db support recovery, only rewind
|
||||||
|
var headBlock *types.Block
|
||||||
|
if bc.triedb.Scheme() == rawdb.VersionScheme {
|
||||||
|
head := rawdb.ReadHeadBlockHash(bc.db)
|
||||||
|
headBlock = bc.GetBlockByHash(head)
|
||||||
|
|
||||||
|
versa := bc.triedb.VersaDB()
|
||||||
|
archiveVersion, _ := versa.LatestStoreDiskVersionInfo()
|
||||||
|
// empty chain
|
||||||
|
if archiveVersion == -1 {
|
||||||
|
archiveVersion = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if int64(headBlock.NumberU64()) < archiveVersion {
|
||||||
|
log.Crit("versa db disk version large than header block", "head number", headBlock.NumberU64(), "versa archive number", archiveVersion)
|
||||||
|
}
|
||||||
|
log.Info("begin rewind versa db head", "target", archiveVersion)
|
||||||
|
for {
|
||||||
|
if int64(headBlock.NumberU64()) == archiveVersion {
|
||||||
|
rawdb.WriteCanonicalHash(bc.db, headBlock.Hash(), headBlock.NumberU64())
|
||||||
|
rawdb.WriteHeadHeaderHash(bc.db, headBlock.Hash())
|
||||||
|
rawdb.WriteHeadBlockHash(bc.db, headBlock.Hash())
|
||||||
|
rawdb.WriteHeadFastBlockHash(bc.db, headBlock.Hash())
|
||||||
|
log.Info("reset versa db head block", "number", headBlock.NumberU64(), "hash", headBlock.Hash())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
headBlock = rawdb.ReadBlock(bc.db, headBlock.ParentHash(), headBlock.NumberU64()-1)
|
||||||
|
if headBlock == nil {
|
||||||
|
panic("versa db rewind head is nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
// Restore the last known head block
|
// Restore the last known head block
|
||||||
head := rawdb.ReadHeadBlockHash(bc.db)
|
head := rawdb.ReadHeadBlockHash(bc.db)
|
||||||
if head == (common.Hash{}) {
|
if head == (common.Hash{}) {
|
||||||
@ -710,12 +765,14 @@ func (bc *BlockChain) loadLastState() error {
|
|||||||
return bc.Reset()
|
return bc.Reset()
|
||||||
}
|
}
|
||||||
// Make sure the entire head block is available
|
// Make sure the entire head block is available
|
||||||
headBlock := bc.GetBlockByHash(head)
|
headBlock = bc.GetBlockByHash(head)
|
||||||
if headBlock == nil {
|
if headBlock == nil {
|
||||||
// Corrupt or empty database, init from scratch
|
// Corrupt or empty database, init from scratch
|
||||||
log.Warn("Head block missing, resetting chain", "hash", head)
|
log.Warn("Head block missing, resetting chain", "hash", head)
|
||||||
return bc.Reset()
|
return bc.Reset()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
log.Info("load state head block", "number", headBlock.NumberU64())
|
||||||
|
|
||||||
// Everything seems to be fine, set as the head block
|
// Everything seems to be fine, set as the head block
|
||||||
bc.currentBlock.Store(headBlock.Header())
|
bc.currentBlock.Store(headBlock.Header())
|
||||||
|
@ -191,6 +191,8 @@ func peerToSyncOp(mode downloader.SyncMode, p *eth.Peer) *chainSyncOp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
||||||
|
head := cs.handler.chain.CurrentBlock()
|
||||||
|
if cs.handler.chain.TrieDB().Scheme() != rawdb.VersionScheme {
|
||||||
// If we're in snap sync mode, return that directly
|
// If we're in snap sync mode, return that directly
|
||||||
if cs.handler.snapSync.Load() {
|
if cs.handler.snapSync.Load() {
|
||||||
block := cs.handler.chain.CurrentSnapBlock()
|
block := cs.handler.chain.CurrentSnapBlock()
|
||||||
@ -199,7 +201,7 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
|||||||
}
|
}
|
||||||
// We are probably in full sync, but we might have rewound to before the
|
// We are probably in full sync, but we might have rewound to before the
|
||||||
// snap sync pivot, check if we should re-enable snap sync.
|
// snap sync pivot, check if we should re-enable snap sync.
|
||||||
head := cs.handler.chain.CurrentBlock()
|
head = cs.handler.chain.CurrentBlock()
|
||||||
if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
|
if pivot := rawdb.ReadLastPivotNumber(cs.handler.database); pivot != nil {
|
||||||
if head.Number.Uint64() < *pivot {
|
if head.Number.Uint64() < *pivot {
|
||||||
if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType {
|
if rawdb.ReadAncientType(cs.handler.database) == rawdb.PruneFreezerType {
|
||||||
@ -219,6 +221,11 @@ func (cs *chainSyncer) modeAndLocalHead() (downloader.SyncMode, *big.Int) {
|
|||||||
log.Info("Reenabled snap sync as chain is stateless")
|
log.Info("Reenabled snap sync as chain is stateless")
|
||||||
return downloader.SnapSync, td
|
return downloader.SnapSync, td
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if !cs.handler.chain.HasState(head.Root) {
|
||||||
|
panic("version db not support snap sync")
|
||||||
|
}
|
||||||
|
}
|
||||||
// Nope, we're really full syncing
|
// Nope, we're really full syncing
|
||||||
td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64())
|
td := cs.handler.chain.GetTd(head.Hash(), head.Number.Uint64())
|
||||||
return downloader.FullSync, td
|
return downloader.FullSync, td
|
||||||
|
@ -49,7 +49,8 @@ func (v *VersionDB) Scheme() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (v *VersionDB) Initialized(genesisRoot common.Hash) bool {
|
func (v *VersionDB) Initialized(genesisRoot common.Hash) bool {
|
||||||
return v.db.HasState(genesisRoot)
|
version, _ := v.db.LatestStoreDiskVersionInfo()
|
||||||
|
return version >= 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *VersionDB) Size() (common.StorageSize, common.StorageSize, common.StorageSize) {
|
func (v *VersionDB) Size() (common.StorageSize, common.StorageSize, common.StorageSize) {
|
||||||
|
Loading…
Reference in New Issue
Block a user