private void StartNodeServer()
        {
            var logs = new StringBuilder();

            logs.AppendLine("Node listening on:");

            foreach (NodeServerEndpoint listen in this.ConnectionSettings.Listen)
            {
                NetworkPeerConnectionParameters cloneParameters = this.Parameters.Clone();
                NetworkPeerServer server = this.NetworkPeerFactory.CreateNetworkPeerServer(listen.Endpoint, this.ConnectionSettings.ExternalEndpoint);

                this.Servers.Add(server);
                cloneParameters.TemplateBehaviors.Add(new ConnectionManagerBehavior(true, this, this.loggerFactory)
                {
                    Whitelisted = listen.Whitelisted
                });

                server.InboundNetworkPeerConnectionParameters = cloneParameters;
                try
                {
                    server.Listen();
                }
                catch (SocketException e)
                {
                    this.logger.LogCritical("Unable to listen on port {0} (you can change the port using '-port=[number]'). Error message: {1}", listen.Endpoint.Port, e.Message);
                    throw e;
                }

                logs.Append(listen.Endpoint.Address + ":" + listen.Endpoint.Port);
                if (listen.Whitelisted)
                {
                    logs.Append(" (whitelisted)");
                }

                logs.AppendLine();
            }

            this.logger.LogInformation(logs.ToString());
        }
Пример #2
0
        /// <summary>
        ///     Initializes node's address manager. Loads previously known peers from the file
        ///     or creates new peer file if it does not exist. Creates periodic task to persist changes
        ///     in peers to disk.
        /// </summary>
        void StartAddressManager(NetworkPeerConnectionParameters connectionParameters)
        {
            var addressManagerBehaviour = new PeerAddressManagerBehaviour(this.dateTimeProvider,
                                                                          this.peerAddressManager, this.peerBanning, this.loggerFactory);

            connectionParameters.TemplateBehaviors.Add(addressManagerBehaviour);

            if (File.Exists(Path.Combine(this.dataFolder.AddressManagerFilePath, PeerAddressManager.PeerFileName)))
            {
                this.logger.LogInformation($"Loading peers from : {this.dataFolder.AddressManagerFilePath}.");
                this.peerAddressManager.LoadPeers();
            }

            this.flushAddressManagerLoop = this.asyncProvider.CreateAndRunAsyncLoop("Periodic peer flush", token =>
            {
                this.peerAddressManager.SavePeers();
                return(Task.CompletedTask);
            },
                                                                                    this.nodeLifetime.ApplicationStopping,
                                                                                    TimeSpan.FromMinutes(5.0),
                                                                                    TimeSpan.FromMinutes(5.0));
        }
Пример #3
0
        /// <inheritdoc />
        public override async Task InitializeAsync()
        {
            this.dbreezeSerializer.Initialize(this.chain.Network);

            await this.StartChainAsync().ConfigureAwait(false);

            NetworkPeerConnectionParameters connectionParameters = this.connectionManager.Parameters;

            connectionParameters.IsRelay = this.connectionManager.ConnectionSettings.RelayTxes;

            connectionParameters.TemplateBehaviors.Add(new PingPongBehavior());
            connectionParameters.TemplateBehaviors.Add(new ConsensusManagerBehavior(this.chain, this.initialBlockDownloadState, this.consensusManager, this.peerBanning, this.loggerFactory));
            connectionParameters.TemplateBehaviors.Add(new PeerBanningBehavior(this.loggerFactory, this.peerBanning, this.nodeSettings));
            connectionParameters.TemplateBehaviors.Add(new BlockPullerBehavior(this.blockPuller, this.initialBlockDownloadState, this.dateTimeProvider, this.loggerFactory));
            connectionParameters.TemplateBehaviors.Add(new ConnectionManagerBehavior(this.connectionManager, this.loggerFactory));

            this.StartAddressManager(connectionParameters);

            if (this.connectionManager.ConnectionSettings.SyncTimeEnabled)
            {
                connectionParameters.TemplateBehaviors.Add(new TimeSyncBehavior(this.timeSyncBehaviorState, this.dateTimeProvider, this.loggerFactory));
            }
            else
            {
                this.logger.LogDebug("Time synchronization with peers is disabled.");
            }

            // Block store must be initialized before consensus manager.
            // This may be a temporary solution until a better way is found to solve this dependency.
            await this.blockStore.InitializeAsync().ConfigureAwait(false);

            await this.consensusRules.InitializeAsync(this.chain.Tip).ConfigureAwait(false);

            this.consensusRules.Register();

            await this.consensusManager.InitializeAsync(this.chain.Tip).ConfigureAwait(false);

            this.chainState.ConsensusTip = this.consensusManager.Tip;
        }
        public ConnectionManager(IDateTimeProvider dateTimeProvider,
                                 ILoggerFactory loggerFactory,
                                 Network network,
                                 INetworkPeerFactory networkPeerFactory,
                                 NodeSettings nodeSettings,
                                 INodeLifetime nodeLifetime,
                                 NetworkPeerConnectionParameters parameters,
                                 IPeerAddressManager peerAddressManager,
                                 IEnumerable <IPeerConnector> peerConnectors,
                                 IPeerDiscovery peerDiscovery,
                                 ConnectionManagerSettings connectionSettings,
                                 IVersionProvider versionProvider)
        {
            this.connectedPeers      = new NetworkPeerCollection();
            this.dateTimeProvider    = dateTimeProvider;
            this.loggerFactory       = loggerFactory;
            this.logger              = loggerFactory.CreateLogger(this.GetType().FullName);
            this.Network             = network;
            this.NetworkPeerFactory  = networkPeerFactory;
            this.NodeSettings        = nodeSettings;
            this.nodeLifetime        = nodeLifetime;
            this.peerAddressManager  = peerAddressManager;
            this.PeerConnectors      = peerConnectors;
            this.peerDiscovery       = peerDiscovery;
            this.ConnectionSettings  = connectionSettings;
            this.networkPeerDisposer = new NetworkPeerDisposer(this.loggerFactory);
            this.Servers             = new List <NetworkPeerServer>();

            this.Parameters = parameters;
            this.Parameters.ConnectCancellation = this.nodeLifetime.ApplicationStopping;
            this.versionProvider = versionProvider;

            this.Parameters.UserAgent = $"{this.NodeSettings.Agent}:{versionProvider.GetVersion()}";

            this.Parameters.Version = this.NodeSettings.ProtocolVersion;

            this.downloads = new Dictionary <INetworkPeer, PerformanceSnapshot>();
        }
