/// <summary> /// Initialize the BlockStore /// <para> /// If StoreTip is <c>null</c>, the store is out of sync. This can happen when:</para> /// <list> /// <item>1. The node crashed.</item> /// <item>2. The node was not closed down properly.</item> /// </list> /// <para> /// To recover we walk back the chain until a common block header is found /// and set the BlockStore's StoreTip to that. /// </para> /// </summary> public async Task InitializeAsync() { this.logger.LogTrace("()"); if (this.storeSettings.ReIndex) { throw new NotImplementedException(); } this.StoreTip = this.Chain.GetBlock(this.BlockRepository.BlockHash); if (this.StoreTip == null) { var blockStoreResetList = new List <uint256>(); Block resetBlock = await this.BlockRepository.GetAsync(this.BlockRepository.BlockHash).ConfigureAwait(false); uint256 resetBlockHash = resetBlock.GetHash(); while (this.Chain.GetBlock(resetBlockHash) == null) { blockStoreResetList.Add(resetBlockHash); if (resetBlock.Header.HashPrevBlock == this.Chain.Genesis.HashBlock) { resetBlockHash = this.Chain.Genesis.HashBlock; break; } resetBlock = await this.BlockRepository.GetAsync(resetBlock.Header.HashPrevBlock).ConfigureAwait(false); Guard.NotNull(resetBlock, nameof(resetBlock)); resetBlockHash = resetBlock.GetHash(); } ChainedBlock newTip = this.Chain.GetBlock(resetBlockHash); await this.BlockRepository.DeleteAsync(newTip.HashBlock, blockStoreResetList).ConfigureAwait(false); this.StoreTip = newTip; this.logger.LogWarning("{0} Initialize recovering to block height = {1}, hash = {2}.", this.StoreName, newTip.Height, newTip.HashBlock); } if (this.storeSettings.TxIndex != this.BlockRepository.TxIndex) { if (this.StoreTip != this.Chain.Genesis) { throw new BlockStoreException($"You need to rebuild the {this.StoreName} database using -reindex-chainstate to change -txindex"); } if (this.storeSettings.TxIndex) { await this.BlockRepository.SetTxIndexAsync(this.storeSettings.TxIndex).ConfigureAwait(false); } } this.SetHighestPersistedBlock(this.StoreTip); this.stepChain = new BlockStoreStepChain(); this.stepChain.SetNextStep(new ReorganiseBlockRepositoryStep(this, this.loggerFactory)); this.stepChain.SetNextStep(new CheckNextChainedBlockExistStep(this, this.loggerFactory)); this.stepChain.SetNextStep(new ProcessPendingStorageStep(this, this.loggerFactory)); this.stepChain.SetNextStep(new DownloadBlockStep(this, this.loggerFactory, this.dateTimeProvider)); this.StartLoop(); this.logger.LogTrace("(-)"); }
/// <summary> /// Initialize the BlockStore /// <para> /// If StoreTip is <c>null</c>, the store is out of sync. This can happen when:</para> /// <list> /// <item>1. The node crashed.</item> /// <item>2. The node was not closed down properly.</item> /// </list> /// <para> /// To recover we walk back the chain until a common block header is found /// and set the BlockStore's StoreTip to that. /// </para> /// </summary> public async Task Initialize() { if (this.nodeArgs.Store.ReIndex) { throw new NotImplementedException(); } this.StoreTip = this.Chain.GetBlock(this.BlockRepository.BlockHash); if (this.StoreTip == null) { var blockStoreResetList = new List <uint256>(); Block resetBlock = await this.BlockRepository.GetAsync(this.BlockRepository.BlockHash); uint256 resetBlockHash = resetBlock.GetHash(); while (this.Chain.GetBlock(resetBlockHash) == null) { blockStoreResetList.Add(resetBlockHash); if (resetBlock.Header.HashPrevBlock == this.Chain.Genesis.HashBlock) { resetBlockHash = this.Chain.Genesis.HashBlock; break; } resetBlock = await this.BlockRepository.GetAsync(resetBlock.Header.HashPrevBlock); Guard.NotNull(resetBlock, nameof(resetBlock)); resetBlockHash = resetBlock.GetHash(); } ChainedBlock newTip = this.Chain.GetBlock(resetBlockHash); await this.BlockRepository.DeleteAsync(newTip.HashBlock, blockStoreResetList); this.StoreTip = newTip; this.storeLogger.LogWarning($"{this.name} Initialize recovering to block height = {newTip.Height} hash = {newTip.HashBlock}"); } if (this.nodeArgs.Store.TxIndex != this.BlockRepository.TxIndex) { if (this.StoreTip != this.Chain.Genesis) { throw new BlockStoreException($"You need to rebuild the {this.name} database using -reindex-chainstate to change -txindex"); } if (this.nodeArgs.Store.TxIndex) { await this.BlockRepository.SetTxIndex(this.nodeArgs.Store.TxIndex); } } SetHighestPersistedBlock(this.StoreTip); this.stepChain = new BlockStoreStepChain(); this.stepChain.SetNextStep(new ReorganiseBlockRepositoryStep(this)); this.stepChain.SetNextStep(new CheckNextChainedBlockExistStep(this)); this.stepChain.SetNextStep(new ProcessPendingStorageStep(this)); this.stepChain.SetNextStep(new DownloadBlockStep(this)); StartLoop(); }