/// <summary>
        /// Checks a version payload from a peer against the requirements.
        /// </summary>
        /// <param name="version">Version payload to check.</param>
        /// <returns><c>true</c> if the version payload satisfies the protocol requirements, <c>false</c> otherwise.</returns>
        public virtual bool Check(VersionPayload version)
        {
            if (this.MinVersion != null)
            {
                if (version.Version < this.MinVersion.Value)
                {
                    return(false);
                }
            }

            if ((this.RequiredServices & version.Services) != this.RequiredServices)
            {
                return(false);
            }

            if (this.SupportSPV)
            {
                if (version.Version < ProtocolVersion.MEMPOOL_GD_VERSION)
                {
                    return(false);
                }

                if ((ProtocolVersion.NO_BLOOM_VERSION <= version.Version) && ((version.Services & NetworkPeerServices.NODE_BLOOM) == 0))
                {
                    return(false);
                }
            }

            return(true);
        }
示例#2
0
        /// <summary>
        /// Processes a "version" message received from a peer.
        /// </summary>
        /// <param name="version">Version message received from a peer.</param>
        /// <param name="cancellation">Cancellation token to abort message processing.</param>
        private async Task ProcessVersionMessageAsync(VersionPayload version, CancellationToken cancellation)
        {
            this.logger.LogTrace("Peer's state is {0}.", this.State);

            switch (this.State)
            {
            case NetworkPeerState.Connected:
                if (this.Inbound)
                {
                    await this.ProcessInitialVersionPayloadAsync(version, cancellation).ConfigureAwait(false);
                }

                break;

            case NetworkPeerState.HandShaked:
                if (this.Version >= ProtocolVersion.REJECT_VERSION)
                {
                    var rejectPayload = new RejectPayload()
                    {
                        Code = RejectCode.DUPLICATE
                    };

                    await this.SendMessageAsync(rejectPayload, cancellation).ConfigureAwait(false);
                }

                break;
            }

            this.TimeOffset = this.dateTimeProvider.GetTimeOffset() - version.Timestamp;
            if ((version.Services & NetworkPeerServices.NODE_WITNESS) != 0)
            {
                this.SupportedTransactionOptions |= TransactionOptions.Witness;
            }
        }
示例#3
0
 private void OnVersionMessageReceived(VersionPayload payload)
 {
     version = payload;
     Context.Parent.Tell(new SetVersion {
         Version = payload
     });
 }
示例#4
0
        public async Task Can_activate_peer_on_verack_receiving()
        {
            // Arrange
            var blockchain = new NullBlockchain();

            AutoMockContainer.Register <IBlockchain>(blockchain);

            var verAckMessage = new VerAckMessage();
            var version       = new VersionPayload();
            var peerMock      = AutoMockContainer.GetMock <IPeer>();

            peerMock.SetupProperty(x => x.IsReady, false);
            peerMock.SetupProperty(x => x.Version, version);

            blockchain.LastBlockHeader.Index = 1;
            version.CurrentBlockIndex        = 1;

            var messageHandler = AutoMockContainer.Get <VerAckMessageHandler>();

            // Act
            await messageHandler.Handle(verAckMessage, peerMock.Object);

            // Assert
            peerMock.Object.IsReady.Should().BeTrue();
        }
示例#5
0
        public void RemoteNode_Test_Accept_IfSameMagic()
        {
            var connectionTestProbe = CreateTestProbe();
            var remoteNodeActor     = ActorOfAsTestActorRef(() => new RemoteNode(testBlockchain, connectionTestProbe, null, null));

            connectionTestProbe.ExpectMsg <Tcp.Write>();

            var payload = new VersionPayload()
            {
                UserAgent    = "Unit Test".PadLeft(1024, '0'),
                Nonce        = 1,
                Magic        = ProtocolSettings.Default.Magic,
                Timestamp    = 5,
                Version      = 6,
                Capabilities = new NodeCapability[]
                {
                    new ServerCapability(NodeCapabilityType.TcpServer, 25)
                }
            };

            var testProbe = CreateTestProbe();

            testProbe.Send(remoteNodeActor, payload);

            var verackMessage = connectionTestProbe.ExpectMsg <Tcp.Write>();

            //Verack
            verackMessage.Data.Count.Should().Be(3);
        }
        public RemoteNode(LyraSystem system, object connection, IPEndPoint remote, IPEndPoint local)
            : base(connection, remote, local)
        {
            _log = new SimpleLogger("RemoteNode").Logger;

            this.system   = system;
            this.protocol = Context.ActorOf(ProtocolHandler.Props(system));
            LocalNode.Singleton.RemoteNodes.TryAdd(Self, this);

            while (BlockChain.Singleton == null)
            {
                Task.Delay(100).Wait();
            }

            var capabilities = new List <NodeCapability>
            {
                new FullNodeCapability(BlockChain.Singleton.Height)
            };

            if (LocalNode.Singleton.ListenerTcpPort > 0)
            {
                capabilities.Add(new ServerCapability(NodeCapabilityType.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort));
            }
            if (LocalNode.Singleton.ListenerWsPort > 0)
            {
                capabilities.Add(new ServerCapability(NodeCapabilityType.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort));
            }

            SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, capabilities.ToArray())));
        }