Пример #5
0
        public override async Task InitializeAsync()
        {
            // Set up our database of deposit and withdrawal transactions. Needs to happen before everything else.
            this.crossChainTransferStore.Initialize();

            // Load the federation wallet that will be used to generate transactions.
            this.federationWalletManager.Start();

            // Query the other chain every N seconds for deposits. Triggers signing process if deposits are found.
            this.maturedBlocksSyncManager.Start();

            // Syncs the wallet correctly when restarting the node. i.e. deals with reorgs.
            this.walletSyncManager.Initialize();

            // Synchronises the wallet and the transfer store.
            this.crossChainTransferStore.Start();

            // Query our database for partially-signed transactions and send them around to be signed every N seconds.
            this.partialTransactionRequester.Start();

            // Query our database for fully-signed transactions and broadcast them every N seconds.
            this.signedBroadcaster.Start();

            // Check that the feature is configured correctly before going any further.
            this.CheckConfiguration();

            // Connect the node to the other federation members.
            foreach (IPEndPoint federationMemberIp in this.federatedPegSettings.FederationNodeIpEndPoints)
            {
                this.connectionManager.AddNodeAddress(federationMemberIp, true);
            }

            // Respond to requests to sign transactions from other nodes.
            NetworkPeerConnectionParameters networkPeerConnectionParameters = this.connectionManager.Parameters;

            networkPeerConnectionParameters.TemplateBehaviors.Add(new PartialTransactionsBehavior(this.loggerFactory, this.federationWalletManager,
                                                                                                  this.network, this.federatedPegSettings, this.crossChainTransferStore, this.inputConsolidator));
        }
Пример #6
0
        /// <summary>Constructor used by <see cref="Connection.ConnectionManager"/>.</summary>
        protected PeerConnector(
            IAsyncLoopFactory asyncLoopFactory,
            ILogger logger,
            Network network,
            INetworkPeerFactory networkPeerFactory,
            INodeLifetime nodeLifeTime,
            NodeSettings nodeSettings,
            NetworkPeerConnectionParameters parameters,
            IPeerAddressManager peerAddressManager)
        {
            this.asyncLoopFactory   = asyncLoopFactory;
            this.ConnectedPeers     = new NetworkPeerCollection();
            this.network            = network;
            this.networkPeerFactory = networkPeerFactory;
            this.nodeLifetime       = nodeLifeTime;
            this.NodeSettings       = nodeSettings;
            this.parentParameters   = parameters;
            this.peerAddressManager = peerAddressManager;

            this.CurrentParameters = this.parentParameters.Clone();
            this.CurrentParameters.TemplateBehaviors.Add(new PeerConnectorBehaviour(this));
            this.CurrentParameters.ConnectCancellation = this.nodeLifetime.ApplicationStopping;
        }
