コード例 #1
0
 private void OnAddrMessageReceived(AddrPayload payload)
 {
     system.LocalNode.Tell(new Peer.Peers
     {
         EndPoints = payload.AddressList.Select(p => p.EndPoint)
     });
 }
コード例 #2
0
        public void AddrPayloadSerialize()
        {
            var original = new AddrPayload
            {
                Address = new[]
                {
                    new NetworkAddressWithTime
                    {
                        EndPoint  = new IPEndPoint(IPAddress.Parse("127.0.0.1").MapToIPv6(), ushort.MaxValue),
                        Services  = ulong.MaxValue,
                        Timestamp = uint.MaxValue,
                    },
                    new NetworkAddressWithTime
                    {
                        EndPoint  = new IPEndPoint(IPAddress.Parse("::01").MapToIPv6(), ushort.MinValue),
                        Services  = ulong.MinValue,
                        Timestamp = uint.MinValue,
                    }
                }
            };

            var copy = _serializer.Deserialize <AddrPayload>(_serializer.Serialize(original));

            Assert.AreEqual(copy.Address.Length, original.Address.Length);

            for (int x = 0; x < copy.Address.Length; x++)
            {
                Assert.AreEqual(copy.Address[x].EndPoint.ToString(), original.Address[x].EndPoint.ToString());
                Assert.AreEqual(copy.Address[x].Timestamp, original.Address[x].Timestamp);
                Assert.AreEqual(copy.Address[x].Services, original.Address[x].Services);
            }
        }
