コード例 #1
0
        public async Task ProcessHeadersAsync_DontSyncAfterSomeHeadersConsumedAndSomeCachedAsync()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[10], null, null, NetworkPeerState.HandShaked,
                                                                                    (presentedHeaders, triggerDownload) =>
            {
                return(new ConnectNewHeadersResult()
                {
                    Consumed = this.headers[40]
                });
            });

            await this.helper.ReceivePayloadAsync(new HeadersPayload(this.headers.Skip(11).Take(40).Select(x => x.Header)));

            Assert.Equal(this.headers[40], behavior.BestReceivedTip);
            Assert.Equal(0, this.helper.GetHeadersPayloadSentTimes);

            List <BlockHeader> cached = this.helper.GetCachedHeaders(behavior);

            Assert.Equal(10, cached.Count);

            for (int i = 41; i <= 50; i++)
            {
                Assert.Equal(this.headers[i].Header, cached[i - 41]);
            }
        }
コード例 #2
0
        public async Task ConsensusTipChanged_CachedHeadersConsumedFullyAsync()
        {
            var cache = new List <BlockHeader>()
            {
                this.headers[11].Header, this.headers[12].Header
            };

            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], cache, this.headers[10], NetworkPeerState.HandShaked,
                                                                                    (presentedHeaders, triggerDownload) =>
            {
                Assert.Equal(this.headers[12].Header, presentedHeaders.Last());

                return(new ConnectNewHeadersResult()
                {
                    Consumed = this.headers[12]
                });
            });

            ConnectNewHeadersResult result = await behavior.ConsensusTipChangedAsync();

            Assert.Equal(this.headers[12], behavior.BestReceivedTip);
            Assert.Equal(this.headers[12], behavior.BestSentHeader);
            Assert.Empty(this.helper.GetCachedHeaders(behavior));
            Assert.Equal(1, this.helper.GetHeadersPayloadSentTimes);
            Assert.Equal(result.Consumed, this.headers[12]);
        }
コード例 #3
0
        public void UpdateBestSentHeader_DoesntChangeIfArgumentIsNull()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20], null, this.headers[10]);

            behavior.UpdateBestSentHeader(null);

            Assert.Equal(this.headers[10], behavior.BestSentHeader);
        }
コード例 #4
0
        public void UpdateBestSentHeader_ChangesIfPreviousValueWasNull()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20]);

            behavior.UpdateBestSentHeader(this.headers[10]);

            Assert.Equal(this.headers[10], behavior.BestSentHeader);
        }
コード例 #5
0
        public void UpdateBestSentHeader_DoesntChangeIfCalledWithAncestor()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20], null, this.headers[10]);

            behavior.UpdateBestSentHeader(this.headers[5]);

            Assert.Equal(this.headers[10], behavior.BestSentHeader);
        }
コード例 #6
0
        public void UpdateBestSentHeader_IsSetIfChainProlonged()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20], null, this.headers[10]);

            behavior.UpdateBestSentHeader(this.headers[15]);

            Assert.Equal(this.headers[15], behavior.BestSentHeader);
        }
コード例 #7
0
        protected override void AttachCore()
        {
            this.logger.LogTrace("()");

            this.AttachedPeer.MessageReceived.Register(this.OnMessageReceivedAsync);
            this.consensusManagerBehavior = this.AttachedPeer.Behavior <ConsensusManagerBehavior>();

            this.logger.LogTrace("(-)");
        }
コード例 #8
0
        public void UpdateBestSentHeader_ChangedIfHeaderIsOnFork()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20], null, this.headers[10]);

            ChainedHeader headerOnChainB = ChainedHeadersHelper.CreateConsecutiveHeaders(7, this.headers[8]).Last();

            behavior.UpdateBestSentHeader(headerOnChainB);

            Assert.Equal(headerOnChainB, behavior.BestSentHeader);
        }
コード例 #9
0
        public async Task ResetPeerTipInformationAndSyncAsync_ResyncsAndResetsAsync()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], null, this.headers[5]);

            await behavior.ResetPeerTipInformationAndSyncAsync();

            Assert.Null(behavior.BestReceivedTip);
            Assert.Null(behavior.BestSentHeader);
            Assert.Equal(1, this.helper.GetHeadersPayloadSentTimes);
        }