示例#7
0
        private void OnVersionPayload(VersionPayload version)
        {
            Version = version;
            foreach (NodeCapability capability in version.Capabilities)
            {
                switch (capability)
                {
                case FullNodeCapability fullNodeCapability:
                    IsFullNode     = true;
                    LastBlockIndex = fullNodeCapability.StartHeight;
                    break;

                case ServerCapability serverCapability:
                    if (serverCapability.Type == NodeCapabilityType.TcpServer)
                    {
                        ListenerTcpPort = serverCapability.Port;
                    }
                    break;
                }
            }
            if (version.Nonce == LocalNode.Nonce || version.Magic != ProtocolSettings.Default.Magic)
            {
                Disconnect(true);
                return;
            }
            if (LocalNode.Singleton.RemoteNodes.Values.Where(p => p != this).Any(p => p.Remote.Address.Equals(Remote.Address) && p.Version?.Nonce == version.Nonce))
            {
                Disconnect(true);
                return;
            }
            SendMessage(Message.Create(MessageCommand.Verack));
        }
示例#8
0
        public void RemoteNode_Test_Abort_DifferentMagic()
        {
            var connectionTestProbe = CreateTestProbe();
            var remoteNodeActor     = ActorOfAsTestActorRef(() => new RemoteNode(testBlockchain, connectionTestProbe, null, null));

            connectionTestProbe.ExpectMsg <Tcp.Write>();

            var payload = new VersionPayload()
            {
                UserAgent    = "".PadLeft(1024, '0'),
                Nonce        = 1,
                Magic        = 2,
                Timestamp    = 5,
                Version      = 6,
                Capabilities = new NodeCapability[]
                {
                    new ServerCapability(NodeCapabilityType.TcpServer, 25)
                }
            };

            var testProbe = CreateTestProbe();

            testProbe.Send(remoteNodeActor, payload);

            connectionTestProbe.ExpectMsg <Tcp.Abort>();
        }
        /// <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 connection = new NetworkPeerConnection(KnownNetworks.StratisMain, peer.Object, new TcpClient(), this.currentPeerId, (message, token) => Task.CompletedTask,
                                                       new DateTimeProvider(), this.loggerFactory, new PayloadProvider());

            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.NOBLKS_VERSION_START;
            }
            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);
        }
示例#10
0
        private Mock <INetworkPeer> CreatePeerMock()
        {
            var peer = new Mock <INetworkPeer>();

            var connection = new NetworkPeerConnection(this.Network, peer.Object, new TcpClient(), 0, (message, token) => Task.CompletedTask, DateTimeProvider.Default, this.extendedLoggerFactory, new PayloadProvider(), this.asyncProvider);

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

            var            connectionParameters = new NetworkPeerConnectionParameters();
            VersionPayload version = connectionParameters.CreateVersion(new IPEndPoint(1, 1), new IPEndPoint(1, 1), this.Network, DateTimeProvider.Default.GetTimeOffset());

            version.Services = NetworkPeerServices.Network;

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

            var stateChanged    = new AsyncExecutionEvent <INetworkPeer, NetworkPeerState>();
            var messageReceived = new AsyncExecutionEvent <INetworkPeer, IncomingMessage>();

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

            var connectionManagerBehaviorMock = new Mock <IConnectionManagerBehavior>();

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

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

            return(peer);
        }
        /// <summary>
        /// Event handler that is called when the attached node receives a network message.
        /// </summary>
        /// <param name="node">Node that received the message.</param>
        /// <param name="message">Received message.</param>
        /// <remarks>
        /// This handler only cares about "verack" messages, which are only sent once per node
        /// and at the time they are sent the time offset information is parsed by underlaying logic.
        /// <para>
        /// Note that it is not possible to use "version" message here as <see cref="Node"/>
        /// does not deliver this message for inbound peers to node behaviors.
        /// </para>
        /// </remarks>
        private void AttachedNode_MessageReceived(Node node, IncomingMessage message)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}')", nameof(node), node.RemoteSocketEndpoint, nameof(message), message.Message.Command);

            VerAckPayload verack = message.Message.Payload as VerAckPayload;

            if (verack != null)
            {
                IPAddress address = node.RemoteSocketAddress;
                if (address != null)
                {
                    VersionPayload version = node.PeerVersion;
                    if (version != null)
                    {
                        TimeSpan timeOffset = version.Timestamp - this.dateTimeProvider.GetUtcNow();
                        if (timeOffset != null)
                        {
                            this.state.AddTimeData(address, timeOffset, node.Inbound);
                        }
                    }
                    else
                    {
                        this.logger.LogTrace("Node '{0}' does not have an initialized time offset.", node.RemoteSocketEndpoint);
                    }
                }
                else
                {
                    this.logger.LogTrace("Message received from unknown node's address.");
                }
            }

            this.logger.LogTrace("(-)");
        }