Пример #7
0
        public void RequestPeerServices_PeersThatDontSupportNewServicesAreRemoved()
        {
            Mock <INetworkPeer> peer1 = this.helper.CreatePeerMock(out ExtendedBlockPullerBehavior behavior1);
            Mock <INetworkPeer> peer2 = this.helper.CreatePeerMock(out ExtendedBlockPullerBehavior behavior2);

            List <ChainedHeader> headers = ChainedHeadersHelper.CreateConsecutiveHeaders(5);

            this.puller.NewPeerTipClaimed(peer1.Object, headers.Last());
            this.puller.NewPeerTipClaimed(peer2.Object, headers.Last());

            Assert.Equal(2, this.puller.PullerBehaviorsByPeerId.Count);

            VersionPayload version = new NetworkPeerConnectionParameters().CreateVersion(new IPEndPoint(1, 1), new IPEndPoint(1, 1),
                                                                                         KnownNetworks.StratisMain, new DateTimeProvider().GetTimeOffset());

            version.Services = NetworkPeerServices.Network | NetworkPeerServices.NODE_WITNESS;

            peer1.SetupGet(x => x.PeerVersion).Returns(version);

            this.puller.RequestPeerServices(NetworkPeerServices.NODE_WITNESS);

            Assert.Equal(1, this.puller.PullerBehaviorsByPeerId.Count);
        }
        /// <summary>Creates a peer with extended puller behavior.</summary>
        public Mock <INetworkPeer> CreatePeerMock(out ExtendedBlockPullerBehavior mockedBehavior, bool notSupportedVersion = false)
        {
            var peer = new Mock <INetworkPeer>();

            var signals       = new Blockcore.Signals.Signals(this.loggerFactory, null);
            var asyncProvider = new AsyncProvider(this.loggerFactory, signals, new NodeLifetime());

            var connection = new NetworkPeerConnection(KnownNetworks.StratisMain, peer.Object, new TcpClient(), this.currentPeerId, (message, token) => Task.CompletedTask,
                                                       new DateTimeProvider(), this.loggerFactory, new PayloadProvider(), asyncProvider);

            this.currentPeerId++;
            peer.SetupGet(networkPeer => networkPeer.Connection).Returns(connection);

            var            connectionParameters = new NetworkPeerConnectionParameters();
            VersionPayload version = connectionParameters.CreateVersion(new IPEndPoint(1, 1), new IPEndPoint(1, 1), KnownNetworks.StratisMain, new DateTimeProvider().GetTimeOffset());

            if (notSupportedVersion)
            {
                version.Version = ProtocolVersion.MIN_PEER_PROTO_VERSION;
            }
            else
            {
                version.Services = NetworkPeerServices.Network;
            }

            peer.SetupGet(x => x.PeerVersion).Returns(version);
            peer.SetupGet(x => x.State).Returns(NetworkPeerState.HandShaked);
            peer.SetupGet(x => x.MessageReceived).Returns(new AsyncExecutionEvent <INetworkPeer, IncomingMessage>());

            ExtendedBlockPullerBehavior behavior = this.CreateBlockPullerBehavior();

            behavior.Attach(peer.Object);
            peer.Setup(x => x.Behavior <IBlockPullerBehavior>()).Returns(() => behavior);

            mockedBehavior = behavior;
            return(peer);
        }
        private Mock <INetworkPeer> CreatePeerMock()
        {
            var peer = new Mock <INetworkPeer>();

            var signals       = new Bitcoin.Signals.Signals(this.loggerFactory, null);
            var asyncProvider = new AsyncProvider(this.loggerFactory, signals, new NodeLifetime());

            var connection = new NetworkPeerConnection(KnownNetworks.StraxMain, peer.Object, new TcpClient(), 0, (message, token) => Task.CompletedTask,
                                                       new DateTimeProvider(), this.loggerFactory, new PayloadProvider(), asyncProvider);

            peer.SetupGet(networkPeer => networkPeer.Connection).Returns(connection);

            var            connectionParameters = new NetworkPeerConnectionParameters();
            VersionPayload version = connectionParameters.CreateVersion(new IPEndPoint(1, 1), new IPEndPoint(1, 1), KnownNetworks.StraxMain, new DateTimeProvider().GetTimeOffset());

            version.Services = NetworkPeerServices.Network;

            peer.SetupGet(x => x.PeerVersion).Returns(version);
            peer.SetupGet(x => x.State).Returns(NetworkPeerState.HandShaked);

            this.StateChanged    = new AsyncExecutionEvent <INetworkPeer, NetworkPeerState>();
            this.MessageReceived = new AsyncExecutionEvent <INetworkPeer, IncomingMessage>();

            peer.Setup(x => x.StateChanged).Returns(() => this.StateChanged);
            peer.Setup(x => x.MessageReceived).Returns(() => this.MessageReceived);

            var connectionManagerBehaviorMock = new Mock <IConnectionManagerBehavior>();

            connectionManagerBehaviorMock.Setup(x => x.Whitelisted).Returns(this.IsPeerWhitelisted);

            peer.Setup(x => x.Behavior <IConnectionManagerBehavior>()).Returns(() => connectionManagerBehaviorMock.Object);

            peer.SetupGet(x => x.PeerEndPoint).Returns(new IPEndPoint(1, 1));

            return(peer);
        }
