Exemplo n.º 1
0
 public NetworkPeerStorage(string baseDirectory, ChainType chainType)
     : base(Path.Combine(baseDirectory, "KnownAddresses"),
            keyEncoder: key => NetworkEncoder.EncodeNetworkAddressKey(key),
            keyDecoder: key => NetworkEncoder.DecodeNetworkAddressKey(key),
            valueEncoder: value => NetworkEncoder.EncodeNetworkAddressWithTime(value),
            valueDecoder: value => NetworkEncoder.DecodeNetworkAddressWithTime(value))
 {
 }
Exemplo n.º 2
0
        private async Task ConnectAndHandshake(Peer peer)
        {
            peer.OnDisconnect += DisconnectPeer;
            if (peer.IsIncoming)
            {
                Interlocked.Increment(ref this.incomingCount);
            }

            // connect
            await peer.ConnectAsync();

            // notify peer is connected
            PeerConnected?.Invoke(peer);

            // setup task to wait for verack
            var verAckTask = peer.Receiver.WaitForMessage(x => x.Command == "verack", HANDSHAKE_TIMEOUT_MS);

            // setup task to wait for version
            var versionTask = peer.Receiver.WaitForMessage(x => x.Command == "version", HANDSHAKE_TIMEOUT_MS);

            // start listening for messages after tasks have been setup
            peer.Receiver.Listen();

            // send our local version
            var nodeId = random.NextUInt64(); //TODO should be generated and verified on version message

            var currentHeight = this.coreDaemon.CurrentChain.Height;
            await peer.Sender.SendVersion(Messaging.GetExternalIPEndPoint(), peer.RemoteEndPoint, nodeId, (UInt32)currentHeight);

            // wait for our local version to be acknowledged by the remote peer
            // wait for remote peer to send their version
            await Task.WhenAll(verAckTask, versionTask);

            //TODO shouldn't have to decode again
            var versionMessage = versionTask.Result;
            var versionPayload = NetworkEncoder.DecodeVersionPayload(versionMessage.Payload.ToArray(), versionMessage.Payload.Length);

            var remoteAddressWithTime = new NetworkAddressWithTime
                                        (
                Time: DateTimeOffset.Now,
                NetworkAddress: new NetworkAddress
                (
                    Services: versionPayload.LocalAddress.Services,
                    IPv6Address: versionPayload.LocalAddress.IPv6Address,
                    Port: versionPayload.LocalAddress.Port
                )
                                        );

            // acknowledge their version
            await peer.Sender.SendVersionAcknowledge();
        }
Exemplo n.º 3
0
        private void OnGetHeaders(RemoteNode remoteNode, GetBlocksPayload payload)
        {
            // if in comparison mode, synchronize all work before returning current headers
            if (this.Type == LocalClientType.ComparisonToolTestNet)
            {
                this.blockchainDaemon.WaitForFullUpdate();
            }

            var currentBlockchainLocal = this.blockchainDaemon.CurrentBlockchain;
            var blockHeaders           = new List <BlockHeader>(currentBlockchainLocal.BlockCount);

            foreach (var chainedBlock in currentBlockchainLocal.BlockList)
            {
                BlockHeader blockHeader;
                if (this.blockchainDaemon.CacheContext.BlockHeaderCache.TryGetValue(chainedBlock.BlockHash, out blockHeader))
                {
                    blockHeaders.Add(blockHeader);
                }
                else
                {
                    Debugger.Break();
                    Debug.WriteLine("Couldn't generate getheaders response");
                    return;
                }
            }

            var payloadStream = new MemoryStream();

            using (var payloadWriter = new BinaryWriter(payloadStream))
            {
                payloadWriter.WriteVarInt((UInt64)blockHeaders.Count);
                foreach (var blockHeader in blockHeaders)
                {
                    NetworkEncoder.EncodeBlockHeader(payloadStream, blockHeader);
                    payloadWriter.WriteVarInt(0);
                }
            }

            remoteNode.Sender.SendMessageAsync(Messaging.ConstructMessage("headers", payloadStream.ToArray())).Wait();
        }