コード例 #3
0
        private async Task OnMessageReceivedAsync(NetworkPeer peer, IncomingMessage message)
        {
            try
            {
                if ((this.Mode & PeerAddressManagerBehaviourMode.Advertise) != 0)
                {
                    if (message.Message.Payload is GetAddrPayload)
                    {
                        var endPoints      = this.peerAddressManager.PeerSelector.SelectPeersForGetAddrPayload(1000).Select(p => p.EndPoint).ToArray();
                        var addressPayload = new AddrPayload(endPoints.Select(p => new NetworkAddress(p)).ToArray());
                        await peer.SendMessageAsync(addressPayload).ConfigureAwait(false);
                    }

                    if (message.Message.Payload is PingPayload ping || message.Message.Payload is PongPayload pong)
                    {
                        if (peer.State == NetworkPeerState.HandShaked)
                        {
                            this.peerAddressManager.PeerSeen(peer.PeerEndPoint, this.dateTimeProvider.GetUtcNow());
                        }
                    }
                }

                if ((this.Mode & PeerAddressManagerBehaviourMode.Discover) != 0)
                {
                    if (message.Message.Payload is AddrPayload addr)
                    {
                        this.peerAddressManager.AddPeers(addr.Addresses, peer.RemoteSocketAddress);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
コード例 #4
0
        private async Task OnMessageReceivedAsync(INetworkPeer peer, IncomingMessage message)
        {
            try
            {
                if ((this.Mode & PeerAddressManagerBehaviourMode.Advertise) != 0)
                {
                    if (message.Message.Payload is GetAddrPayload)
                    {
                        if (!peer.Inbound)
                        {
                            this.logger.LogDebug("Outbound peer sent {0}. Not replying to avoid fingerprinting attack.", nameof(GetAddrPayload));
                            return;
                        }

                        if (this.addrPayloadSent)
                        {
                            this.logger.LogDebug("Multiple GetAddr requests from peer. Not replying to avoid fingerprinting attack.");
                            return;
                        }

                        IEnumerable <IPEndPoint> endPoints = this.peerAddressManager.PeerSelector.SelectPeersForGetAddrPayload(MaxAddressesPerAddrPayload).Select(p => p.Endpoint);
                        var addressPayload = new AddrPayload(endPoints.Select(p => new NetworkAddress(p)).ToArray());

                        await peer.SendMessageAsync(addressPayload).ConfigureAwait(false);

                        this.logger.LogDebug("Sent address payload following GetAddr request.");

                        this.addrPayloadSent = true;
                    }

                    if ((message.Message.Payload is PingPayload) || (message.Message.Payload is PongPayload))
                    {
                        if (peer.State == NetworkPeerState.HandShaked)
                        {
                            this.peerAddressManager.PeerSeen(peer.PeerEndPoint, this.dateTimeProvider.GetUtcNow());
                        }
                    }
                }

                if ((this.Mode & PeerAddressManagerBehaviourMode.Discover) != 0)
                {
                    if (message.Message.Payload is AddrPayload addr)
                    {
                        if (addr.Addresses.Length > MaxAddressesPerAddrPayload)
                        {
                            // Not respecting the protocol.
                            this.peerBanning.BanAndDisconnectPeer(peer.PeerEndPoint, $"Protocol violation: addr payload size is limited by {MaxAddressesPerAddrPayload} entries.");

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

                        this.peerAddressManager.AddPeers(addr.Addresses.Select(a => a.Endpoint), peer.RemoteSocketAddress);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }
        }
コード例 #5
0
        private bool OnBroadcastCommand(string[] args)
        {
            string        command = args[1].ToLower();
            ISerializable payload = null;

            switch (command)
            {
            case "addr":
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp()));
                break;

            case "block":
                if (args[2].Length == 64 || args[2].Length == 66)
                {
                    payload = Blockchain.Default.GetBlock(UInt256.Parse(args[2]));
                }
                else
                {
                    payload = Blockchain.Default.GetBlock(uint.Parse(args[2]));
                }
                break;

            case "getblocks":
            case "getheaders":
                payload = GetBlocksPayload.Create(UInt256.Parse(args[2]));
                break;

            case "getdata":
            case "inv":
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(p => UInt256.Parse(p)).ToArray());
                break;

            case "tx":
                payload = LocalNode.GetTransaction(UInt256.Parse(args[2]));
                if (payload == null)
                {
                    payload = Blockchain.Default.GetTransaction(UInt256.Parse(args[2]));
                }
                break;

            case "alert":
            case "consensus":
            case "filteradd":
            case "filterload":
            case "headers":
            case "merkleblock":
            case "ping":
            case "pong":
            case "reject":
            case "verack":
            case "version":
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            foreach (RemoteNode node in LocalNode.GetRemoteNodes())
            {
                node.EnqueueMessage(command, payload);
            }
            return(true);
        }
コード例 #6
0
        public void TryDeserialize_FailTest(FastStreamReader stream, string expErr)
        {
            AddrPayload pl = new AddrPayload();
            bool        b  = pl.TryDeserialize(stream, out string error);

            Assert.False(b);
            Assert.Equal(expErr, error);
        }
コード例 #7
0
ファイル: RemoteNode.cs プロジェクト: ys8090/NEU
 private void OnAddrMessageReceived(AddrPayload payload)
 {
     IPEndPoint[] peers = payload.AddressList.Select(p => p.EndPoint).Where(p => p.Port != localNode.Port || !LocalNode.LocalAddresses.Contains(p.Address)).ToArray();
     if (peers.Length > 0)
     {
         PeersReceived?.Invoke(this, peers);
     }
 }
コード例 #8
0
 private void OnAddrMessageReceived(AddrPayload payload)
 {
     IPEndPoint[] peers = payload.AddressList.Select(p => p.EndPoint).Where(p => !p.Equals(localNode.LocalEndpoint)).ToArray();
     if (PeersReceived != null && peers.Length > 0)
     {
         PeersReceived(this, peers);
     }
 }
コード例 #9
0
        private async Task OnMessageReceivedAsync(INetworkPeer peer, IncomingMessage message)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}')", nameof(peer), peer.RemoteSocketEndpoint, nameof(message), message.Message.Command);

            try
            {
                if ((this.Mode & PeerAddressManagerBehaviourMode.Advertise) != 0)
                {
                    if (message.Message.Payload is GetAddrPayload)
                    {
                        if (!peer.Inbound)
                        {
                            this.logger.LogTrace("Outbound peer sent {0}. Not replying to avoid fingerprinting attack.", nameof(GetAddrPayload));
                            this.logger.LogTrace("(-)");
                            return;
                        }

                        if (this.sentAddress)
                        {
                            this.logger.LogTrace("Multiple GetAddr requests from peer. Not replying to avoid fingerprinting attack.");
                            this.logger.LogTrace("(-)");
                            return;
                        }

                        IPEndPoint[] endPoints      = this.peerAddressManager.PeerSelector.SelectPeersForGetAddrPayload(1000).Select(p => p.Endpoint).ToArray();
                        var          addressPayload = new AddrPayload(endPoints.Select(p => new NetworkAddress(p)).ToArray());
                        await peer.SendMessageAsync(addressPayload).ConfigureAwait(false);

                        this.logger.LogTrace("Sent address payload following GetAddr request.");

                        this.sentAddress = true;
                    }

                    if (message.Message.Payload is PingPayload ping || message.Message.Payload is PongPayload pong)
                    {
                        if (peer.State == NetworkPeerState.HandShaked)
                        {
                            this.peerAddressManager.PeerSeen(peer.PeerEndPoint, this.dateTimeProvider.GetUtcNow());
                        }
                    }
                }

                if ((this.Mode & PeerAddressManagerBehaviourMode.Discover) != 0)
                {
                    if (message.Message.Payload is AddrPayload addr)
                    {
                        this.peerAddressManager.AddPeers(addr.Addresses.Select(a => a.Endpoint).ToArray(), peer.RemoteSocketAddress);
                    }
                }
            }
            catch (OperationCanceledException)
            {
            }

            this.logger.LogTrace("(-)");
        }
コード例 #10
0
        public void TryDeserialize_EmptyListTest()
        {
            AddrPayload      pl     = new AddrPayload();
            FastStreamReader stream = new FastStreamReader(Helper.HexToBytes("00"));
            bool             b      = pl.TryDeserialize(stream, out string error);

            Assert.True(b, error);
            Assert.Null(error);
            Assert.Empty(pl.Addresses);
        }
コード例 #11
0
        public void SerializeTest()
        {
            AddrPayload pl     = new AddrPayload(new NetworkAddressWithTime[] { addr1, addr2 });
            FastStream  stream = new FastStream(1 + (2 * 30));

            pl.Serialize(stream);

            byte[] actual   = stream.ToByteArray();
            byte[] expected = Helper.HexToBytes("02" + addr1Hex + addr2Hex);

            Assert.Equal(expected, actual);
        }
コード例 #12
0
        private async Task OnGetAddrMessageReceivedAsync()
        {
            if (!localNode.ServiceEnabled)
            {
                return;
            }
            AddrPayload payload;

            lock (localNode.connectedPeers)
            {
                payload = AddrPayload.Create(localNode.connectedPeers.Take(10).Select(p => NetworkAddressWithTime.Create(p.Value.RemoteEndpoint, p.Value.Version.Services, p.Value.Version.Timestamp)).ToArray());
            }
            await SendMessageAsync("addr", payload);
        }
コード例 #13
0
        private void OnGetAddrMessageReceived()
        {
            if (!localNode.ServiceEnabled)
            {
                return;
            }
            AddrPayload payload;

            lock (localNode.connectedPeers)
            {
                payload = AddrPayload.Create(localNode.connectedPeers.Where(p => p.ListenerEndpoint != null && p.Version != null).Take(100).Select(p => NetworkAddressWithTime.Create(p.ListenerEndpoint, p.Version.Services, p.Version.Timestamp)).ToArray());
            }
            EnqueueMessage("addr", payload, true);
        }
コード例 #14
0
        public void Size_Get()
        {
            var test = new AddrPayload()
            {
                AddressList = new NetworkAddressWithTime[0]
            };

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

            test = AddrPayload.Create(new NetworkAddressWithTime[] { new NetworkAddressWithTime()
                                                                     {
                                                                         Address = IPAddress.Any, Capabilities = new Vauth.Network.P2P.Capabilities.NodeCapability[0], Timestamp = 1
                                                                     } });
            test.Size.Should().Be(22);
        }
コード例 #15
0
        private void OnGetAddrMessageReceived()
        {
            Random rand = new Random();
            IEnumerable <RemoteNode> peers = LocalNode.Singleton.RemoteNodes.Values
                                             .Where(p => p.ListenerPort > 0)
                                             .GroupBy(p => p.Remote.Address, (k, g) => g.First())
                                             .OrderBy(p => rand.Next())
                                             .Take(AddrPayload.MaxCountToSend);

            NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)).ToArray();
            if (networkAddresses.Length == 0)
            {
                return;
            }
            Context.Parent.Tell(Message.Create("addr", AddrPayload.Create(networkAddresses)));
        }
コード例 #16
0
        public void DeserializeAndSerialize()
        {
            var test = AddrPayload.Create(new NetworkAddressWithTime[] { new NetworkAddressWithTime()
                                                                         {
                                                                             Address      = IPAddress.Any,
                                                                             Capabilities = new Vauth.Network.P2P.Capabilities.NodeCapability[0], Timestamp = 1
                                                                         } });
            var clone = test.ToArray().AsSerializable <AddrPayload>();

            CollectionAssert.AreEqual(test.AddressList.Select(u => u.EndPoint).ToArray(), clone.AddressList.Select(u => u.EndPoint).ToArray());

            Assert.ThrowsException <FormatException>(() => new AddrPayload()
            {
                AddressList = new NetworkAddressWithTime[0]
            }.ToArray().AsSerializable <AddrPayload>());
        }
コード例 #17
0
        private void OnBroadcastAddressCommand(IPAddress payload, ushort port)
        {
            if (payload == null)
            {
                Console.WriteLine("You must input the payload to relay.");
                return;
            }

            OnBroadcastCommand(MessageCommand.Addr,
                               AddrPayload.Create(
                                   NetworkAddressWithTime.Create(
                                       payload, DateTime.UtcNow.ToTimestamp(),
                                       new FullNodeCapability(),
                                       new ServerCapability(NodeCapabilityType.TcpServer, port))
                                   ));
        }
コード例 #18
0
        private bool OnBroadcastCommand(string[] args)
        {
            if (!Enum.TryParse(args[1], true, out MessageCommand command))
            {
                Console.WriteLine($"Command \"{args[1]}\" is not supported.");
                return(true);
            }
            ISerializable payload = null;

            switch (command)
            {
            case MessageCommand.Addr:
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(IPAddress.Parse(args[2]), DateTime.UtcNow.ToTimestamp(), new FullNodeCapability(), new ServerCapability(NodeCapabilityType.TcpServer, ushort.Parse(args[3]))));
                break;

            case MessageCommand.Block:
                if (args[2].Length == 64 || args[2].Length == 66)
                {
                    payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2]));
                }
                else
                {
                    payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2]));
                }
                break;

            case MessageCommand.GetBlocks:
            case MessageCommand.GetHeaders:
                payload = GetBlocksPayload.Create(UInt256.Parse(args[2]));
                break;

            case MessageCommand.GetData:
            case MessageCommand.Inv:
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray());
                break;

            case MessageCommand.Transaction:
                payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2]));
                break;

            default:
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            system.LocalNode.Tell(Message.Create(command, payload));
            return(true);
        }