示例#12
0
        /// <summary>
        /// Event handler that is called when the node receives a network message from the attached peer.
        /// </summary>
        /// <param name="peer">Peer that sent us the message.</param>
        /// <param name="message">Received message.</param>
        /// <remarks>
        /// This handler only cares about "verack" messages, which are only sent once per node
        /// and at the time they are sent the time offset information is parsed by underlaying logic.
        /// <para>
        /// Note that it is not possible to use "version" message here as <see cref="INetworkPeer"/>
        /// does not deliver this message for inbound peers to node behaviors.
        /// </para>
        /// </remarks>
        private Task OnMessageReceivedAsync(INetworkPeer peer, IncomingMessage message)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}')", nameof(peer), peer.RemoteSocketEndpoint, nameof(message), message.Message.Command);

            if (message.Message.Payload is VerAckPayload verack)
            {
                IPAddress address = peer.RemoteSocketAddress;
                if (address != null)
                {
                    VersionPayload version = peer.PeerVersion;
                    if (version != null)
                    {
                        TimeSpan timeOffset = version.Timestamp - this.dateTimeProvider.GetTimeOffset();
                        if (timeOffset != null)
                        {
                            this.state.AddTimeData(address, timeOffset, peer.Inbound);
                        }
                    }
                    else
                    {
                        this.logger.LogTrace("Node '{0}' does not have an initialized time offset.", peer.RemoteSocketEndpoint);
                    }
                }
                else
                {
                    this.logger.LogTrace("Message received from unknown node's address.");
                }
            }

            this.logger.LogTrace("(-)");
            return(Task.CompletedTask);
        }
示例#13
0
 public TaskSession(IActorRef node, VersionPayload version)
 {
     this.RemoteNode  = node;
     this.Version     = version;
     this.StartHeight = version.Capabilities
                        .OfType <FullNodeCapability>()
                        .FirstOrDefault()?.StartHeight ?? 0;
 }
示例#14
0
 public RemoteNode(CamSystem system, object connection, IPEndPoint remote, IPEndPoint local)
     : base(connection, remote, local)
 {
     this.system   = system;
     this.protocol = Context.ActorOf(ProtocolHandler.Props(system));
     LocalNode.Singleton.RemoteNodes.TryAdd(Self, this);
     SendMessage(Message.Create("version", VersionPayload.Create(LocalNode.Singleton.ListenerPort, LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height)));
 }
示例#15
0
 public static byte[] EncodeVersionPayload(VersionPayload versionPayload, bool withRelay)
 {
     using (var stream = new MemoryStream())
     {
         EncodeVersionPayload(stream, versionPayload, withRelay);
         return(stream.ToArray());
     }
 }
示例#16
0
        private void OnRegister(VersionPayload version)
        {
            Context.Watch(Sender);
            TaskSession session = new TaskSession(Sender, version);

            sessions.Add(Sender, session);
            RequestTasks(session);
        }
