コード例 #1
0
        public async Task CanConnectWithDifferentModesAsync()
        {
            var connector = new BestEffortEndpointConnector(6);
            var nodeConnectionParameters = new NodeConnectionParameters();

            nodeConnectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(new IPEndPoint(IPAddress.Loopback, 8090), onlyForOnionHosts: true, networkCredential: null, streamIsolation: true));

            using var nodes = new NodesGroup(Network.TestNet, nodeConnectionParameters);

            async Task ConnectAsync(EndPoint endpoint)
            {
                using var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
                await connector.ConnectSocket(socket, endpoint, nodeConnectionParameters, CancellationToken.None);
            }

            Exception ex;

            // Try to connect to a non-onion address.
            ex = await Assert.ThrowsAsync <SocketException>(
                async() => await ConnectAsync(new IPEndPoint(IPAddress.Loopback, 180)));

            Assert.Contains("refused", ex.Message);
            Assert.False(connector.State.AllowOnlyTorEndpoints);

            // Try to connect to an onion address (it has to fail because there is no real socks proxy listening).
            ex = await Assert.ThrowsAnyAsync <SocketException>(
                async() => await ConnectAsync(new DnsEndPoint("nec4kn4ghql7p7an.onion", 180)));

            Assert.Contains("refused", ex.Message);
            Assert.False(connector.State.AllowOnlyTorEndpoints);

            // Simulate we lost connection.
            connector.State.ConnectedNodesCount = 10;
            ex = await Assert.ThrowsAsync <SocketException>(
                async() => await ConnectAsync(new IPEndPoint(IPAddress.Loopback, 180)));

            Assert.Contains("refused", ex.Message);
            Assert.True(connector.State.AllowOnlyTorEndpoints);

            ex = await Assert.ThrowsAnyAsync <SocketException>(
                async() => await ConnectAsync(new DnsEndPoint("nec4kn4ghql7p7an.onion", 180)));

            Assert.Contains("refused", ex.Message);
            Assert.True(connector.State.AllowOnlyTorEndpoints);

            // Simulate we lost connection.
            connector.State.ConnectedNodesCount = 0;
            ex = await Assert.ThrowsAsync <SocketException>(
                async() => await ConnectAsync(new IPEndPoint(IPAddress.Loopback, 180)));

            Assert.Contains("refused", ex.Message);
            Assert.False(connector.State.AllowOnlyTorEndpoints);

            // Try to connect to an onion address (it has to fail because there is no real socks proxy listening).
            ex = await Assert.ThrowsAnyAsync <SocketException>(
                async() => await ConnectAsync(new DnsEndPoint("nec4kn4ghql7p7an.onion", 180)));

            Assert.Contains("refused", ex.Message);
            Assert.False(connector.State.AllowOnlyTorEndpoints);

            // Enough peers with recent connection.
            connector.State.ConnectedNodesCount = 10;
            ex = await Assert.ThrowsAnyAsync <SocketException>(
                async() => await ConnectAsync(new DnsEndPoint("nec4kn4ghql7p7an.onion", 180)));

            Assert.Contains("refused", ex.Message);
            Assert.True(connector.State.AllowOnlyTorEndpoints);
        }