コード例 #19
0
ファイル: ProtocolHandler.cs プロジェクト: ZoroChain/Zoro
        private void OnAddrMessageReceived(Message msg)
        {
            AddrPayload payload = msg.GetPayload <AddrPayload>();

            // 过滤掉已经建立了连接的地址
            IEnumerable <IPEndPoint> Listeners   = localNode.RemoteNodes.Values.Select(p => p.Listener);
            IEnumerable <IPEndPoint> AddressList = payload.AddressList.Select(p => p.EndPoint).Where(p => !Listeners.Contains(p));

            if (AddressList.Count() == 0)
            {
                return;
            }

            system.LocalNode.Tell(new Peer.Peers
            {
                EndPoints = AddressList
            });
        }
コード例 #20
0
        private bool OnBroadcastCommand(string[] args)
        {
            string        command = args[1].ToLower();
            ISerializable payload = null;

            switch (command)
            {
            case "addr":
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[2]), ushort.Parse(args[3])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp()));
                break;

            case "block":
                if (args[2].Length == 64 || args[2].Length == 66)
                {
                    payload = Blockchain.Singleton.GetBlock(UInt256.Parse(args[2]));
                }
                else
                {
                    payload = Blockchain.Singleton.Store.GetBlock(uint.Parse(args[2]));
                }
                break;

            case "getblocks":
            case "getheaders":
                payload = GetBlocksPayload.Create(UInt256.Parse(args[2]));
                break;

            case "getdata":
            case "inv":
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[2], true), args.Skip(3).Select(UInt256.Parse).ToArray());
                break;

            case "tx":
                payload = Blockchain.Singleton.GetTransaction(UInt256.Parse(args[2]));
                break;

            default:
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            system.LocalNode.Tell(Message.Create(command, payload));
            return(true);
        }