示例#17
0
        public void TestVersoinPayload()
        {
            VersionPayload payload;

            byte[] expected;

            payload = new VersionPayload(
                version: 70001,
                services: 0x01,
                timeStamp: new DateTime(1000),
                addressTo: new IPAddressPayload(
                    timeStamp: new DateTime(),
                    services: (UInt64)1,
                    address: IPAddress.Parse("10.0.0.2"),
                    port: (UInt16)9911
                    ),
                addressFrom: new IPAddressPayload(
                    timeStamp: new DateTime(),
                    services: (UInt64)1,
                    address: IPAddress.Parse("10.0.0.1"),
                    port: (UInt16)9911
                    ),
                nonce: 0,
                userAgent: new StringPayload("/UnitTest-v0.0.1/"),
                startHeight: 1000,
                relay: true
                );
            expected = new byte[] {
                0x71, 0x11, 0x01, 0x00,                         // Version
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Services
                0xE8, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // TimeStamp

                // AddressTo
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Services
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address...
                0x00, 0x00, 0xFF, 0xFF, 0x0A, 0x00, 0x00, 0x02, // ...
                0x26, 0xB7,                                     // Port

                // AddressFrom
                0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Services
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Address...
                0x00, 0x00, 0xFF, 0xFF, 0x0A, 0x00, 0x00, 0x01, // ...
                0x26, 0xB7,                                     // Port

                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Nonce

                // UserAgent
                17,                                             // UserAgent byte count
                0x2F, 0x55, 0x6E, 0x69, 0x74, 0x54, 0x65, 0x73, // "/UnitTest-v0.0.1/"...
                0x74, 0x2D, 0x76, 0x30, 0x2E, 0x30, 0x2E, 0x31, // ...
                0x2F,                                           // ...

                0xE8, 0x03, 0x00, 0x00,                         // StartHeight
                0x01                                            // Relay
            };
            AssertBytesEqual(expected, payload.ToBytes());
            AssertVersionPayloadsEqual(payload, new VersionPayload(expected));
        }
        private bool DoesPeerSupportsPH(VersionPayload peerVersion)
        {
            if (peerVersion == null)
            {
                return(false);
            }

            return(peerVersion.Version >= NBitcoin.Protocol.ProtocolVersion.PROVEN_HEADER_VERSION);
        }
示例#19
0
 private void OnRegister(VersionPayload version)
 {
     Context.Watch(Sender);
     TaskSession session = new TaskSession(version);
     if (session.IsFullNode)
         session.InvTasks.TryAdd(MemPoolTaskHash, TimeProvider.Current.UtcNow);
     sessions.TryAdd(Sender, session);
     RequestTasks();
 }
示例#20
0
        public TaskSession(IActorRef node, VersionPayload version)
        {
            var fullNode = version.Capabilities.OfType <FullNodeCapability>().FirstOrDefault();

            this.IsFullNode     = fullNode != null;
            this.RemoteNode     = node;
            this.Version        = version;
            this.StartHeight    = fullNode?.StartHeight ?? 0;
            this.LastBlockIndex = this.StartHeight;
        }
示例#21
0
        public void TryDeserializeTest()
        {
            var pl = new VersionPayload();

            byte[] data = Helper.HexToBytes("721101000100000000000000bc8f5e5400000000010000000000000000000000000000000000ffffc61b6409208d010000000000000000000000000000000000ffffcb0071c0208d128035cbc97953f80f2f5361746f7368693a302e392e332fcf05050001");
            bool   b    = pl.TryDeserialize(new FastStreamReader(data), out string error);

            Assert.True(b, error);
            Assert.Null(error);
        }
示例#22
0
 public MockNodeStatus(VersionPayload pl)
 {
     _protVer       = pl.Version;
     _servs         = pl.Services;
     _nonce         = pl.Nonce;
     _agent         = pl.UserAgent;
     _height        = pl.StartHeight;
     _relayToReturn = pl.Relay;
     _relayToSet    = pl.Relay;
 }