Пример #10
0
        /// <inheritdoc />
        public override Task InitializeAsync()
        {
            NetworkPeerConnectionParameters connectionParameters = this.connectionManager.Parameters;

            var defaultConsensusManagerBehavior = connectionParameters.TemplateBehaviors.FirstOrDefault(behavior => behavior is ConsensusManagerBehavior);

            if (defaultConsensusManagerBehavior == null)
            {
                throw new MissingServiceException(typeof(ConsensusManagerBehavior), "Missing expected ConsensusManagerBehavior.");
            }

            // Replace default ConsensusManagerBehavior with ProvenHeadersConsensusManagerBehavior
            // Temporary disabled in impleum until soft fork is done
            if (this.network.IsImpleum())
            {
                return(Task.CompletedTask);
            }
            connectionParameters.TemplateBehaviors.Remove(defaultConsensusManagerBehavior);
            connectionParameters.TemplateBehaviors.Add(new ProvenHeadersConsensusManagerBehavior(this.chainIndexer, this.initialBlockDownloadState, this.consensusManager, this.peerBanning, this.loggerFactory, this.network, this.chainState, this.checkpoints, this.provenBlockHeaderStore, this.connectionManagerSettings));

            connectionParameters.TemplateBehaviors.Add(new ProvenHeadersReservedSlotsBehavior(this.connectionManager, this.loggerFactory));

            return(Task.CompletedTask);
        }
        private IPeerConnector CreatePeerConnector(
            NetworkPeerConnectionParameters parameters,
            NetworkPeerServices requiredServices,
            Func <IPEndPoint, byte[]> peerSelector,
            PeerIntroductionType peerIntroductionType,
            int?maximumNodeConnections = 8)
        {
            this.logger.LogTrace("({0}:{1})", nameof(requiredServices), requiredServices);

            var nodeRequirement = new NetworkPeerRequirement
            {
                MinVersion       = this.NodeSettings.ProtocolVersion,
                RequiredServices = requiredServices,
            };

            var peerConnector = new PeerConnector(this.Network, this.nodeLifetime, parameters, nodeRequirement, peerSelector, this.asyncLoopFactory, this.peerAddressManager, peerIntroductionType, this.networkPeerFactory)
            {
                MaximumNodeConnections = maximumNodeConnections.Value
            };

            this.logger.LogTrace("(-)");

            return(peerConnector);
        }
        public override Task InitializeAsync()
        {
            // Subscribe to receiving blocks and transactions.
            this.blockSubscriberDisposable = this.signals.SubscribeForBlocksConnected(
                new BlockObserver(
                    this.walletSyncManager,
                    this.depositExtractor,
                    this.withdrawalExtractor,
                    this.withdrawalReceiver,
                    this.maturedBlockSender,
                    this.maturedBlocksProvider,
                    this.blockTipSender));

            this.transactionSubscriberDisposable = this.signals.SubscribeForTransactions(new TransactionObserver(this.walletSyncManager));

            this.crossChainTransferStore.Initialize();

            this.federationWalletManager.Start();
            this.walletSyncManager.Start();
            this.crossChainTransferStore.Start();
            this.partialTransactionRequester.Start();
            this.maturedBlockRequester.Start();

            // Connect the node to the other federation members.
            foreach (IPEndPoint federationMemberIp in this.federationGatewaySettings.FederationNodeIpEndPoints)
            {
                this.connectionManager.AddNodeAddress(federationMemberIp);
            }

            NetworkPeerConnectionParameters networkPeerConnectionParameters = this.connectionManager.Parameters;

            networkPeerConnectionParameters.TemplateBehaviors.Add(new PartialTransactionsBehavior(this.loggerFactory, this.federationWalletManager,
                                                                                                  this.network, this.federationGatewaySettings, this.crossChainTransferStore));

            return(Task.CompletedTask);
        }
        public void PeerConnectorDiscovery_ConnectsTo_NodeInSameNetworkGroup_WithIpRangeFilteringDisabled()
        {
            // IpRangeFiltering enabled by default, disabled explicitly.
            var nodeSettings = new NodeSettings(this.Network, args: new[] { "-IpRangeFiltering=false" });

            var connectionManagerSettingsExisting = new ConnectionManagerSettings(nodeSettings);

            DataFolder peerFolder         = CreateDataFolder(this);
            var        peerAddressManager = new PeerAddressManager(DateTimeProvider.Default, peerFolder, this.extendedLoggerFactory,
                                                                   new SelfEndpointTracker(this.extendedLoggerFactory, connectionManagerSettingsExisting));

            Mock <INetworkPeerFactory> networkPeerFactoryExisting = new Mock <INetworkPeerFactory>();

            Mock <IConnectionManager> connectionManagerExisting = new Mock <IConnectionManager>();

            var networkPeerParameters = new NetworkPeerConnectionParameters();

            networkPeerParameters.TemplateBehaviors.Add(new ConnectionManagerBehavior(connectionManagerExisting.Object, this.extendedLoggerFactory));

            connectionManagerExisting.SetupGet(np => np.Parameters).Returns(networkPeerParameters);
            connectionManagerExisting.SetupGet(np => np.ConnectedPeers).Returns(new NetworkPeerCollection());

            var peerConnector = new PeerConnectorDiscovery(this.asyncProvider, DateTimeProvider.Default, this.extendedLoggerFactory, this.Network, networkPeerFactoryExisting.Object, this.nodeLifetime, nodeSettings, connectionManagerSettingsExisting, peerAddressManager,
                                                           new SelfEndpointTracker(this.extendedLoggerFactory, connectionManagerSettingsExisting));

            peerConnector.Initialize(connectionManagerExisting.Object);

            //Peer 1.
            IPAddress originalAddressPeer1 = IPAddress.Parse("::ffff:57.48.183.81"); // ipv4
            var       endpointPeer1        = new IPEndPoint(originalAddressPeer1, 80);

            peerAddressManager.AddPeer(endpointPeer1, IPAddress.Loopback);
            bool connectedToThisPeer = ConnectToPeer(peerAddressManager, networkPeerFactoryExisting, connectionManagerSettingsExisting, peerConnector, endpointPeer1, connectionManagerExisting);

            Assert.True(connectedToThisPeer);

            // Peer 2 has different network group to Peer 1.
            IPAddress addressInDifferentNetworkGroupPeer2 = IPAddress.Parse("99be:f5c5:adc2:525c:f6d7:7b30:5336:5a0f"); // ipv6
            var       endpointPeer2 = new IPEndPoint(addressInDifferentNetworkGroupPeer2, 80);

            peerAddressManager.AddPeer(endpointPeer2, IPAddress.Loopback);
            connectedToThisPeer = ConnectToPeer(peerAddressManager, networkPeerFactoryExisting, connectionManagerSettingsExisting, peerConnector, endpointPeer2, connectionManagerExisting);
            Assert.True(connectedToThisPeer); // Different network group: connects.

            // Peer 3 in same network group as Peer 2.
            IPAddress addressInSameNetworkGroupPeer3 = IPAddress.Parse("99be:f5c5:adc2:525c:db45:d36e:ce01:a394"); // ipv6
            var       endpointPeer3 = new IPEndPoint(addressInSameNetworkGroupPeer3, 80);

            peerAddressManager.AddPeer(endpointPeer3, IPAddress.Loopback);
            connectedToThisPeer = ConnectToPeer(peerAddressManager, networkPeerFactoryExisting, connectionManagerSettingsExisting, peerConnector, endpointPeer3, connectionManagerExisting);
            Assert.True(connectedToThisPeer); // Same network group: connects.

            // Peer 4 has different network group to Peer 1.
            IPAddress addressInDifferentNetworkGroupPeer4 = IPAddress.Parse("::ffff:58.48.183.81"); // ipv4
            var       endpointPeer4 = new IPEndPoint(addressInDifferentNetworkGroupPeer4, 80);

            peerAddressManager.AddPeer(endpointPeer4, IPAddress.Loopback);
            connectedToThisPeer = ConnectToPeer(peerAddressManager, networkPeerFactoryExisting, connectionManagerSettingsExisting, peerConnector, endpointPeer4, connectionManagerExisting);
            Assert.True(connectedToThisPeer); // Different network group: connects.

            // Peer 5 has same network group as Peer 1.
            IPAddress addressInSameNetworkGroupPeer5 = IPAddress.Parse("::ffff:57.48.183.82"); // ipv4
            var       endpointPeer5 = new IPEndPoint(addressInSameNetworkGroupPeer5, 80);

            peerAddressManager.AddPeer(endpointPeer5, IPAddress.Loopback);
            connectedToThisPeer = ConnectToPeer(peerAddressManager, networkPeerFactoryExisting, connectionManagerSettingsExisting, peerConnector, endpointPeer5, connectionManagerExisting);
            Assert.True(connectedToThisPeer); // Same network group: connects.
        }
