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()))); }
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); }
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); }
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>()); }
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()))); }
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()))); }
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; } } }
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; } } }
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; } } }
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(); }
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; } } }