Пример #1
0
        private async Task ConsumeBlockCandidates(
            TimeSpan timeout,
            CancellationToken cancellationToken)
        {
            var checkInterval = TimeSpan.FromMilliseconds(10);

            while (!cancellationToken.IsCancellationRequested)
            {
                if (BlockCandidateTable.Any())
                {
                    BlockHeader tipHeader = BlockChain.Tip.Header;
                    SortedList <long, Block <T> > blocks =
                        BlockCandidateTable.GetCurrentRoundCandidate(tipHeader);
                    if (!(blocks is null))
                    {
                        var latest = blocks.Last();
                        _logger.Debug(
                            "{MethodName} has started. Excerpt: #{BlockIndex} {BlockHash} " +
                            "Count of {BlockCandidateTable}: {Count}",
                            nameof(ConsumeBlockCandidates),
                            latest.Value.Index,
                            latest.Value.Header,
                            nameof(BlockCandidateTable),
                            BlockCandidateTable.Count);
                        _ = BlockCandidateProcess(
                            blocks,
                            timeout,
                            cancellationToken);
                        BlockAppended.Set();
                    }
                }
                else
                {
                    await Task.Delay(checkInterval, cancellationToken);

                    continue;
                }

                BlockCandidateTable.Cleanup(IsBlockNeeded);
            }
        }
Пример #2
0
        private async Task ProcessFillBlocks(
            TimeSpan timeout,
            CancellationToken cancellationToken
            )
        {
            var sessionRandom = new Random();
            IComparer <BlockPerception> canonComparer = BlockChain.Policy.CanonicalChainComparer;

            while (!cancellationToken.IsCancellationRequested)
            {
                int sessionId = sessionRandom.Next();

                if (!(BlockDemand is { } blockDemand))
                {
                    await Task.Delay(1, cancellationToken);

                    continue;
                }

                BoundPeer peer = blockDemand.Peer;

                try
                {
                    if (canonComparer.Compare(
                            BlockChain.PerceiveBlock(BlockDemand?.Header),
                            BlockChain.PerceiveBlock(BlockChain.Tip)
                            ) <= 0)
                    {
                        using (await _blockSyncMutex.LockAsync(cancellationToken))
                        {
                            BlockDemand = null;
                            continue;
                        }
                    }

                    var          hash        = new BlockHash(blockDemand.Header.Hash);
                    const string startLogMsg =
                        "{SessionId}: Got a new " + nameof(BlockDemand) + " from {Peer}; started " +
                        "to fetch the block #{BlockIndex} {BlockHash}...";
                    _logger.Debug(startLogMsg, sessionId, peer, blockDemand.Header.Index, hash);
                    await SyncPreviousBlocksAsync(
                        blockChain : BlockChain,
                        peer : peer,
                        stop : hash,
                        progress : null,
                        timeout : timeout,
                        totalBlockCount : 0,
                        logSessionId : sessionId,
                        cancellationToken : cancellationToken
                        );

                    _logger.Debug(
                        "{SessionId}: Synced block(s) from {Peer}; broadcast them to neighbors...",
                        sessionId,
                        peer
                        );

                    // FIXME: Clean up events
                    BlockReceived.Set();
                    BlockAppended.Set();
                    BroadcastBlock(peer.Address, BlockChain.Tip);

                    ProcessFillBlocksFinished.Set();
                }
                catch (TimeoutException)
                {
                    const string msg =
                        "{SessionId}: Timeout occurred during " + nameof(ProcessFillBlocks) +
                        "() from {Peer}.";
                    _logger.Debug(msg, sessionId, peer);
                }
                catch (InvalidBlockIndexException ibie)
                {
                    const string msg =
                        "{SessionId}: " + nameof(InvalidBlockIndexException) + " occurred during " +
                        nameof(ProcessFillBlocks) + "() from {Peer}: {Exception}";
                    _logger.Warning(ibie, msg, sessionId, peer, ibie);
                }
                catch (Exception e)
                {
                    const string msg =
                        "{SessionId}: Unexpected exception occurred during " +
                        nameof(ProcessFillBlocks) + "() from {Peer}: {Exception}";
                    _logger.Error(e, msg, sessionId, peer, e);
                }
                finally
                {
                    using (await _blockSyncMutex.LockAsync(cancellationToken))
                    {
                        const string msg =
                            "{SessionId}: " + nameof(ProcessFillBlocks) + "() finished.";
                        _logger.Debug(msg, sessionId);
                        if (BlockDemand.Equals(blockDemand))
                        {
                            const string resetMsg =
                                "{SessionId}: Reset " + nameof(BlockDemand) + "...";
                            _logger.Debug(resetMsg, sessionId);
                            BlockDemand = null;
                        }
                    }
                }
            }
        }