Пример #14
0
        /// <summary>Attempts to connect to a random peer.</summary>
        public async Task ConnectAsync(PeerAddress peerAddress)
        {
            if (this.selfEndpointTracker.IsSelf(peerAddress.Endpoint))
            {
                this.logger.LogDebug("Connect aborted: {0} is self.", peerAddress.Endpoint);
                return;
            }

            if (this.IsPeerConnected(peerAddress.Endpoint))
            {
                this.logger.LogDebug("Connect aborted: {0} is already connected.", peerAddress.Endpoint);
                return;
            }

            if (peerAddress.IsBanned(this.dateTimeProvider.GetUtcNow()))
            {
                this.logger.LogDebug("Connect aborted: {0} is banned until {1}.", peerAddress.Endpoint, peerAddress.BanUntil);
                return;
            }

            INetworkPeer peer = null;

            try
            {
                using (CancellationTokenSource timeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(this.NodeLifetime.ApplicationStopping))
                {
                    this.PeerAddressManager.PeerAttempted(peerAddress.Endpoint, this.dateTimeProvider.GetUtcNow());

                    NetworkPeerConnectionParameters clonedConnectParameters = this.CurrentParameters.Clone();
                    timeoutTokenSource.CancelAfter(5000);
                    clonedConnectParameters.ConnectCancellation = timeoutTokenSource.Token;

                    peer = await this.networkPeerFactory.CreateConnectedNetworkPeerAsync(peerAddress.Endpoint, clonedConnectParameters, this.networkPeerDisposer).ConfigureAwait(false);

                    await peer.VersionHandshakeAsync(this.Requirements, timeoutTokenSource.Token).ConfigureAwait(false);

                    this.AddPeer(peer);
                }
            }
            catch (OperationCanceledException)
            {
                if (this.NodeLifetime.ApplicationStopping.IsCancellationRequested)
                {
                    this.logger.LogDebug("Peer {0} connection canceled because application is stopping.", peerAddress.Endpoint);
                    peer?.Disconnect("Application stopping");
                }
                else
                {
                    this.logger.LogDebug("Peer {0} connection timeout.", peerAddress.Endpoint);
                    peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                    peer?.Disconnect("Connection timeout");
                }
            }
            catch (NBitcoin.Protocol.ProtocolException)
            {
                this.logger.LogDebug("Handshake rejected by peer '{0}'.", peerAddress.Endpoint);
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while handshaking");
            }
            catch (Exception exception)
            {
                this.logger.LogDebug("Exception occurred while connecting: {0}", exception is SocketException ? exception.Message : exception.ToString());
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while connecting", exception);
            }
        }