コード例 #21
0
        private void AttachedPeer_MessageReceived(NetworkPeer peer, IncomingMessage message)
        {
            if ((this.Mode & PeerAddressManagerBehaviourMode.Advertise) != 0)
            {
                if (message.Message.Payload is GetAddrPayload getaddr)
                {
                    var endPoints      = this.peerAddressManager.PeerSelector.SelectPeersForGetAddrPayload(1000).Select(p => p.EndPoint).ToArray();
                    var addressPayload = new AddrPayload(endPoints.Select(p => new NetworkAddress(p)).ToArray());
                    peer.SendMessageVoidAsync(addressPayload);
                }
            }

            if ((this.Mode & PeerAddressManagerBehaviourMode.Discover) != 0)
            {
                if (message.Message.Payload is AddrPayload addr)
                {
                    this.peerAddressManager.AddPeers(addr.Addresses, peer.RemoteSocketAddress);
                }
            }
        }
コード例 #22
0
        public static void Process(BaseChain chain, Node node, IncomingMessage message)
        {
            if (message.Message.Command != "addr")
            {
                return;
            }

            NLog.Logger _logger = NLog.LogManager.GetCurrentClassLogger();
            AddrPayload payload = (AddrPayload)message.Message.Payload;

            foreach (NetworkAddress address in payload.Addresses)
            {
                AddNodeCommand command = new AddNodeCommand
                {
                    Chain   = chain.ChainName,
                    Address = address.Endpoint.Address.ToString(),
                    Port    = address.Endpoint.Port,
                };
                chain.SendCommand(command).GetAwaiter().GetResult();
            }
        }