示例#23
0
        /// <summary>
        ///     Processes an initial "version" message received from a peer.
        /// </summary>
        /// <param name="version">Version message received from a peer.</param>
        /// <param name="cancellation">Cancellation token to abort message processing.</param>
        /// <exception cref="OperationCanceledException">Thrown if the response to our "version" message is not received on time.</exception>
        async Task ProcessInitialVersionPayloadAsync(VersionPayload version, CancellationToken cancellation)
        {
            this.PeerVersion = version;
            var connectedToSelf = version.Nonce == this.ConnectionParameters.Nonce;

            this.logger.LogDebug("First message received from peer '{0}'.", version.AddressFrom);

            if (connectedToSelf)
            {
                this.logger.LogDebug("Connection to self detected, disconnecting.");

                Disconnect("Connected to self");
                this.selfEndpointTracker.Add(version.AddressReceiver);

                this.logger.LogTrace("(-)[CONNECTED_TO_SELF]");
                throw new OperationCanceledException();
            }

            using (var cancellationSource =
                       CancellationTokenSource.CreateLinkedTokenSource(this.Connection.CancellationSource.Token, cancellation))
            {
                cancellationSource.CancelAfter(TimeSpan.FromSeconds(10.0));
                try
                {
                    await RespondToHandShakeAsync(cancellationSource.Token).ConfigureAwait(false);
                }
                catch (OperationCanceledException ex)
                {
                    if (ex.CancellationToken == cancellationSource.Token)
                    {
                        this.logger.LogDebug(
                            "Remote peer hasn't responded within 10 seconds of the handshake completion, dropping connection.");
                        Disconnect("Handshake timeout");
                    }
                    else
                    {
                        this.logger.LogDebug("Handshake problem, dropping connection. Problem: '{0}'.", ex.Message);
                        Disconnect($"Handshake problem, reason: '{ex.Message}'.");
                    }

                    this.logger.LogTrace("(-)[HANDSHAKE_TIMEDOUT]");
                    throw;
                }
                catch (Exception ex)
                {
                    this.logger.LogDebug("Exception occurred: {0}", ex.ToString());

                    Disconnect("Handshake exception", ex);

                    this.logger.LogTrace("(-)[HANDSHAKE_EXCEPTION]");
                    throw;
                }
            }
        }
示例#24
0
        private void OnRegister(VersionPayload version)
        {
            Context.Watch(Sender);
            TaskSession session = new TaskSession(Sender, version);

            if (session.IsFullNode)
            {
                session.AvailableTasks.Add(TaskManager.MemPoolTaskHash);
            }
            sessions.Add(Sender, session);
            RequestTasks(session);
        }
示例#25
0
        public void SizeAndEndPoint_Get()
        {
            var test = new VersionPayload()
            {
                Capabilities = new NodeCapability[0], UserAgent = "neo3"
            };

            test.Size.Should().Be(22);

            test = VersionPayload.Create(123, "neo3", new NodeCapability[] { new ServerCapability(NodeCapabilityType.TcpServer, 22) });
            test.Size.Should().Be(25);
        }
示例#26
0
 void AssertVersionPayloadsEqual(VersionPayload expected, VersionPayload actual)
 {
     Assert.AreEqual(expected.Version, actual.Version);
     Assert.AreEqual(expected.Services, actual.Services);
     Assert.AreEqual(expected.TimeStamp, actual.TimeStamp);
     AssertIPAddressPayloadsEqual(expected.AddressFrom, actual.AddressFrom);
     AssertIPAddressPayloadsEqual(expected.AddressTo, actual.AddressTo);
     Assert.AreEqual(expected.Nonce, actual.Nonce);
     AssertStringPayloadsEqual(expected.UserAgent, actual.UserAgent);
     Assert.AreEqual(expected.StartHeight, actual.StartHeight);
     Assert.AreEqual(expected.Relay, actual.Relay);
 }
        public void SizeAndEndPoint_Get()
        {
            var test = new VersionPayload()
            {
                Capabilities = Array.Empty <NodeCapability>(), UserAgent = "Vauth3"
            };

            test.Size.Should().Be(22);

            test = VersionPayload.Create(123, 456, "Vauth3", new NodeCapability[] { new ServerCapability(NodeCapabilityType.TcpServer, 22) });
            test.Size.Should().Be(25);
        }
 public NetworkPeerConnectionParameters()
 {
     this.TemplateBehaviors.Add(new PingPongBehavior());
     this.Version                     = ProtocolVersion.PROTOCOL_VERSION;
     this.IsRelay                     = true;
     this.Services                    = NetworkPeerServices.Nothing;
     this.ConnectCancellation         = default(CancellationToken);
     this.ReceiveBufferSize           = 1000 * 5000;
     this.SendBufferSize              = 1000 * 1000;
     this.UserAgent                   = VersionPayload.GetNBitcoinUserAgent();
     this.PreferredTransactionOptions = NetworkOptions.TemporaryOptions;
 }
示例#29
0
 public NodeConnectionParameters()
 {
     ReuseBuffer = true;
     TemplateBehaviors.Add(new PingPongBehavior());
     Version                     = ProtocolVersion.PROTOCOL_VERSION;
     IsRelay                     = true;
     Services                    = NodeServices.Nothing;
     ConnectCancellation         = default(CancellationToken);
     ReceiveBufferSize           = 1000 * 5000;
     SendBufferSize              = 1000 * 1000;
     UserAgent                   = VersionPayload.GetNBitcoinUserAgent();
     PreferredTransactionOptions = TransactionOptions.All;
 }