Пример #15
0
        /// <inheritdoc />
        public override async Task InitializeAsync()
        {
            // TODO rewrite chain starting logic. Tips manager should be used.

            await this.StartChainAsync().ConfigureAwait(false);

            if (this.provenBlockHeaderStore != null)
            {
                // If we find at this point that proven header store is behind chain we can rewind chain (this will cause a ripple effect and rewind block store and consensus)
                // This problem should go away once we implement a component to keep all tips up to date
                // https://github.com/stratisproject/StratisBitcoinFullNode/issues/2503
                ChainedHeader initializedAt = await this.provenBlockHeaderStore.InitializeAsync(this.chainIndexer.Tip);

                this.chainIndexer.Initialize(initializedAt);
            }

            NetworkPeerConnectionParameters connectionParameters = this.connectionManager.Parameters;

            connectionParameters.IsRelay = this.connectionManager.ConnectionSettings.RelayTxes;

            connectionParameters.TemplateBehaviors.Add(new PingPongBehavior());
            connectionParameters.TemplateBehaviors.Add(new EnforcePeerVersionCheckBehavior(this.chainIndexer, this.nodeSettings, this.network, this.loggerFactory));
            connectionParameters.TemplateBehaviors.Add(new ConsensusManagerBehavior(this.chainIndexer, this.initialBlockDownloadState, this.consensusManager, this.peerBanning, this.loggerFactory));

            // TODO: Once a proper rate limiting strategy has been implemented, this check will be removed.
            if (!this.network.IsRegTest())
            {
                connectionParameters.TemplateBehaviors.Add(new RateLimitingBehavior(this.dateTimeProvider, this.loggerFactory, this.peerBanning));
            }

            connectionParameters.TemplateBehaviors.Add(new PeerBanningBehavior(this.loggerFactory, this.peerBanning, this.nodeSettings));
            connectionParameters.TemplateBehaviors.Add(new BlockPullerBehavior(this.blockPuller, this.initialBlockDownloadState, this.dateTimeProvider, this.loggerFactory));
            connectionParameters.TemplateBehaviors.Add(new ConnectionManagerBehavior(this.connectionManager, this.loggerFactory));

            this.StartAddressManager(connectionParameters);

            if (this.connectionManager.ConnectionSettings.SyncTimeEnabled)
            {
                connectionParameters.TemplateBehaviors.Add(new TimeSyncBehavior(this.timeSyncBehaviorState, this.dateTimeProvider, this.loggerFactory));
            }
            else
            {
                this.logger.LogDebug("Time synchronization with peers is disabled.");
            }

            // Block store must be initialized before consensus manager.
            // This may be a temporary solution until a better way is found to solve this dependency.
            this.blockStore.Initialize();

            // The finalized repository needs to be initialized before the rules engine in case the
            // node shutdown unexpectedly and the finalized block info needs to be reset.
            this.finalizedBlockInfoRepository.Initialize(this.chainIndexer.Tip);

            this.consensusRules.Initialize(this.chainIndexer.Tip);

            await this.consensusManager.InitializeAsync(this.chainIndexer.Tip).ConfigureAwait(false);

            this.chainState.ConsensusTip = this.consensusManager.Tip;

            this.nodeStats.RegisterStats(sb => sb.Append(this.asyncProvider.GetStatistics(!this.nodeSettings.LogSettings.DebugArgs.Any())), StatsType.Component, this.GetType().Name, 100);

            // TODO: Should this always be called?
            ((IBlockStoreQueue)this.blockStore).ReindexChain(this.consensusManager, this.nodeLifetime.ApplicationStopping);
        }
