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())));
        }
Exemple #2
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)));
 }
        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);
        }
Exemple #4
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);
        }
Exemple #5
0
        public RemoteNode(ZoroSystem system, object connection, IPEndPoint remote, IPEndPoint local, Blockchain blockchain, LocalNode localNode)
            : base(connection, remote, local)
        {
            this.system     = system;
            this.localNode  = localNode;
            this.blockchain = blockchain;

            this.protocol = Context.ActorOf(ProtocolHandler.Props(system, localNode, blockchain, this), "RemoteNode");
            localNode.RemoteNodes.TryAdd(Self, this);

            SendMessage(Message.Create(MessageType.Version, VersionPayload.Create(localNode.ChainHash, localNode.ListenerPort, LocalNode.NodeId, LocalNode.UserAgent, blockchain.Height)));

            Log($"Connected to RemoteNode {blockchain.Name} {remote}");
        }
        public void DeserializeAndSerialize()
        {
            var test  = VersionPayload.Create(123, 456, "Vauth3", new NodeCapability[] { new ServerCapability(NodeCapabilityType.TcpServer, 22) });
            var clone = test.ToArray().AsSerializable <VersionPayload>();

            CollectionAssert.AreEqual(test.Capabilities.ToByteArray(), clone.Capabilities.ToByteArray());
            Assert.AreEqual(test.UserAgent, clone.UserAgent);
            Assert.AreEqual(test.Nonce, clone.Nonce);
            Assert.AreEqual(test.Timestamp, clone.Timestamp);
            CollectionAssert.AreEqual(test.Capabilities.ToByteArray(), clone.Capabilities.ToByteArray());

            Assert.ThrowsException <FormatException>(() => VersionPayload.Create(123, 456, "Vauth3",
                                                                                 new NodeCapability[] {
                new ServerCapability(NodeCapabilityType.TcpServer, 22),
                new ServerCapability(NodeCapabilityType.TcpServer, 22)
            }).ToArray().AsSerializable <VersionPayload>());
        }