コード例 #10
0
        public async Task ConsensusTipChanged_ConsensusTipAdvancedBuNoCachedHeadersAsync()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], null, this.headers[10]);

            ConnectNewHeadersResult result = await behavior.ConsensusTipChangedAsync();

            Assert.Null(result);
            Assert.Equal(0, this.helper.GetHeadersPayloadSentTimes);
            Assert.Equal(0, this.helper.HeadersPresentedCalledTimes);
        }
コード例 #11
0
        public async Task ProcessHeadersAsync_ConsumeAllHeadersAndAskForMoreAsync()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[10], null, null, NetworkPeerState.HandShaked,
                                                                                    (presentedHeaders, triggerDownload) =>
            {
                return(new ConnectNewHeadersResult()
                {
                    Consumed = this.headers.Single(x => x.HashBlock == presentedHeaders.Last().GetHash())
                });
            });

            await this.helper.ReceivePayloadAsync(new HeadersPayload(this.headers.Skip(11).Take(5).Select(x => x.Header)));

            Assert.Equal(this.headers[15], behavior.BestReceivedTip);
            Assert.Equal(1, this.helper.GetHeadersPayloadSentTimes);
        }
コード例 #12
0
        public async Task ConsensusTipChanged_PeerNotAttachedAsync()
        {
            var cache = new List <BlockHeader>()
            {
                this.headers[11].Header, this.headers[12].Header
            };

            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], cache, this.headers[10]);

            // That will set peer to null.
            behavior.Dispose();

            ConnectNewHeadersResult result = await behavior.ConsensusTipChangedAsync();

            Assert.Equal(0, this.helper.GetHeadersPayloadSentTimes);
            Assert.Equal(0, this.helper.HeadersPresentedCalledTimes);
            Assert.Null(result);
        }
コード例 #13
0
        public async Task ProcessHeadersAsync_DontSyncAfterCacheIsPopulatedAsync()
        {
            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], new List <BlockHeader>()
            {
                this.headers[1].Header
            });

            await this.helper.ReceivePayloadAsync(new HeadersPayload(this.headers.Skip(2).Take(10).Select(x => x.Header)));

            List <BlockHeader> cached = this.helper.GetCachedHeaders(behavior);

            Assert.Equal(11, cached.Count);

            for (int i = 0; i < 11; i++)
            {
                Assert.Equal(this.headers[i + 1].Header, cached[i]);
            }

            Assert.Equal(0, this.helper.GetHeadersPayloadSentTimes);
        }
コード例 #14
0
        public async Task ConsensusTipChanged_NotAbleToConnectCachedHeadersAsync()
        {
            var cache = new List <BlockHeader>()
            {
                this.headers[14].Header, this.headers[15].Header
            };

            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], cache, this.headers[10], NetworkPeerState.HandShaked,
                                                                                    (presentedHeaders, triggerDownload) =>
            {
                Assert.Equal(this.headers[14].Header, presentedHeaders.First());

                throw new ConnectHeaderException();
            });

            ConnectNewHeadersResult result = await behavior.ConsensusTipChangedAsync();

            Assert.Equal(this.headers[10], behavior.BestReceivedTip);
            Assert.Equal(this.headers[10], behavior.BestSentHeader);
            Assert.Equal(1, this.helper.GetHeadersPayloadSentTimes);
            Assert.Null(result);
            Assert.Empty(this.helper.GetCachedHeaders(behavior));
        }
コード例 #15
0
        public async Task ConsensusTipChanged_CachedHeadersConsumedPartiallyAsync()
        {
            var cache = new List <BlockHeader>();

            for (int i = 11; i <= 50; i++)
            {
                cache.Add(this.headers[i].Header);
            }

            ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[5], cache, this.headers[10], NetworkPeerState.HandShaked,
                                                                                    (presentedHeaders, triggerDownload) =>
            {
                Assert.Equal(this.headers[50].Header, presentedHeaders.Last());

                return(new ConnectNewHeadersResult()
                {
                    Consumed = this.headers[40]
                });
            });

            ConnectNewHeadersResult result = await behavior.ConsensusTipChangedAsync();

            Assert.Equal(this.headers[40], behavior.BestReceivedTip);
            Assert.Equal(this.headers[40], behavior.BestSentHeader);
            Assert.Equal(0, this.helper.GetHeadersPayloadSentTimes);
            Assert.Equal(result.Consumed, this.headers[40]);

            List <BlockHeader> cacheAfterTipChanged = this.helper.GetCachedHeaders(behavior);

            Assert.Equal(10, cacheAfterTipChanged.Count);

            for (int i = 41; i <= 50; i++)
            {
                Assert.Contains(this.headers[i].Header, cacheAfterTipChanged);
            }
        }