Пример #16
0
 public static BroadcastHub GetBroadcastHub(NetworkPeerConnectionParameters parameters)
 {
     return(GetBroadcastHub(parameters.TemplateBehaviors));
 }
Пример #17
0
 public NetworkPeer CreateNodeClient(NetworkPeerConnectionParameters parameters)
 {
     return(this.networkPeerFactory.CreateConnectedNetworkPeerAsync(Network.RegTest, "127.0.0.1:" + this.ports[0].ToString(), parameters).GetAwaiter().GetResult());
 }
Пример #18
0
        /// <summary>Attempts to connect to a random peer.</summary>
        internal async Task ConnectAsync(PeerAddress peerAddress)
        {
            if (this.selfEndpointTracker.IsSelf(peerAddress.Endpoint))
            {
                this.logger.LogTrace("{0} is self. Therefore not connecting.", peerAddress.Endpoint);
                return;
            }

            // Connect if local, ip range filtering disabled or ip range filtering enabled and peer in a different group.
            if (peerAddress.Endpoint.Address.IsRoutable(false) && this.ConnectionSettings.IpRangeFiltering && this.PeerIsPartOfExistingGroup(peerAddress))
            {
                this.logger.LogTrace("(-)[RANGE_FILTERED]");
                return;
            }

            INetworkPeer peer = null;

            try
            {
                using (CancellationTokenSource timeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(this.nodeLifetime.ApplicationStopping))
                {
                    this.peerAddressManager.PeerAttempted(peerAddress.Endpoint, this.dateTimeProvider.GetUtcNow());

                    NetworkPeerConnectionParameters clonedConnectParamaters = this.CurrentParameters.Clone();
                    timeoutTokenSource.CancelAfter(5000);
                    clonedConnectParamaters.ConnectCancellation = timeoutTokenSource.Token;

                    peer = await this.networkPeerFactory.CreateConnectedNetworkPeerAsync(peerAddress.Endpoint, clonedConnectParamaters, this.networkPeerDisposer).ConfigureAwait(false);

                    await peer.VersionHandshakeAsync(this.Requirements, timeoutTokenSource.Token).ConfigureAwait(false);

                    this.AddPeer(peer);
                }
            }
            catch (OperationCanceledException)
            {
                if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
                {
                    this.logger.LogDebug("Peer {0} connection canceled because application is stopping.", peerAddress.Endpoint);
                    peer?.Disconnect("Application stopping");
                }
                else
                {
                    this.logger.LogDebug("Peer {0} connection timeout.", peerAddress.Endpoint);
                    peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                    peer?.Disconnect("Connection timeout");
                }
            }
            catch (NBitcoin.Protocol.ProtocolException)
            {
                this.logger.LogDebug("Handshake rejected by peer '{0}'.", peerAddress.Endpoint);
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while handshaking");
            }
            catch (Exception exception)
            {
                this.logger.LogTrace("Exception occurred while connecting: {0}", exception.ToString());
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while connecting", exception);
            }
        }