コード例 #2
0
ファイル: P2pNetwork.cs プロジェクト: yahiheb/WalletWasabi
        public P2pNetwork(Network network, EndPoint fullnodeP2pEndPoint, EndPoint?torSocks5EndPoint, string workDir, BitcoinStore bitcoinStore)
        {
            Network             = network;
            FullnodeP2PEndPoint = fullnodeP2pEndPoint;
            TorSocks5EndPoint   = torSocks5EndPoint;
            WorkDir             = workDir;
            BitcoinStore        = bitcoinStore;

            var userAgent            = Constants.UserAgents.RandomElement();
            var connectionParameters = new NodeConnectionParameters {
                UserAgent = userAgent
            };

            connectionParameters.TemplateBehaviors.Add(BitcoinStore.CreateUntrustedP2pBehavior());

            AddressManagerFilePath = Path.Combine(WorkDir, $"AddressManager{Network}.dat");
            var needsToDiscoverPeers = true;

            if (Network == Network.RegTest)
            {
                AddressManager = new AddressManager();
                Logger.LogInfo($"Fake {nameof(AddressManager)} is initialized on the {Network.RegTest}.");
            }
            else
            {
                try
                {
                    AddressManager = AddressManager.LoadPeerFile(AddressManagerFilePath);

                    // Most of the times we do not need to discover new peers. Instead, we can connect to
                    // some of those that we already discovered in the past. In this case we assume that
                    // discovering new peers could be necessary if our address manager has less
                    // than 500 addresses. 500 addresses could be okay because previously we tried with
                    // 200 and only one user reported he/she was not able to connect (there could be many others,
                    // of course).
                    // On the other side, increasing this number forces users that do not need to discover more peers
                    // to spend resources (CPU/bandwidth) to discover new peers.
                    needsToDiscoverPeers = TorSocks5EndPoint is not null || AddressManager.Count < 500;
                    Logger.LogInfo($"Loaded {nameof(AddressManager)} from `{AddressManagerFilePath}`.");
                }
                catch (DirectoryNotFoundException ex)
                {
                    Logger.LogInfo($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one.");
                    Logger.LogTrace(ex);
                    AddressManager = new AddressManager();
                }
                catch (FileNotFoundException ex)
                {
                    Logger.LogInfo($"{nameof(AddressManager)} did not exist at `{AddressManagerFilePath}`. Initializing new one.");
                    Logger.LogTrace(ex);
                    AddressManager = new AddressManager();
                }
                catch (OverflowException ex)
                {
                    // https://github.com/zkSNACKs/WalletWasabi/issues/712
                    Logger.LogInfo($"{nameof(AddressManager)} has thrown `{nameof(OverflowException)}`. Attempting to autocorrect.");
                    File.Delete(AddressManagerFilePath);
                    Logger.LogTrace(ex);
                    AddressManager = new AddressManager();
                    Logger.LogInfo($"{nameof(AddressManager)} autocorrection is successful.");
                }
                catch (FormatException ex)
                {
                    // https://github.com/zkSNACKs/WalletWasabi/issues/880
                    Logger.LogInfo($"{nameof(AddressManager)} has thrown `{nameof(FormatException)}`. Attempting to autocorrect.");
                    File.Delete(AddressManagerFilePath);
                    Logger.LogTrace(ex);
                    AddressManager = new AddressManager();
                    Logger.LogInfo($"{nameof(AddressManager)} autocorrection is successful.");
                }
            }

            var addressManagerBehavior = new AddressManagerBehavior(AddressManager)
            {
                Mode = needsToDiscoverPeers ? AddressManagerBehaviorMode.Discover : AddressManagerBehaviorMode.None
            };

            connectionParameters.TemplateBehaviors.Add(addressManagerBehavior);

            if (Network == Network.RegTest)
            {
                Nodes = new NodesGroup(Network, requirements: Constants.NodeRequirements);
            }
            else
            {
                var maximumNodeConnection       = 12;
                var bestEffortEndpointConnector = new BestEffortEndpointConnector(maximumNodeConnection / 2);
                connectionParameters.EndpointConnector = bestEffortEndpointConnector;
                if (TorSocks5EndPoint is not null)
                {
                    connectionParameters.TemplateBehaviors.Add(new SocksSettingsBehavior(TorSocks5EndPoint, onlyForOnionHosts: false, networkCredential: null, streamIsolation: true));
                }
                var nodes = new NodesGroup(Network, connectionParameters, requirements: Constants.NodeRequirements);
                nodes.ConnectedNodes.Added   += ConnectedNodes_OnAddedOrRemoved;
                nodes.ConnectedNodes.Removed += ConnectedNodes_OnAddedOrRemoved;
                nodes.MaximumNodeConnection   = maximumNodeConnection;

                Nodes = nodes;
            }
        }