예제 #1
0
        private async Task SyncPreviousBlocksAsync(
            BlockChain <T> blockChain,
            BoundPeer peer,
            BlockHash?stop,
            IProgress <BlockDownloadState> progress,
            TimeSpan timeout,
            long totalBlockCount,
            int logSessionId,
            CancellationToken cancellationToken
            )
        {
            long           previousTipIndex = blockChain.Tip?.Index ?? -1;
            BlockChain <T> synced           = null;

            try
            {
                long currentTipIndex    = blockChain.Tip?.Index ?? -1;
                long receivedBlockCount = currentTipIndex - previousTipIndex;

                const string startMsg = "{SessionId}: Starts " + nameof(FillBlocksAsync) + "()...";
                _logger.Debug(startMsg, logSessionId);
                FillBlocksAsyncStarted.Set();
                synced = await FillBlocksAsync(
                    peer,
                    blockChain,
                    stop,
                    progress,
                    totalBlockCount,
                    receivedBlockCount,
                    true,
                    timeout,
                    logSessionId,
                    cancellationToken
                    );

                const string finishMsg = "{SessionId}: Finished " + nameof(FillBlocksAsync) + "().";
                _logger.Debug(finishMsg, logSessionId);
            }
            catch (Exception)
            {
                FillBlocksAsyncFailed.Set();
                throw;
            }
            finally
            {
                var canonComparer = BlockChain.Policy.CanonicalChainComparer;
                if (synced is { } syncedB &&
                    !syncedB.Id.Equals(blockChain?.Id) &&
                    (!(blockChain.Tip is { } tip&& syncedB.Tip is { } syncedTip) ||
                     canonComparer.Compare(
                         blockChain.PerceiveBlock(tip),
                         blockChain.PerceiveBlock(
                             syncedTip,
                             syncedB.PerceiveBlock(syncedTip).PerceivedTime
                             )
                         ) < 0
                    )
                    )
                {
                    _logger.Debug(
                        "{SessionId}: Swap the chain {ChainIdA} for the chain {ChainIdB}...",
                        logSessionId,
                        blockChain.Id,
                        synced.Id
                        );
                    blockChain.Swap(
                        synced,
                        render: true,
                        stateCompleters: null
                        );
                    _logger.Debug(
                        "{SessionId}: The chain {ChainIdB} replaced {ChainIdA}",
                        logSessionId,
                        synced.Id,
                        blockChain.Id
                        );
                }
            }
        }
예제 #2
0
        private bool BlockCandidateProcess(
            SortedList <long, Block <T> > candidate,
            TimeSpan timeout,
            CancellationToken cancellationToken)
        {
            BlockChain <T> synced = null;

            System.Action renderSwap = () => { };
            const string  methodName =
                nameof(Swarm <T>) + "<T>." + nameof(BlockCandidateProcess) + "()";

            try
            {
                FillBlocksAsyncStarted.Set();
                _logger.Debug(
                    methodName + " starts to append. Current tip: #{BlockIndex}.",
                    BlockChain.Tip.Index
                    );
                synced = AppendPreviousBlocks(
                    blockChain: BlockChain,
                    candidate: candidate,
                    timeout: timeout,
                    evaluateActions: true);
                ProcessFillBlocksFinished.Set();
                _logger.Debug(
                    methodName + " finished appending blocks. Synced tip: #{BlockIndex}.",
                    synced.Tip.Index
                    );
            }
            catch (Exception e)
            {
                _logger.Error(e, methodName + " failed to append blocks.");
                FillBlocksAsyncFailed.Set();
                return(false);
            }

            var canonComparer = BlockChain.Policy.CanonicalChainComparer;

            if (synced is { } syncedB &&
                !syncedB.Id.Equals(BlockChain?.Id) &&
                (canonComparer.Compare(
                     BlockChain.PerceiveBlock(BlockChain.Tip),
                     BlockChain.PerceiveBlock(syncedB.Tip)) < 0
                )
                )
            {
                _logger.Debug(
                    "Swapping chain {ChainIdA} with chain {ChainIdB}...",
                    BlockChain.Id,
                    synced.Id
                    );
                renderSwap = BlockChain.Swap(
                    synced,
                    render: true,
                    stateCompleters: null);
                _logger.Debug(
                    "Swapped chain {ChainIdA} with chain {ChainIdB}.",
                    BlockChain.Id,
                    synced.Id
                    );
            }

            renderSwap();
            BroadcastBlock(BlockChain.Tip);
            return(true);
        }