Пример #19
0
        /// <summary>
        /// See <see cref="DiscoverPeers"/>
        /// </summary>
        private async Task DiscoverPeersAsync()
        {
            var peersToDiscover           = new List <IPEndPoint>();
            List <PeerAddress> foundPeers = this.peerAddressManager.PeerSelector.SelectPeersForDiscovery(1000).ToList();

            peersToDiscover.AddRange(foundPeers.Select(p => p.Endpoint));

            if (peersToDiscover.Count == 0)
            {
                // On normal circumstances the dns seeds are attempted only once per node lifetime.
                if (this.isSeedAndDnsAttempted)
                {
                    this.logger.LogTrace("(-)[DNS_ATTEMPTED]");
                    return;
                }

                this.AddDNSSeedNodes(peersToDiscover);
                this.AddSeedNodes(peersToDiscover);
                this.isSeedAndDnsAttempted = true;

                if (peersToDiscover.Count == 0)
                {
                    this.logger.LogTrace("(-)[NO_ADDRESSES]");
                    return;
                }

                peersToDiscover = peersToDiscover.OrderBy(a => RandomUtils.GetInt32()).ToList();
            }
            else
            {
                // If all attempts have failed then attempt the dns seeds again.
                if (!this.isSeedAndDnsAttempted && foundPeers.All(peer => peer.Attempted))
                {
                    peersToDiscover.Clear();
                    this.AddDNSSeedNodes(peersToDiscover);
                    this.AddSeedNodes(peersToDiscover);
                    this.isSeedAndDnsAttempted = true;
                }
            }

            await peersToDiscover.ForEachAsync(5, this.nodeLifetime.ApplicationStopping, async (endPoint, cancellation) =>
            {
                using (CancellationTokenSource connectTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellation))
                {
                    this.logger.LogTrace("Attempting to discover from : '{0}'", endPoint);

                    connectTokenSource.CancelAfter(TimeSpan.FromSeconds(5));

                    INetworkPeer networkPeer = null;

                    try
                    {
                        NetworkPeerConnectionParameters clonedParameters = this.currentParameters.Clone();
                        clonedParameters.ConnectCancellation             = connectTokenSource.Token;

                        PeerAddressManagerBehaviour addressManagerBehaviour = clonedParameters.TemplateBehaviors.OfType <PeerAddressManagerBehaviour>().FirstOrDefault();
                        clonedParameters.TemplateBehaviors.Clear();
                        clonedParameters.TemplateBehaviors.Add(addressManagerBehaviour);

                        networkPeer = await this.networkPeerFactory.CreateConnectedNetworkPeerAsync(endPoint, clonedParameters).ConfigureAwait(false);
                        await networkPeer.VersionHandshakeAsync(connectTokenSource.Token).ConfigureAwait(false);
                        await networkPeer.SendMessageAsync(new GetAddrPayload(), connectTokenSource.Token).ConfigureAwait(false);

                        this.peerAddressManager.PeerDiscoveredFrom(endPoint, DateTimeProvider.Default.GetUtcNow());

                        connectTokenSource.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(5));
                    }
                    catch
                    {
                    }
                    finally
                    {
                        networkPeer?.Disconnect("Discovery job done");
                        networkPeer?.Dispose();
                    }

                    this.logger.LogTrace("Discovery from '{0}' finished", endPoint);
                }
            }).ConfigureAwait(false);
        }
 public static PeerAddressManagerBehaviour PeerAddressManagerBehaviour(
     this NetworkPeerConnectionParameters parameters)
 {
     return(parameters.TemplateBehaviors.OfType <PeerAddressManagerBehaviour>().FirstOrDefault());
 }
Пример #21
0
 public static PeerAddressManagerBehaviour PeerAddressManagerBehaviour(this NetworkPeerConnectionParameters parameters)
 {
     return(parameters.TemplateBehaviors.Find <PeerAddressManagerBehaviour>());
 }
        public void CanDiscoverAndConnectToPeersOnTheNetwork()
        {
            var parameters = new NetworkPeerConnectionParameters();

            var testFolder = TestDirectory.Create("CanDiscoverAndConnectToPeersOnTheNetwork");

            var nodeSettings = new NodeSettings
            {
                DataDir = testFolder.FolderName
            };

            nodeSettings.DataFolder = new DataFolder(nodeSettings);

            var peerAddressManager          = new PeerAddressManager(nodeSettings.DataFolder);
            var peerAddressManagerBehaviour = new PeerAddressManagerBehaviour(new DateTimeProvider(), peerAddressManager)
            {
                PeersToDiscover = 3
            };

            parameters.TemplateBehaviors.Add(peerAddressManagerBehaviour);

            var loggerFactory = new ExtendedLoggerFactory();

            loggerFactory.AddConsoleWithFilters();

            var networkPeerFactory = new NetworkPeerFactory(DateTimeProvider.Default, loggerFactory);

            var peerConnectorDiscovery = new PeerConnectorDiscovery(
                new AsyncLoopFactory(loggerFactory),
                loggerFactory,
                Network.Main,
                networkPeerFactory,
                new NodeLifetime(),
                nodeSettings,
                peerAddressManager);

            var peerDiscovery = new PeerDiscovery(
                new AsyncLoopFactory(loggerFactory),
                loggerFactory,
                Network.Main,
                networkPeerFactory,
                new NodeLifetime(),
                nodeSettings,
                peerAddressManager);

            IConnectionManager connectionManager = new ConnectionManager(
                new AsyncLoopFactory(loggerFactory),
                new DateTimeProvider(),
                loggerFactory,
                Network.Main,
                networkPeerFactory,
                nodeSettings,
                new NodeLifetime(),
                parameters,
                peerAddressManager,
                new IPeerConnector[] { peerConnectorDiscovery },
                peerDiscovery);

            NetworkPeerConnectionParameters cloned = parameters.Clone();

            cloned.TemplateBehaviors.Add(new ConnectionManagerBehavior(false, connectionManager, loggerFactory));

            peerDiscovery.DiscoverPeers(cloned);

            // Wait until we have discovered 3 peers.
            TestHelper.WaitLoop(() => peerAddressManager.Peers.Count > 3);

            // Wait until at least one successful connection has been made.
            while (true)
            {
                try
                {
                    var         peerOne = peerAddressManager.SelectPeerToConnectTo();
                    NetworkPeer node    = networkPeerFactory.CreateConnectedNetworkPeer(Network.Main, peerOne, parameters);
                    node.VersionHandshake();
                    node.Disconnect();

                    break;
                }
                catch
                {
                }
            }
            ;
        }