コード例 #16
0
 public List <BlockHeader> GetCachedHeaders(ConsensusManagerBehavior behavior)
 {
     return(behavior.GetMemberValue("cachedHeaders") as List <BlockHeader>);
 }
コード例 #17
0
        /// <summary>Creates the and attaches a new <see cref="ConsensusManagerBehavior"/>.</summary>
        /// <param name="consensusTip">Consensus tip.</param>
        /// <param name="cache">List of cached headers with which behavior is initialized.</param>
        /// <param name="bestReceivedTip">Behavior's expected tip's initial value.</param>
        /// <param name="peerState">Peer connection state returned by the <see cref="INetworkPeer.State"/>.</param>
        /// <param name="connectNewHeadersMethod">Method which is invoked when behavior calls <see cref="IConsensusManager.HeadersPresented"/>.</param>
        /// <returns></returns>
        public ConsensusManagerBehavior CreateAndAttachBehavior(ChainedHeader consensusTip, List <BlockHeader> cache = null,
                                                                ChainedHeader bestReceivedTip = null, NetworkPeerState peerState = NetworkPeerState.HandShaked,
                                                                Func <List <BlockHeader>, bool, ConnectNewHeadersResult> connectNewHeadersMethod = null)
        {
            // Chain
            var chain = new ConcurrentChain(KnownNetworks.StratisMain);

            chain.SetTip(consensusTip);

            // Ibd
            var ibdState = new Mock <IInitialBlockDownloadState>();

            ibdState.Setup(x => x.IsInitialBlockDownload()).Returns(() => this.IsIBD);

            // Consensus manager
            var cmMock = new Mock <IConsensusManager>();

            cmMock.Setup(x => x.HeadersPresented(It.IsAny <INetworkPeer>(), It.IsAny <List <BlockHeader> >(), It.IsAny <bool>()))
            .Returns((INetworkPeer p, List <BlockHeader> presentedHeaders, bool triggerDownload) =>
            {
                this.HeadersPresentedCalledTimes++;

                return(connectNewHeadersMethod?.Invoke(presentedHeaders, triggerDownload));
            });

            cmMock.Setup(x => x.Tip).Returns(consensusTip);

            this.testPeerBanning = new TestPeerBanning();

            var connectionManagerMock = new Mock <IConnectionManager>();

            connectionManagerMock.SetupGet(x => x.ConnectionSettings).Returns(new ConnectionManagerSettings(new NodeSettings(KnownNetworks.StratisMain)));

            var cmBehavior = new ConsensusManagerBehavior(chain, ibdState.Object, cmMock.Object, this.testPeerBanning, this.loggerFactory);

            // Peer and behavior
            this.PeerMock = this.CreatePeerMock();

            cmBehavior.Attach(this.PeerMock.Object);

            this.PeerMock.Setup(x => x.Behavior <ConsensusManagerBehavior>()).Returns(() => cmBehavior);
            this.PeerMock.Setup(x => x.State).Returns(peerState);

            if (bestReceivedTip != null)
            {
                cmBehavior.SetPrivatePropertyValue(nameof(cmBehavior.BestReceivedTip), bestReceivedTip);
                cmBehavior.SetPrivatePropertyValue(nameof(cmBehavior.BestSentHeader), bestReceivedTip);
            }

            if (cache != null)
            {
                cmBehavior.SetPrivateVariableValue("cachedHeaders", cache);
            }

            this.GetHeadersPayloadSentTimes = 0;
            this.HeadersPayloadsSent        = new List <HeadersPayload>();
            this.GetHeadersPayloadsSent     = new List <GetHeadersPayload>();

            this.PeerMock.Setup(x => x.SendMessageAsync(It.IsAny <Payload>(), It.IsAny <CancellationToken>())).Returns((Payload payload, CancellationToken token) =>
            {
                if (payload is GetHeadersPayload getHeadersPayload)
                {
                    this.GetHeadersPayloadSentTimes++;
                    this.GetHeadersPayloadsSent.Add(getHeadersPayload);
                }

                if (payload is HeadersPayload headersPayload)
                {
                    this.HeadersPayloadsSent.Add(headersPayload);
                }

                return(Task.CompletedTask);
            });

            this.PeerMock.Setup(x => x.SendMessage(It.IsAny <Payload>())).Callback((Payload payload) =>
            {
                if (payload is GetHeadersPayload getHeadersPayload)
                {
                    this.GetHeadersPayloadSentTimes++;
                    this.GetHeadersPayloadsSent.Add(getHeadersPayload);
                }

                if (payload is HeadersPayload headersPayload)
                {
                    this.HeadersPayloadsSent.Add(headersPayload);
                }
            });

            return(cmBehavior);
        }