コード例 #23
0
        public void TryDeserializeTest()
        {
            AddrPayload      pl     = new AddrPayload();
            FastStreamReader stream = new FastStreamReader(Helper.HexToBytes("02" + addr1Hex + addr2Hex));
            bool             b      = pl.TryDeserialize(stream, out string error);

            Assert.True(b, error);
            Assert.Null(error);
            Assert.Equal(2, pl.Addresses.Length);

            Assert.Equal(addr1.Time, pl.Addresses[0].Time);
            Assert.Equal(addr1.NodeServices, pl.Addresses[0].NodeServices);
            Assert.Equal(addr1.NodeIP, pl.Addresses[0].NodeIP);
            Assert.Equal(addr1.NodePort, pl.Addresses[0].NodePort);

            Assert.Equal(addr2.Time, pl.Addresses[1].Time);
            Assert.Equal(addr2.NodeServices, pl.Addresses[1].NodeServices);
            Assert.Equal(addr2.NodeIP, pl.Addresses[1].NodeIP);
            Assert.Equal(addr2.NodePort, pl.Addresses[1].NodePort);

            Assert.Equal(PayloadType.Addr, pl.PayloadType);
        }
コード例 #24
0
ファイル: RemoteNode.cs プロジェクト: ys8090/NEU
        private void OnGetAddrMessageReceived()
        {
            if (!localNode.ServiceEnabled)
            {
                return;
            }
            AddrPayload payload;

            lock (localNode.connectedPeers)
            {
                const int MaxCountToSend       = 200;
                IEnumerable <RemoteNode> peers = localNode.connectedPeers.Where(p => p.ListenerEndpoint != null && p.Version != null);
                if (localNode.connectedPeers.Count > MaxCountToSend)
                {
                    Random rand = new Random();
                    peers = peers.OrderBy(p => rand.Next());
                }
                peers   = peers.Take(MaxCountToSend);
                payload = AddrPayload.Create(peers.Select(p => NetworkAddressWithTime.Create(p.ListenerEndpoint, p.Version.Services, p.Version.Timestamp)).ToArray());
            }
            EnqueueMessage("addr", payload, true);
        }
コード例 #25
0
        private async Task HandleOutboundHandshakeMessage(NetworkNode node, Message msg, Blockchain blockchain)
        {
            if (node.HandshakeStage == 1 && msg.Command == NetworkCommand.VerAck.ToString())
            {
                // Receive a version acknowledgement
                node.ProgressHandshakeStage();
            }
            else if (node.HandshakeStage == 2)
            {
                // Then, receive a version message
                // Verify if the protocol version is the same as ours
                var payload = (VersionPayload)msg.Payload;
                if (payload.ProtocolVersion != BlockchainConstants.ProtocolVersion)
                {
                    throw new ArgumentException("Mismatch in protocol version");
                }
                _logger.LogDebug("Accepted version from node {0} on port {1}", node.DirectEndpoint.Address.ToString(), node.DirectEndpoint.Port);
                node.IsSyncCandidate = payload.BlockHeight > blockchain.CurrentHeight;
                node.ProgressHandshakeStage();

                // Send an acknowledgement
                await SendMessageToNode(node, NetworkCommand.VerAck, null);

                _logger.LogInformation("Successfully connected to node {0} on port {1}", node.DirectEndpoint.Address.ToString(), node.DirectEndpoint.Port);

                // Request all peers that the remote node knows
                await SendMessageToNode(node, NetworkCommand.GetAddr, null);

                // Send our known peers
                var addresses = new AddrPayload(_nodePool.GetAllRemoteListenEndpoints());
                await SendMessageToNode(node, NetworkCommand.Addr, addresses);

                // Download their transaction pool
                await SendMessageToNode(node, NetworkCommand.GetTxPool, null);
            }
        }
