Exemplo n.º 1
0
        /// <summary>Rewinds the connected part of invalid chain.</summary>
        private async Task RewindPartiallyConnectedChainAsync(ChainedHeader lastValidatedBlockHeader, ChainedHeader currentTip)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}'", nameof(lastValidatedBlockHeader), lastValidatedBlockHeader, nameof(currentTip), currentTip);

            ChainedHeader current = lastValidatedBlockHeader;

            while (currentTip.Height < current.Height)
            {
                RewindState transitionState = await this.consensusRules.RewindAsync().ConfigureAwait(false);

                lock (this.peerLock)
                {
                    current = this.chainedHeaderTree.GetChainedHeader(transitionState.BlockHash);
                }
            }

            if (currentTip.Height != current.Height)
            {
                // The rewind operation must return to the same fork point.
                this.logger.LogError("The rewind operation ended up at '{0}' instead of fork point '{1}'.", currentTip, current);
                this.logger.LogTrace("(-)[INVALID_REWIND]");
                throw new ConsensusException("The rewind operation must return to the same fork point.");
            }

            this.logger.LogTrace("(-)");
        }
Exemplo n.º 2
0
        /// <summary>Rewinds to fork point or below it.</summary>
        /// <returns>New consensus tip.</returns>
        private async Task <ChainedHeader> RewindToForkPointOrBelowAsync(ChainedHeader fork, ChainedHeader oldTip)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}'", nameof(fork), fork, nameof(oldTip), oldTip);

            ChainedHeader currentTip = oldTip;

            while (fork.Height < currentTip.Height)
            {
                RewindState transitionState = await this.consensusRules.RewindAsync().ConfigureAwait(false);

                lock (this.peerLock)
                {
                    currentTip = this.chainedHeaderTree.GetChainedHeader(transitionState.BlockHash);
                }
            }

            this.logger.LogTrace("(-):'{0}'", currentTip);
            return(currentTip);
        }
Exemplo n.º 3
0
        /// <inheritdoc />
        /// <remarks>
        /// If <see cref="blockStore"/> is not <c>null</c> (block store is available) then all block headers in
        /// <see cref="chainedHeaderTree"/> will be marked as their block data is available.
        /// If store is not available the <see cref="ConsensusManager"/> won't be able to serve blocks from disk,
        /// instead all block requests that are not in memory will be sent to the <see cref="blockPuller"/>.
        /// </remarks>
        public async Task InitializeAsync(ChainedHeader chainTip)
        {
            this.logger.LogTrace("({0}:'{1}')", nameof(chainTip), chainTip);

            // TODO: consensus store
            // We should consider creating a consensus store class that will internally contain
            // coinview and it will abstract the methods `RewindAsync()` `GetBlockHashAsync()`

            uint256 consensusTipHash = await this.consensusRules.GetBlockHashAsync().ConfigureAwait(false);

            while (true)
            {
                this.Tip = chainTip.FindAncestorOrSelf(consensusTipHash);

                if (this.Tip?.HashBlock == consensusTipHash)
                {
                    break;
                }

                // In case block store initialized behind, rewind until or before the block store tip.
                // The node will complete loading before connecting to peers so the chain will never know if a reorg happened.
                RewindState transitionState = await this.consensusRules.RewindAsync().ConfigureAwait(false);

                consensusTipHash = transitionState.BlockHash;
            }

            this.chainState.ConsensusTip = this.Tip;

            this.chainedHeaderTree.Initialize(this.Tip, this.blockStore != null);

            this.blockPuller.Initialize();

            this.isIbd = this.ibdState.IsInitialBlockDownload();
            this.blockPuller.OnIbdStateChanged(this.isIbd);

            this.logger.LogTrace("(-)");
        }