コード例 #18
0
        public IActionResult Status([FromQuery] bool publish)
        {
            // Output has been merged with RPC's GetInfo() since they provided similar functionality.
            var model = new StatusModel
            {
                Version           = this.fullNode.Version?.ToString() ?? "0",
                ProtocolVersion   = (uint)(this.nodeSettings.ProtocolVersion),
                Difficulty        = GetNetworkDifficulty(this.networkDifficulty)?.Difficulty ?? 0,
                Agent             = this.connectionManager.ConnectionSettings.Agent,
                ExternalAddress   = this.selfEndpointTracker.MyExternalAddress.Address.ToString(),
                ProcessId         = Process.GetCurrentProcess().Id,
                Network           = this.fullNode.Network.Name,
                ConsensusHeight   = this.chainState.ConsensusTip?.Height,
                DataDirectoryPath = this.nodeSettings.DataDir,
                Testnet           = this.network.IsTest(),
                RelayFee          = this.nodeSettings.MinRelayTxFeeRate?.FeePerK?.ToUnit(MoneyUnit.BTC) ?? 0,
                RunningTime       = this.dateTimeProvider.GetUtcNow() - this.fullNode.StartTime,
                CoinTicker        = this.network.CoinTicker,
                State             = this.fullNode.State.ToString(),
                BestPeerHeight    = this.chainState.BestPeerTip?.Height,
                InIbd             = this.initialBlockDownloadState.IsInitialBlockDownload()
            };

            try
            {
                model.HeaderHeight = this.consensusManager.HeaderTip;
            }
            catch (Exception)
            {
                // It is possible that consensus manager has not yet initialized when calling this.
                model.HeaderHeight = 0;
            }

            if (publish)
            {
                this.signals.Publish(new FullNodeEvent()
                {
                    Message = "Full State Requested", State = this.fullNode.State.ToString()
                });
            }

            // Add the list of features that are enabled.
            foreach (IFullNodeFeature feature in this.fullNode.Services.Features)
            {
                model.FeaturesData.Add(new FeatureData
                {
                    Namespace = feature.GetType().ToString(),
                    State     = feature.State.ToString()
                });
            }

            // Include BlockStore Height if enabled
            if (this.chainState.BlockStoreTip != null)
            {
                model.BlockStoreHeight = this.chainState.BlockStoreTip.Height;
            }

            // Add the details of connected nodes.
            foreach (INetworkPeer peer in this.connectionManager.ConnectedPeers)
            {
                ConsensusManagerBehavior chainHeadersBehavior = peer.Behavior <ConsensusManagerBehavior>();

                var connectedPeer = new ConnectedPeerModel
                {
                    Version = peer.PeerVersion != null ? peer.PeerVersion.UserAgent : "[Unknown]",
                    RemoteSocketEndpoint = peer.RemoteSocketEndpoint.ToString(),
                    TipHeight            = chainHeadersBehavior.BestReceivedTip != null ? chainHeadersBehavior.BestReceivedTip.Height : peer.PeerVersion?.StartHeight ?? -1,
                    IsInbound            = peer.Inbound
                };

                if (connectedPeer.IsInbound)
                {
                    model.InboundPeers.Add(connectedPeer);
                }
                else
                {
                    model.OutboundPeers.Add(connectedPeer);
                }
            }

            return(this.Json(model));
        }