コード例 #26
0
        private void OnGetAddrMessageReceived()
        {
            if (!localNode.ServiceEnabled)
            {
                return;
            }
            AddrPayload payload;

            lock (localNode.connectedPeers)
            {
                const int MaxCountToSend       = 200;
                IEnumerable <RemoteNode> peers = localNode.connectedPeers.Where(p => p.ListenerEndpoint != null && p.Version != null);
                if (localNode.connectedPeers.Count > MaxCountToSend)
                {
                    var rnd = new byte[4];
                    using (var rng = new RNGCryptoServiceProvider())
                        rng.GetBytes(rnd);
                    peers = peers.OrderBy(p => BitConverter.ToInt32(rnd, 0));
                }
                peers   = peers.Take(MaxCountToSend);
                payload = AddrPayload.Create(peers.Select(p => NetworkAddressWithTime.Create(p.ListenerEndpoint, p.Version.Services, p.Version.Timestamp)).ToArray());
            }
            EnqueueMessage("addr", payload, true);
        }
コード例 #27
0
ファイル: NetworkPeer.cs プロジェクト: clintnetwork/blockcore
        /// <inheritdoc/>
        public async Task VersionHandshakeAsync(NetworkPeerRequirement requirements, CancellationToken cancellationToken)
        {
            // Note that this method gets called for outbound peers. When our peer is inbound we receive the initial version handshake from the initiating peer, and it is handled via this.ProcessMessageAsync() only.

            // In stratisX, the equivalent functionality is contained in main.cpp, method ProcessMessage()

            requirements = requirements ?? new NetworkPeerRequirement();
            NetworkPeerListener listener = null;

            try
            {
                listener = new NetworkPeerListener(this, this.asyncProvider);
                this.logger.LogDebug("Sending my version.");
                await this.SendMessageAsync(this.MyVersion, cancellationToken).ConfigureAwait(false);

                this.logger.LogDebug("Waiting for version or rejection message.");
                bool versionReceived = false;
                bool verAckReceived  = false;
                while (!versionReceived || !verAckReceived)
                {
                    Payload payload = await listener.ReceivePayloadAsync <Payload>(cancellationToken).ConfigureAwait(false);

                    switch (payload)
                    {
                    case RejectPayload rejectPayload:
                        this.logger.LogTrace("(-)[HANDSHAKE_REJECTED]");
                        throw new ProtocolException("Handshake rejected: " + rejectPayload.Reason);

                    case VersionPayload versionPayload:
                        versionReceived = true;

                        this.PeerVersion = versionPayload;
                        if (!versionPayload.AddressReceiver.Address.MapToIPv6().Equals(this.MyVersion.AddressFrom.Address.MapToIPv6()))
                        {
                            this.logger.LogDebug("Different external address detected by the node '{0}' instead of '{1}'.", versionPayload.AddressReceiver.Address, this.MyVersion.AddressFrom.Address);
                        }

                        if (versionPayload.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION)
                        {
                            this.logger.LogDebug("Outdated version {0} received, disconnecting peer.", versionPayload.Version);

                            this.Disconnect("Outdated version");
                            this.logger.LogTrace("(-)[OUTDATED]");
                            return;
                        }

                        if (!requirements.Check(versionPayload, this.Inbound, out string reason))
                        {
                            this.logger.LogTrace("(-)[UNSUPPORTED_REQUIREMENTS]");
                            this.Disconnect("The peer does not support the required services requirement, reason: " + reason);
                            return;
                        }

                        this.logger.LogDebug("Sending version acknowledgement.");
                        await this.SendMessageAsync(new VerAckPayload(), cancellationToken).ConfigureAwait(false);

                        // Note that we only update our external address data from information returned by outbound peers.
                        // TODO: Is this due to a security assumption or is it an oversight? There is a higher risk the inbounds could be spoofing what they claim our external IP is. We would then use it in future version payloads, so that could be considered an attack.
                        // For outbounds: AddressFrom is our current external endpoint from our perspective, and could easily be incorrect if it has been automatically detected from local NICs.
                        // Whereas AddressReceiver is the endpoint from the peer's perspective, so we update our view using that.
                        this.selfEndpointTracker.UpdateAndAssignMyExternalAddress(versionPayload.AddressReceiver, false);
                        break;

                    case VerAckPayload verAckPayload:
                        verAckReceived = true;
                        break;
                    }
                }

                await this.SetStateAsync(NetworkPeerState.HandShaked).ConfigureAwait(false);

                if (this.advertize && this.MyVersion.AddressFrom.Address.IsRoutable(true))
                {
                    var addrPayload = new AddrPayload
                                      (
                        new NetworkAddress(this.MyVersion.AddressFrom)
                    {
                        Time = this.dateTimeProvider.GetTimeOffset()
                    }
                                      );

                    await this.SendMessageAsync(addrPayload, cancellationToken).ConfigureAwait(false);
                }

                // Ask the just-handshaked peer for the peers they know about to aid in our own peer discovery.
                await this.SendMessageAsync(new GetAddrPayload(), cancellationToken).ConfigureAwait(false);
            }
            catch
            {
                throw;
            }
            finally
            {
                listener?.Dispose();
            }
        }