Exemplo n.º 4
0
        public void TestWireDecodeGetBlocksPayload()
        {
            var actual = NetworkEncoder.EncodeGetBlocksPayload(NetworkEncoder.DecodeGetBlocksPayload(GET_BLOCKS_PAYLOAD_1_BYTES.ToArray()));

            CollectionAssert.AreEqual(GET_BLOCKS_PAYLOAD_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 5
0
        public void TestWireDecodeAlertPayload()
        {
            var actual = NetworkEncoder.EncodeAlertPayload(NetworkEncoder.DecodeAlertPayload(ALERT_PAYLOAD_1_BYTES.ToArray()));

            CollectionAssert.AreEqual(ALERT_PAYLOAD_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 6
0
        public void TestWireDecodeVersionPayloadWithRelay()
        {
            var actual = NetworkEncoder.EncodeVersionPayload(NetworkEncoder.DecodeVersionPayload(VERSION_PAYLOAD_2_RELAY_BYTES.ToArray(), VERSION_PAYLOAD_2_RELAY_BYTES.Length), withRelay: true);

            CollectionAssert.AreEqual(VERSION_PAYLOAD_2_RELAY_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 7
0
        public void TestWireEncodeVersionPayloadWithoutRelay()
        {
            var actual = NetworkEncoder.EncodeVersionPayload(VERSION_PAYLOAD_1_NO_RELAY, withRelay: false);

            CollectionAssert.AreEqual(VERSION_PAYLOAD_1_NO_RELAY_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 8
0
        public void TestWireDecodeNetworkAddressWithTime()
        {
            var actual = NetworkEncoder.EncodeNetworkAddressWithTime(NetworkEncoder.DecodeNetworkAddressWithTime(NETWORK_ADDRESS_WITH_TIME_1_BYTES.ToArray()));

            CollectionAssert.AreEqual(NETWORK_ADDRESS_WITH_TIME_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 9
0
        public void TestWireEncodeTransaction()
        {
            var actual = NetworkEncoder.EncodeTransaction(TRANSACTION_1);

            CollectionAssert.AreEqual(TRANSACTION_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 10
0
        public void TestWireEncodeAddressPayload()
        {
            var actual = NetworkEncoder.EncodeAddressPayload(ADDRESS_PAYLOAD_1);

            CollectionAssert.AreEqual(ADDRESS_PAYLOAD_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 11
0
        private async Task <bool> ConnectAndHandshake(RemoteNode remoteNode, bool isIncoming)
        {
            // wire node
            WireNode(remoteNode);

            // connect
            await remoteNode.ConnectAsync();

            if (remoteNode.IsConnected)
            {
                //TODO
                RemoteNode ignore;
                this.pendingPeers.TryRemove(remoteNode.RemoteEndPoint, out ignore);
                this.connectedPeers.TryAdd(remoteNode.RemoteEndPoint, remoteNode);

                // setup task to wait for verack
                var verAckTask = remoteNode.Receiver.WaitForMessage(x => x.Command == "verack", HANDSHAKE_TIMEOUT_MS);

                // setup task to wait for version
                var versionTask = remoteNode.Receiver.WaitForMessage(x => x.Command == "version", HANDSHAKE_TIMEOUT_MS);

                // start listening for messages after tasks have been setup
                remoteNode.Receiver.Listen();

                // send our local version
                var nodeId = (((UInt64)random.Next()) << 32) + (UInt64)random.Next(); //TODO should be generated and verified on version message

                var currentBlockchainLocal = this.blockchainDaemon.CurrentBlockchain;
                var currentHeight          = !currentBlockchainLocal.IsDefault ? (UInt32)currentBlockchainLocal.Height : 0;
                await remoteNode.Sender.SendVersion(Messaging.GetExternalIPEndPoint(), remoteNode.RemoteEndPoint, nodeId, currentHeight);

                // wait for our local version to be acknowledged by the remote peer
                // wait for remote peer to send their version
                await Task.WhenAll(verAckTask, versionTask);

                //TODO shouldn't have to decode again
                var versionMessage = versionTask.Result;
                var versionPayload = NetworkEncoder.DecodeVersionPayload(versionMessage.Payload.ToArray().ToMemoryStream(), versionMessage.Payload.Length);

                var remoteAddressWithTime = new NetworkAddressWithTime
                                            (
                    Time: DateTime.UtcNow.ToUnixTime(),
                    NetworkAddress: new NetworkAddress
                    (
                        Services: versionPayload.LocalAddress.Services,
                        IPv6Address: versionPayload.LocalAddress.IPv6Address,
                        Port: versionPayload.LocalAddress.Port
                    )
                                            );

                if (!isIncoming)
                {
                    this.knownAddressCache.UpdateValue(remoteAddressWithTime.GetKey(), remoteAddressWithTime);
                }

                // acknowledge their version
                await remoteNode.Sender.SendVersionAcknowledge();

                return(true);
            }
            else
            {
                return(false);
            }
        }
Exemplo n.º 12
0
        public void TestWireDecodeBlock()
        {
            var actual = NetworkEncoder.EncodeBlock(NetworkEncoder.DecodeBlock(BLOCK_1_BYTES.ToArray().ToMemoryStream()));

            CollectionAssert.AreEqual(BLOCK_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 13
0
        public void TestWireEncodeBlock()
        {
            var actual = NetworkEncoder.EncodeBlock(BLOCK_1);

            CollectionAssert.AreEqual(BLOCK_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 14
0
        public void TestWireDecodeAddressPayload()
        {
            var actual = NetworkEncoder.EncodeAddressPayload(NetworkEncoder.DecodeAddressPayload(ADDRESS_PAYLOAD_1_BYTES.ToArray().ToMemoryStream()));

            CollectionAssert.AreEqual(ADDRESS_PAYLOAD_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 15
0
        public void TestWireDecodeTransaction()
        {
            var actual = NetworkEncoder.EncodeTransaction(NetworkEncoder.DecodeTransaction(TRANSACTION_1_BYTES.ToArray().ToMemoryStream()));

            CollectionAssert.AreEqual(TRANSACTION_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 16
0
        public void TestWireDecodeInventoryPayload()
        {
            var actual = NetworkEncoder.EncodeInventoryPayload(NetworkEncoder.DecodeInventoryPayload(INVENTORY_PAYLOAD_1_BYTES.ToArray()));

            CollectionAssert.AreEqual(INVENTORY_PAYLOAD_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 17
0
        public void TestWireDecodeInventoryVector()
        {
            var actual = NetworkEncoder.EncodeInventoryVector(NetworkEncoder.DecodeInventoryVector(INVENTORY_VECTOR_1_BYTES.ToArray()));

            CollectionAssert.AreEqual(INVENTORY_VECTOR_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 18
0
        public void TestWireEncodeNetworkAddress()
        {
            var actual = NetworkEncoder.EncodeNetworkAddress(NETWORK_ADDRESS_1);

            CollectionAssert.AreEqual(NETWORK_ADDRESS_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 19
0
        public void TestWireDecodeMessage()
        {
            var actual = NetworkEncoder.EncodeMessage(NetworkEncoder.DecodeMessage(MESSAGE_1_BYTES.ToArray()));

            CollectionAssert.AreEqual(MESSAGE_1_BYTES.ToList(), actual.ToList());
        }
Exemplo n.º 20
0
        public void TestWireDecodeNetworkAddress()
        {
            var actual = NetworkEncoder.EncodeNetworkAddress(NetworkEncoder.DecodeNetworkAddress(NETWORK_ADDRESS_1_BYTES.ToArray().ToMemoryStream()));

            CollectionAssert.AreEqual(NETWORK_ADDRESS_1_BYTES.ToList(), actual.ToList());
        }