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]); } }
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]); }
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); }
public void UpdateBestSentHeader_ChangesIfPreviousValueWasNull() { ConsensusManagerBehavior behavior = this.helper.CreateAndAttachBehavior(this.headers[20]); behavior.UpdateBestSentHeader(this.headers[10]); Assert.Equal(this.headers[10], behavior.BestSentHeader); }
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); }
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); }
protected override void AttachCore() { this.logger.LogTrace("()"); this.AttachedPeer.MessageReceived.Register(this.OnMessageReceivedAsync); this.consensusManagerBehavior = this.AttachedPeer.Behavior <ConsensusManagerBehavior>(); this.logger.LogTrace("(-)"); }
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); }
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); }
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); }
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); }
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); }
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); }
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)); }
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); } }
public List <BlockHeader> GetCachedHeaders(ConsensusManagerBehavior behavior) { return(behavior.GetMemberValue("cachedHeaders") as List <BlockHeader>); }
/// <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); }
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)); }