コード例 #28
0
        private bool OnBroadcastCommand(string[] args)
        {
            string     command    = args[1].ToLower();
            string     hashString = args[2];
            ZoroSystem zoroSystem = system.GetZoroSystem(hashString);
            Blockchain blockchain = system.GetBlockchain(hashString);

            if (zoroSystem == null || blockchain == null)
            {
                Console.WriteLine($"Unknown blockchain hash {hashString}.");
                return(true);
            }
            ISerializable payload = null;

            switch (command)
            {
            case "addr":
                payload = AddrPayload.Create(NetworkAddressWithTime.Create(new IPEndPoint(IPAddress.Parse(args[3]), ushort.Parse(args[4])), NetworkAddressWithTime.NODE_NETWORK, DateTime.UtcNow.ToTimestamp()));
                break;

            case "block":
                if (args[3].Length == 64 || args[3].Length == 66)
                {
                    payload = blockchain.GetBlock(UInt256.Parse(args[3]));
                }
                else
                {
                    payload = blockchain.Store.GetBlock(uint.Parse(args[3]));
                }
                break;

            case "getblocks":
            case "getheaders":
                payload = GetBlocksPayload.Create(UInt256.Parse(args[3]));
                break;

            case "getdata":
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[3], true), UInt256.Parse(args[4]));
                break;

            case "inv":
            case "getdatagroup":
                payload = InvPayload.Create(Enum.Parse <InventoryType>(args[3], true), args.Skip(4).Select(UInt256.Parse).ToArray());
                break;

            case "tx":
                payload = blockchain.GetTransaction(UInt256.Parse(args[3]));
                break;

            case "alert":
            case "consensus":
            case "filteradd":
            case "filterload":
            case "headers":
            case "merkleblock":
            case "ping":
            case "pong":
            case "reject":
            case "verack":
            case "version":
                Console.WriteLine($"Command \"{command}\" is not supported.");
                return(true);
            }
            zoroSystem.LocalNode.Tell(Message.Create(command, payload));
            return(true);
        }
コード例 #29
0
        /// <inheritdoc/>
        public async Task VersionHandshakeAsync(NetworkPeerRequirement requirements, CancellationToken cancellationToken)
        {
            // In stratisX, the equivalent functionality is contained in main.cpp, method ProcessMessage()

            requirements = requirements ?? new NetworkPeerRequirement();
            using (var listener = new NetworkPeerListener(this, this.asyncProvider))
            {
                this.logger.LogTrace("Sending my version.");
                await this.SendMessageAsync(this.MyVersion, cancellationToken).ConfigureAwait(false);

                this.logger.LogTrace("Waiting for version or rejection message.");
                bool versionReceived = false;
                bool verAckReceived  = false;
                while (!versionReceived || !verAckReceived)
                {
                    Payload payload = await listener.ReceivePayloadAsync <Payload>(cancellationToken).ConfigureAwait(false);

                    switch (payload)
                    {
                    case RejectPayload rejectPayload:
                        this.logger.LogTrace("(-)[HANDSHAKE_REJECTED]");
                        throw new ProtocolException("Handshake rejected: " + rejectPayload.Reason);

                    case VersionPayload versionPayload:
                        versionReceived = true;

                        this.PeerVersion = versionPayload;
                        if (!versionPayload.AddressReceiver.Address.Equals(this.MyVersion.AddressFrom.Address))
                        {
                            this.logger.LogDebug("Different external address detected by the node '{0}' instead of '{1}'.", versionPayload.AddressReceiver.Address, this.MyVersion.AddressFrom.Address);
                        }

                        if (versionPayload.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION)
                        {
                            this.logger.LogDebug("Outdated version {0} received, disconnecting peer.", versionPayload.Version);

                            this.Disconnect("Outdated version");
                            this.logger.LogTrace("(-)[OUTDATED]");
                            return;
                        }

                        if (!requirements.Check(versionPayload, this.Inbound, out string reason))
                        {
                            this.logger.LogTrace("(-)[UNSUPPORTED_REQUIREMENTS]");
                            this.Disconnect("The peer does not support the required services requirement, reason: " + reason);
                            return;
                        }

                        this.logger.LogTrace("Sending version acknowledgement.");
                        await this.SendMessageAsync(new VerAckPayload(), cancellationToken).ConfigureAwait(false);

                        this.selfEndpointTracker.UpdateAndAssignMyExternalAddress(versionPayload.AddressFrom, false);
                        break;

                    case VerAckPayload verAckPayload:
                        verAckReceived = true;
                        break;
                    }
                }

                await this.SetStateAsync(NetworkPeerState.HandShaked).ConfigureAwait(false);

                if (this.advertize && this.MyVersion.AddressFrom.Address.IsRoutable(true))
                {
                    var addrPayload = new AddrPayload
                                      (
                        new NetworkAddress(this.MyVersion.AddressFrom)
                    {
                        Time = this.dateTimeProvider.GetTimeOffset()
                    }
                                      );

                    await this.SendMessageAsync(addrPayload, cancellationToken).ConfigureAwait(false);
                }

                // Ask the just-handshaked peer for the peers they know about to aid in our own peer discovery.
                await this.SendMessageAsync(new GetAddrPayload(), cancellationToken).ConfigureAwait(false);
            }
        }