Exemple #7
0
        private void OnStartProtocol()
        {
            var capabilities = new List <NodeCapability>
            {
                new FullNodeCapability(/*DagSystem.Singleton.Storage.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())));
        }
Exemple #8
0
        private void OnStartProtocol()
        {
            var capabilities = new List <NodeCapability>
            {
                new FullNodeCapability(NativeContract.Ledger.CurrentIndex(Blockchain.Singleton.View))
            };

            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())));
        }
Exemple #9
0
        internal async void StartProtocol()
        {
            if (!await SendMessageAsync("version", VersionPayload.Create(localNode.LocalEndpoint.Port, localNode.UserAgent, Blockchain.Default.Height)))
            {
                return;
            }
            Message message = await ReceiveMessageAsync(TimeSpan.FromSeconds(30));

            if (message == null)
            {
                return;
            }
            if (message.Command != "version")
            {
                Disconnect(true);
                return;
            }
            try
            {
                Version = message.Payload.AsSerializable <VersionPayload>();
            }
            catch (FormatException)
            {
                Disconnect(true);
                return;
            }
            if (RemoteEndpoint == null)
            {
                IPAddress  ip             = ((IPEndPoint)tcp.Client.RemoteEndPoint).Address.MapToIPv6();
                IPEndPoint remoteEndpoint = new IPEndPoint(ip, Version.Port);
                lock (localNode.pendingPeers)
                {
                    lock (localNode.connectedPeers)
                    {
                        if (localNode.pendingPeers.All(p => p.RemoteEndpoint != remoteEndpoint) && !localNode.connectedPeers.ContainsKey(remoteEndpoint))
                        {
                            RemoteEndpoint = remoteEndpoint;
                        }
                    }
                }
                if (RemoteEndpoint == null)
                {
                    Disconnect(false);
                    return;
                }
            }
            if (!await SendMessageAsync("verack"))
            {
                return;
            }
            message = await ReceiveMessageAsync(TimeSpan.FromSeconds(30));

            if (message == null)
            {
                return;
            }
            if (message.Command != "verack")
            {
                Disconnect(true);
                return;
            }
            lock (localNode.pendingPeers)
            {
                lock (localNode.connectedPeers)
                {
                    localNode.connectedPeers.Add(RemoteEndpoint, this);
                }
                localNode.pendingPeers.Remove(this);
            }
            if (Blockchain.Default.HeaderHeight < Version.StartHeight)
            {
                HashSet <UInt256> hashes = new HashSet <UInt256>(Blockchain.Default.GetLeafHeaderHashes());
                hashes.UnionWith(hashes.Select(p => Blockchain.Default.GetHeader(p).PrevBlock).ToArray());
                await SendMessageAsync("getheaders", GetBlocksPayload.Create(hashes));
            }
            while (disposed == 0)
            {
                if (Blockchain.Default != null && !Blockchain.Default.IsReadOnly)
                {
                    if (missions.Count == 0 && Blockchain.Default.Height < Blockchain.Default.HeaderHeight)
                    {
                        if (!await SendMessageAsync("getblocks", GetBlocksPayload.Create(new[] { Blockchain.Default.CurrentBlockHash })))
                        {
                            break;
                        }
                    }
                }
                TimeSpan timeout = missions.Count == 0 ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(60);
                message = await ReceiveMessageAsync(timeout);

                if (message == null)
                {
                    break;
                }
                try
                {
                    await OnMessageReceivedAsync(message);
                }
                catch (FormatException)
                {
                    Disconnect(true);
                    break;
                }
            }
        }
Exemple #10
0
        internal async void StartProtocol()
        {
            if (!await SendMessageAsync(Message.Create("version", VersionPayload.Create(localNode.Port, localNode.Nonce, localNode.UserAgent))))
            {
                return;
            }
            Message message = await ReceiveMessageAsync(HalfMinute);

            if (message == null)
            {
                return;
            }
            if (message.Command != "version")
            {
                Disconnect(true);
                return;
            }
            try
            {
                Version = message.Payload.AsSerializable <VersionPayload>();
            }
            catch (EndOfStreamException)
            {
                Disconnect(false);
                return;
            }
            catch (FormatException)
            {
                Disconnect(true);
                return;
            }
            if (Version.Nonce == localNode.Nonce)
            {
                Disconnect(true);
                return;
            }
            bool isSelf;

            lock (localNode.connectedPeers)
            {
                isSelf = localNode.connectedPeers.Where(p => p != this).Any(p => p.RemoteEndpoint.Address.Equals(RemoteEndpoint.Address) && p.Version?.Nonce == Version.Nonce);
            }
            if (isSelf)
            {
                Disconnect(false);
                return;
            }
            if (ListenerEndpoint != null)
            {
                if (ListenerEndpoint.Port != Version.Port)
                {
                    Disconnect(true);
                    return;
                }
            }
            else if (Version.Port > 0)
            {
                ListenerEndpoint = new IPEndPoint(RemoteEndpoint.Address, Version.Port);
            }
            if (!await SendMessageAsync(Message.Create("verack")))
            {
                return;
            }
            message = await ReceiveMessageAsync(HalfMinute);

            if (message == null)
            {
                return;
            }
            if (message.Command != "verack")
            {
                Disconnect(true);
                return;
            }
            if (Blockchain.Default?.HeaderHeight < Version.StartHeight)
            {
                EnqueueMessage("getheaders", GetBlocksPayload.Create(Blockchain.Default.CurrentHeaderHash), true);
            }
            StartSendLoop();
            while (disposed == 0)
            {
                if (Blockchain.Default != null)
                {
                    if (missions.Count == 0 && Blockchain.Default.Height < Version.StartHeight)
                    {
                        EnqueueMessage("getblocks", GetBlocksPayload.Create(Blockchain.Default.CurrentBlockHash), true);
                    }
                }
                TimeSpan timeout = missions.Count == 0 ? HalfHour : OneMinute;
                message = await ReceiveMessageAsync(timeout);

                if (message == null)
                {
                    break;
                }
                if (DateTime.Now - mission_start > OneMinute &&
                    message.Command != "block" && message.Command != "consensus" && message.Command != "tx")
                {
                    Disconnect(false);
                    break;
                }
                try
                {
                    OnMessageReceived(message);
                }
                catch (EndOfStreamException)
                {
                    Disconnect(false);
                    break;
                }
                catch (FormatException)
                {
                    Disconnect(true);
                    break;
                }
            }
        }
Exemple #11
0
        private void RunProtocol()
        {
            if (!SendMessage(Message.Create("version", VersionPayload.Create(localNode.Port, localNode.Nonce, localNode.UserAgent))))
            {
                return;
            }
            Message message = ReceiveMessage(TimeSpan.FromSeconds(30));

            if (message == null)
            {
                return;
            }
            if (message.Command != "version")
            {
                Disconnect(true);
                return;
            }
            try
            {
                Version = message.Payload.AsSerializable <VersionPayload>();
            }
            catch (EndOfStreamException)
            {
                Disconnect(false);
                return;
            }
            catch (FormatException)
            {
                Disconnect(true);
                return;
            }
            if (Version.Nonce == localNode.Nonce)
            {
                Disconnect(true);
                return;
            }
            lock (localNode.pendingPeers)
            {
                lock (localNode.connectedPeers)
                {
                    if (localNode.connectedPeers.Any(p => p.RemoteEndpoint.Address.Equals(RemoteEndpoint.Address) && p.Version.Nonce == Version.Nonce))
                    {
                        Disconnect(false);
                        return;
                    }
                    localNode.connectedPeers.Add(this);
                }
                if (ListenerEndpoint != null)
                {
                    localNode.pendingPeers.Remove(ListenerEndpoint);
                }
            }
            if (ListenerEndpoint != null)
            {
                if (ListenerEndpoint.Port != Version.Port)
                {
                    Disconnect(true);
                    return;
                }
            }
            else if (Version.Port > 0)
            {
                ListenerEndpoint = new IPEndPoint(RemoteEndpoint.Address, Version.Port);
            }
            if (!SendMessage(Message.Create("verack")))
            {
                return;
            }
            message = ReceiveMessage(TimeSpan.FromSeconds(30));
            if (message == null)
            {
                return;
            }
            if (message.Command != "verack")
            {
                Disconnect(true);
                return;
            }
            if (Blockchain.Default?.HeaderHeight < Version.StartHeight)
            {
                HashSet <UInt256> hashes = new HashSet <UInt256>(Blockchain.Default.GetLeafHeaderHashes());
                hashes.UnionWith(hashes.Select(p => Blockchain.Default.GetHeader(p).PrevBlock).ToArray());
                EnqueueMessage("getheaders", GetBlocksPayload.Create(hashes), true);
            }
            sendThread.Start();
            while (disposed == 0)
            {
                if (Blockchain.Default != null && !Blockchain.Default.IsReadOnly)
                {
                    if (missions.Count == 0 && Blockchain.Default.Height < Version.StartHeight)
                    {
                        EnqueueMessage("getblocks", GetBlocksPayload.Create(new[] { Blockchain.Default.CurrentBlockHash }), true);
                    }
                }
                TimeSpan timeout = missions.Count == 0 ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(60);
                message = ReceiveMessage(timeout);
                if (message == null)
                {
                    break;
                }
                try
                {
                    OnMessageReceived(message);
                }
                catch (EndOfStreamException)
                {
                    Disconnect(false);
                    break;
                }
                catch (FormatException)
                {
                    Disconnect(true);
                    break;
                }
            }
        }
Exemple #12
0
        internal async void StartProtocol()
        {
#if !NET47
            //There is a bug in .NET Core 2.0 that blocks async method which returns void.
            await Task.Yield();
#endif
            TR.Enter();

            bool          messageSent = false;
            IndentContext ic          = TR.SaveContextAndShuffle();
            try
            {
                TR.Log("message : {0} to {1}", "version", RemoteEndpoint.Address);
                messageSent = await SendMessageAsync(Message.Create("version", VersionPayload.Create(localNode.Port, localNode.Nonce, localNode.UserAgent)));
            }
            finally
            {
                TR.RestoreContext(ic);
            }
            if (!messageSent)
            {
                TR.Exit();
                return;
            }
            Message message = null;
            ic = TR.SaveContextAndShuffle();
            try
            {
                message = await ReceiveMessageAsync(HalfMinute);
            }
            finally
            {
                TR.RestoreContext(ic);
            }
            if (message == null)
            {
                return;
            }
            TR.Log("message : {0} from {1}", message.Command, RemoteEndpoint.Address);
            if (message.Command != "version")
            {
                TR.Log();
                Disconnect(true);
                TR.Exit();
                return;
            }
            try
            {
                Version = message.Payload.AsSerializable <VersionPayload>();
            }
            catch (EndOfStreamException)
            {
                TR.Log();
                Disconnect(false);
                TR.Exit();
                return;
            }
            catch (FormatException)
            {
                TR.Log();
                Disconnect(true);
                TR.Exit();
                return;
            }
            if (Version.Nonce == localNode.Nonce)
            {
                TR.Log();
                Disconnect(true);
                TR.Exit();
                return;
            }
            bool isSelf;
            lock (localNode.connectedPeers)
            {
                isSelf = localNode.connectedPeers.Where(p => p != this).Any(p => p.RemoteEndpoint.Address.Equals(RemoteEndpoint.Address) && p.Version?.Nonce == Version.Nonce);
            }
            if (isSelf)
            {
                TR.Log();
                Disconnect(false);
                TR.Exit();
                return;
            }
            if (ListenerEndpoint == null && Version.Port > 0)
            {
                ListenerEndpoint = new IPEndPoint(RemoteEndpoint.Address, Version.Port);
            }

            ic = TR.SaveContextAndShuffle();
            try
            {
                messageSent = await SendMessageAsync(Message.Create("verack"));

                TR.Log("message : {0} to {1}", "verack", RemoteEndpoint.Address);
            }
            finally
            {
                TR.RestoreContext(ic);
            }
            if (!messageSent)
            {
                TR.Exit();
                return;
            }
            ic = TR.SaveContextAndShuffle();
            try
            {
                message = await ReceiveMessageAsync(HalfMinute);
            }
            finally
            {
                TR.RestoreContext(ic);
            }

            if (message == null)
            {
                TR.Exit();
                return;
            }
            TR.Log("message : {0} from {1}", message.Command, RemoteEndpoint.Address);
            if (message.Command != "verack")
            {
                TR.Log();
                Disconnect(true);
                TR.Exit();
                return;
            }
            if (Blockchain.Default?.HeaderHeight < Version.StartHeight)
            {
                TR.Log("local header height : {0}, remote height : {1}, {2}", Blockchain.Default?.HeaderHeight, Version.StartHeight, RemoteEndpoint.Address);
                EnqueueMessage("getheaders", GetBlocksPayload.Create(Blockchain.Default.CurrentHeaderHash));
                TR.Log("current header hash : {0}", Blockchain.Default.CurrentHeaderHash.ToString());
            }
            StartSendLoop();
            while (disposed == 0)
            {
                if (Blockchain.Default != null)
                {
                    if (missions.Count == 0 && Blockchain.Default.Height < Version.StartHeight)
                    {
                        TR.Log("local height : {0}, remote height : {1}, {2}", Blockchain.Default.Height, Version.StartHeight, RemoteEndpoint.Address);
                        EnqueueMessage("getblocks", GetBlocksPayload.Create(Blockchain.Default.CurrentBlockHash));
                    }
                }
                TimeSpan timeout = missions.Count == 0 ? HalfHour : OneMinute;
                ic = TR.SaveContextAndShuffle();
                try
                {
                    message = await ReceiveMessageAsync(timeout);
                }
                finally
                {
                    TR.RestoreContext(ic);
                }
                if (message == null)
                {
                    break;
                }
                if (DateTime.Now - mission_start > OneMinute &&
                    message.Command != "block" && message.Command != "consensus" && message.Command != "tx")
                {
                    TR.Log();
                    Disconnect(false);
                    break;
                }
                try
                {
                    OnMessageReceived(message);
                }
                catch (EndOfStreamException)
                {
                    TR.Log();
                    Disconnect(false);
                    break;
                }
                catch (FormatException)
                {
                    TR.Log();
                    Disconnect(true);
                    break;
                }
            }
            TR.Exit();
        }
Exemple #13
0
        private void RunProtocol()
        {
            if (!SendMessage(Message.Create("version", VersionPayload.Create(localNode.Port, localNode.Nonce, localNode.UserAgent))))
            {
                return;
            }
            Message message = ReceiveMessage(TimeSpan.FromSeconds(30));

            if (message == null)
            {
                return;
            }
            if (message.Command != "version")
            {
                Disconnect(true);
                return;
            }
            try
            {
                Version = message.Payload.AsSerializable <VersionPayload>();
            }
            catch (EndOfStreamException)
            {
                Disconnect(false);
                return;
            }
            catch (FormatException)
            {
                Disconnect(true);
                return;
            }
            if (Version.Nonce == localNode.Nonce)
            {
                Disconnect(true);
                return;
            }
            lock (localNode.connectedPeers)
            {
                if (localNode.connectedPeers.Where(p => p != this).Any(p => p.RemoteEndpoint.Address.Equals(RemoteEndpoint.Address) && p.Version?.Nonce == Version.Nonce))
                {
                    Disconnect(false);
                    return;
                }
            }
            if (ListenerEndpoint != null)
            {
                if (ListenerEndpoint.Port != Version.Port)
                {
                    Disconnect(true);
                    return;
                }
            }
            else if (Version.Port > 0)
            {
                ListenerEndpoint = new IPEndPoint(RemoteEndpoint.Address, Version.Port);
            }
            if (!SendMessage(Message.Create("verack")))
            {
                return;
            }
            message = ReceiveMessage(TimeSpan.FromSeconds(30));
            if (message == null)
            {
                return;
            }
            if (message.Command != "verack")
            {
                Disconnect(true);
                return;
            }
            if (Blockchain.Default?.HeaderHeight < Version.StartHeight)
            {
                EnqueueMessage("getheaders", GetBlocksPayload.Create(Blockchain.Default.CurrentHeaderHash), true);
            }
            sendThread.Name = $"RemoteNode.SendLoop@{RemoteEndpoint}";
            sendThread.Start();
            while (disposed == 0)
            {
                if (Blockchain.Default?.IsReadOnly == false)
                {
                    if (missions.Count == 0 && Blockchain.Default.Height < Version.StartHeight)
                    {
                        EnqueueMessage("getblocks", GetBlocksPayload.Create(Blockchain.Default.CurrentBlockHash), true);
                    }
                }
                TimeSpan timeout = missions.Count == 0 ? TimeSpan.FromMinutes(30) : TimeSpan.FromSeconds(60);
                message = ReceiveMessage(timeout);
                if (message == null)
                {
                    break;
                }
                try
                {
                    OnMessageReceived(message);
                }
                catch (EndOfStreamException)
                {
                    Disconnect(false);
                    break;
                }
                catch (FormatException)
                {
                    Disconnect(true);
                    break;
                }
            }
        }