public void CanCreateBigSlimChain() { var main = new ConcurrentChain(LoadMainChain(), Network.Main); var c = new SlimChain(main.GetBlock(0).HashBlock); foreach (var item in main.EnumerateToTip(main.GetBlock(0).HashBlock)) { c.TrySetTip(item.HashBlock, item.Previous?.HashBlock); } Assert.Equal(main.Height, c.Height); Assert.Equal(main.Tip.HashBlock, c.Tip); // Can up the capacity without errors c.SetCapacity(main.Height + 3000); Assert.Equal(main.Height, c.Height); Assert.Equal(main.Tip.HashBlock, c.Tip); Assert.Equal(main.GetBlock(main.Tip.HashBlock).HashBlock, c.GetBlock(c.Tip).Hash); }
private async Task ConnectToBitcoinD(CancellationToken cancellation, GetBlockchainInfoResponse blockchainInfo) { var node = GetHandshakedNode(); if (node != null) { return; } try { EnsureNodeDisposed(); _Chain.ResetToGenesis(); _Chain.SetCapacity((int)(blockchainInfo.Headers * 1.1)); if (_Configuration.CacheChain) { LoadChainFromCache(); if (!await HasBlock(_OriginalRPC, _Chain.Tip)) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: The cached chain contains a tip unknown to the node, dropping the cache..."); _Chain.ResetToGenesis(); } } var heightBefore = _Chain.Height; using (var timeout = CancellationTokenSource.CreateLinkedTokenSource(cancellation)) { timeout.CancelAfter(_Network.ChainLoadingTimeout); Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Trying to connect via the P2P protocol to trusted node ({_ChainConfiguration.NodeEndpoint.ToEndpointString()})..."); var userAgent = "NBXplorer-" + RandomUtils.GetInt64(); bool handshaked = false; bool connected = false; bool chainLoaded = false; using (var handshakeTimeout = CancellationTokenSource.CreateLinkedTokenSource(cancellation)) { try { handshakeTimeout.CancelAfter(TimeSpan.FromSeconds(10)); node = await Node.ConnectAsync(_Network.NBitcoinNetwork, _ChainConfiguration.NodeEndpoint, new NodeConnectionParameters() { UserAgent = userAgent, ConnectCancellation = handshakeTimeout.Token, IsRelay = true }); connected = true; Logs.Explorer.LogInformation($"{Network.CryptoCode}: TCP Connection succeed, handshaking..."); node.VersionHandshake(handshakeTimeout.Token); handshaked = true; Logs.Explorer.LogInformation($"{Network.CryptoCode}: Handshaked"); var loadChainTimeout = _Network.NBitcoinNetwork.ChainName == ChainName.Regtest ? TimeSpan.FromSeconds(5) : _Network.ChainCacheLoadingTimeout; if (_Chain.Height < 5) { loadChainTimeout = TimeSpan.FromDays(7); // unlimited } Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Loading chain from node"); try { using (var cts1 = CancellationTokenSource.CreateLinkedTokenSource(cancellation)) { cts1.CancelAfter(loadChainTimeout); Logs.Explorer.LogInformation($"{Network.CryptoCode}: Loading chain..."); node.SynchronizeSlimChain(_Chain, cancellationToken: cts1.Token); } } catch when(!cancellation.IsCancellationRequested) // Timeout happens with SynchronizeChain, if so, throw away the cached chain { Logs.Explorer.LogInformation($"{Network.CryptoCode}: Failed to load chain before timeout, let's try again without the chain cache..."); _Chain.ResetToGenesis(); node.SynchronizeSlimChain(_Chain, cancellationToken: cancellation); } Logs.Explorer.LogInformation($"{Network.CryptoCode}: Chain loaded"); chainLoaded = true; var peer = (await _OriginalRPC.GetPeersInfoAsync()) .FirstOrDefault(p => p.SubVersion == userAgent); if (IsWhitelisted(peer)) { Logs.Explorer.LogInformation($"{Network.CryptoCode}: NBXplorer is correctly whitelisted by the node"); } else { var addressStr = peer.Address is IPEndPoint end?end.Address.ToString() : peer.Address?.ToString(); Logs.Explorer.LogWarning($"{Network.CryptoCode}: Your NBXplorer server is not whitelisted by your node," + $" you should add \"whitelist={addressStr}\" to the configuration file of your node. (Or use whitebind)"); } } catch { if (!connected) { Logs.Explorer.LogWarning($"{Network.CryptoCode}: NBXplorer failed to connect to the node via P2P ({_ChainConfiguration.NodeEndpoint.ToEndpointString()}).{Environment.NewLine}" + $"It may come from: A firewall blocking the traffic, incorrect IP or port, or your node may not have an available connection slot. {Environment.NewLine}" + $"To make sure your node have an available connection slot, use \"whitebind\" or \"whitelist\" in your node configuration. (typically whitelist=127.0.0.1 if NBXplorer and the node are on the same machine.){Environment.NewLine}"); } else if (!handshaked) { Logs.Explorer.LogWarning($"{Network.CryptoCode}: NBXplorer connected to the remote node but failed to handhsake via P2P.{Environment.NewLine}" + $"Your node may not have an available connection slot, or you may try to connect to the wrong node. (ie, trying to connect to a LTC node on the BTC configuration).{Environment.NewLine}" + $"To make sure your node have an available connection slot, use \"whitebind\" or \"whitelist\" in your node configuration. (typically whitelist=127.0.0.1 if NBXplorer and the node are on the same machine.){Environment.NewLine}"); } else if (!chainLoaded) { Logs.Explorer.LogWarning($"{Network.CryptoCode}: NBXplorer connected and handshaked the remote node but failed to load the chain of header.{Environment.NewLine}" + $"Your connection may be throttled, or you may try to connect to the wrong node. (ie, trying to connect to a LTC node on the BTC configuration).{Environment.NewLine}"); } throw; } } } Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Height: " + _Chain.Height); if (_Configuration.CacheChain && heightBefore != _Chain.Height) { SaveChainInCache(); } GC.Collect(); node.Behaviors.Add(new SlimChainBehavior(_Chain)); var explorer = (ExplorerBehavior)_ExplorerPrototype.Clone(); node.Behaviors.Add(explorer); node.StateChanged += Node_StateChanged; _Node = node; } catch { EnsureNodeDisposed(node ?? _Node); throw; } }