示例#30
0
        /// <summary>
        /// Processes an initial "version" message received from a peer.
        /// </summary>
        /// <param name="version">Version message received from a peer.</param>
        /// <exception cref="OperationCanceledException">Thrown if the response to our "version" message is not received on time.</exception>
        private async Task ProcessInitialVersionPayloadAsync(VersionPayload version)
        {
            this.logger.LogTrace("({0}:'{1}')", nameof(version), version);

            this.PeerVersion = version;
            bool connectedToSelf = version.Nonce == this.Parameters.Nonce;

            this.logger.LogDebug("First message received from peer '{0}'.", version.AddressFrom);

            if (connectedToSelf)
            {
                this.logger.LogDebug("Connection to self detected and will be aborted.");

                VersionPayload versionPayload = this.Parameters.CreateVersion(this.PeerAddress.Endpoint, this.Network, this.dateTimeProvider.GetTimeOffset());
                await this.SendMessageAsync(versionPayload);

                this.Disconnect("Connected to self");

                this.logger.LogTrace("(-)[CONNECTED_TO_SELF]");
                return;
            }

            using (CancellationTokenSource cancellationSource = CancellationTokenSource.CreateLinkedTokenSource(this.Connection.CancellationSource.Token))
            {
                cancellationSource.CancelAfter(TimeSpan.FromSeconds(10.0));
                try
                {
                    await this.RespondToHandShakeAsync(cancellationSource.Token).ConfigureAwait(false);
                }
                catch (OperationCanceledException)
                {
                    this.logger.LogTrace("Remote peer haven't responded within 10 seconds of the handshake completion, dropping connection.");

                    this.Disconnect("Handshake timeout");

                    this.logger.LogTrace("(-)[HANDSHAKE_TIMEDOUT]");
                    throw;
                }
                catch (Exception ex)
                {
                    this.logger.LogTrace("Exception occurred: {0}", ex.ToString());

                    this.Disconnect("Handshake exception", ex);

                    this.logger.LogTrace("(-)[HANDSHAKE_EXCEPTION]");
                    throw;
                }
            }

            this.logger.LogTrace("(-)");
        }
示例#31
0
        public static VersionPayload DecodeVersionPayload(BinaryReader reader, int payloadLength)
        {
            var position = reader.BaseStream.Position;

            var versionPayload = new VersionPayload
            (
                ProtocolVersion: reader.ReadUInt32(),
                ServicesBitfield: reader.ReadUInt64(),
                Time: DateTimeOffset.FromUnixTimeSeconds((long)reader.ReadUInt64()),
                RemoteAddress: DecodeNetworkAddress(reader),
                LocalAddress: DecodeNetworkAddress(reader),
                Nonce: reader.ReadUInt64(),
                UserAgent: reader.ReadVarString(),
                StartBlockHeight: reader.ReadUInt32(),
                Relay: false
            );

            var readCount = reader.BaseStream.Position - position;
            if (versionPayload.ProtocolVersion >= VersionPayload.RELAY_VERSION && payloadLength - readCount == 1)
                versionPayload = versionPayload.With(Relay: reader.ReadBool());

            return versionPayload;
        }
示例#32
0
        public static void EncodeVersionPayload(BinaryWriter writer, VersionPayload versionPayload, bool withRelay)
        {
            writer.WriteUInt32(versionPayload.ProtocolVersion);
            writer.WriteUInt64(versionPayload.ServicesBitfield);
            writer.WriteUInt64((ulong)versionPayload.Time.ToUnixTimeSeconds());
            EncodeNetworkAddress(writer, versionPayload.RemoteAddress);
            EncodeNetworkAddress(writer, versionPayload.LocalAddress);
            writer.WriteUInt64(versionPayload.Nonce);
            writer.WriteVarString(versionPayload.UserAgent);
            writer.WriteUInt32(versionPayload.StartBlockHeight);

            if (withRelay)
                writer.WriteBool(versionPayload.Relay);
        }
示例#33
0
 public static byte[] EncodeVersionPayload(VersionPayload versionPayload, bool withRelay)
 {
     using (var stream = new MemoryStream())
     using (var writer = new BinaryWriter(stream))
     {
         EncodeVersionPayload(writer, versionPayload, withRelay);
         return stream.ToArray();
     }
 }