コード例 #30
0
        /// <inheritdoc/>
        public async Task VersionHandshakeAsync(NetworkPeerRequirement requirements, CancellationToken cancellationToken)
        {
            this.logger.LogTrace("({0}.{1}:{2})", nameof(requirements), nameof(requirements.RequiredServices), requirements?.RequiredServices);

            requirements = requirements ?? new NetworkPeerRequirement();
            using (var listener = new NetworkPeerListener(this))
            {
                this.logger.LogTrace("Sending my version.");
                await this.SendMessageAsync(this.MyVersion, cancellationToken).ConfigureAwait(false);

                this.logger.LogTrace("Waiting for version or rejection message.");
                bool versionReceived = false;
                bool verAckReceived  = false;
                while (!versionReceived || !verAckReceived)
                {
                    Payload payload = await listener.ReceivePayloadAsync <Payload>(cancellationToken).ConfigureAwait(false);

                    switch (payload)
                    {
                    case RejectPayload rejectPayload:
                        this.logger.LogTrace("(-)[HANDSHAKE_REJECTED]");
                        throw new ProtocolException("Handshake rejected: " + rejectPayload.Reason);

                    case VersionPayload versionPayload:
                        versionReceived = true;

                        this.PeerVersion = versionPayload;
                        if (!versionPayload.AddressReceiver.Address.Equals(this.MyVersion.AddressFrom.Address))
                        {
                            this.logger.LogDebug("Different external address detected by the node '{0}' instead of '{1}'.", versionPayload.AddressReceiver.Address, this.MyVersion.AddressFrom.Address);
                        }

                        if (versionPayload.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION)
                        {
                            this.logger.LogDebug("Outdated version {0} received, disconnecting peer.", versionPayload.Version);

                            this.Disconnect("Outdated version");
                            this.logger.LogTrace("(-)[OUTDATED]");
                            return;
                        }

                        if (!requirements.Check(versionPayload))
                        {
                            this.logger.LogTrace("(-)[UNSUPPORTED_REQUIREMENTS]");
                            this.Disconnect("The peer does not support the required services requirement");
                            return;
                        }

                        this.logger.LogTrace("Sending version acknowledgement.");
                        await this.SendMessageAsync(new VerAckPayload(), cancellationToken).ConfigureAwait(false);

                        break;

                    case VerAckPayload verAckPayload:
                        verAckReceived = true;
                        break;
                    }
                }

                await this.SetStateAsync(NetworkPeerState.HandShaked).ConfigureAwait(false);

                if (this.advertize && this.MyVersion.AddressFrom.Address.IsRoutable(true))
                {
                    var addrPayload = new AddrPayload
                                      (
                        new NetworkAddress(this.MyVersion.AddressFrom)
                    {
                        Time = this.dateTimeProvider.GetTimeOffset()
                    }
                                      );

                    await this.SendMessageAsync(addrPayload, cancellationToken).ConfigureAwait(false);
                }
            }

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