예제 #1
0
            public static void handleGetKeepAlives(byte[] data, RemoteEndpoint endpoint)
            {
                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        int ka_count = (int)reader.ReadIxiVarUInt();

                        int max_ka_per_chunk = CoreConfig.maximumKeepAlivesPerChunk;

                        for (int i = 0; i < ka_count;)
                        {
                            using (MemoryStream mOut = new MemoryStream(max_ka_per_chunk * 570))
                            {
                                using (BinaryWriter writer = new BinaryWriter(mOut))
                                {
                                    int next_ka_count;
                                    if (ka_count - i > max_ka_per_chunk)
                                    {
                                        next_ka_count = max_ka_per_chunk;
                                    }
                                    else
                                    {
                                        next_ka_count = ka_count - i;
                                    }
                                    writer.WriteIxiVarInt(next_ka_count);

                                    for (int j = 0; j < next_ka_count && i < ka_count; j++)
                                    {
                                        i++;

                                        long in_rollback_pos  = reader.BaseStream.Position;
                                        long out_rollback_len = mOut.Length;

                                        if (m.Position == m.Length)
                                        {
                                            break;
                                        }

                                        int    address_len = (int)reader.ReadIxiVarUInt();
                                        byte[] address     = reader.ReadBytes(address_len);

                                        int    device_len = (int)reader.ReadIxiVarUInt();
                                        byte[] device     = reader.ReadBytes(device_len);

                                        Presence p = PresenceList.getPresenceByAddress(address);
                                        if (p == null)
                                        {
                                            Logging.info("I don't have presence: " + Base58Check.Base58CheckEncoding.EncodePlain(address));
                                            continue;
                                        }

                                        PresenceAddress pa = p.addresses.Find(x => x.device.SequenceEqual(device));
                                        if (pa == null)
                                        {
                                            Logging.info("I don't have presence address: " + Base58Check.Base58CheckEncoding.EncodePlain(address));
                                            continue;
                                        }

                                        byte[] ka_bytes = pa.getKeepAliveBytes(address);
                                        byte[] ka_len   = IxiVarInt.GetIxiVarIntBytes(ka_bytes.Length);
                                        writer.Write(ka_len);
                                        writer.Write(ka_bytes);

                                        if (mOut.Length > CoreConfig.maxMessageSize)
                                        {
                                            reader.BaseStream.Position = in_rollback_pos;
                                            mOut.SetLength(out_rollback_len);
                                            i--;
                                            break;
                                        }
                                    }
                                }
                                endpoint.sendData(ProtocolMessageCode.keepAlivesChunk, mOut.ToArray(), null);
                            }
                        }
                    }
                }
            }
            public static void handleGetTransactions2(byte[] data, RemoteEndpoint endpoint)
            {
                using (MemoryStream m = new MemoryStream(data))
                {
                    using (BinaryReader reader = new BinaryReader(m))
                    {
                        int msg_id   = (int)reader.ReadIxiVarInt();
                        int tx_count = (int)reader.ReadIxiVarUInt();

                        int max_tx_per_chunk = CoreConfig.maximumTransactionsPerChunk;
                        if (tx_count > max_tx_per_chunk)
                        {
                            tx_count = max_tx_per_chunk;
                        }

                        for (int i = 0; i < tx_count;)
                        {
                            using (MemoryStream mOut = new MemoryStream(max_tx_per_chunk * 570))
                            {
                                using (BinaryWriter writer = new BinaryWriter(mOut))
                                {
                                    int next_tx_count;
                                    if (tx_count - i > max_tx_per_chunk)
                                    {
                                        next_tx_count = max_tx_per_chunk;
                                    }
                                    else
                                    {
                                        next_tx_count = tx_count - i;
                                    }
                                    writer.WriteIxiVarInt(msg_id);
                                    writer.WriteIxiVarInt(next_tx_count);

                                    for (int j = 0; j < next_tx_count && i < tx_count; j++)
                                    {
                                        long in_rollback_pos  = reader.BaseStream.Position;
                                        long out_rollback_len = mOut.Length;

                                        i++;

                                        if (m.Position == m.Length)
                                        {
                                            break;
                                        }

                                        int    txid_len = (int)reader.ReadIxiVarUInt();
                                        byte[] txid     = reader.ReadBytes(txid_len);

                                        Transaction tx = TransactionPool.getUnappliedTransaction(txid);
                                        if (tx == null)
                                        {
                                            tx = TransactionPool.getAppliedTransaction(txid);
                                            if (tx == null)
                                            {
                                                Logging.warn("I do not have txid '{0}.", Transaction.txIdV8ToLegacy(txid)); // convert to string
                                                continue;
                                            }
                                        }

                                        byte[] tx_bytes = tx.getBytes();
                                        byte[] tx_len   = IxiVarInt.GetIxiVarIntBytes(tx_bytes.Length);
                                        writer.Write(tx_len);
                                        writer.Write(tx_bytes);

                                        if (mOut.Length > CoreConfig.maxMessageSize)
                                        {
                                            reader.BaseStream.Position = in_rollback_pos;
                                            mOut.SetLength(out_rollback_len);
                                            i--;
                                            break;
                                        }
                                    }
                                }
                                endpoint.sendData(ProtocolMessageCode.transactionsChunk2, mOut.ToArray(), null, 0, MessagePriority.high);
                            }
                        }
                    }
                }
            }
예제 #3
0
        /// <summary>
        ///  Prepares and sends an Ixian protocol 'Hello' message to the specified remote endpoint.
        /// </summary>
        /// <remarks>
        ///  A valid Ixian 'Hello' message includes certain Node data, verified by a public-key signature, which this function prepares using
        ///  the primary wallet's keypair. If this message is a reply to the other endpoint's hello message, then
        /// </remarks>
        /// <param name="endpoint">Remote endpoint to send the message to.</param>
        /// <param name="sendHelloData">True if the message is the first hello sent to the remote node, false if it is a reply to the challenge.</param>
        /// <param name="challenge_response">Response byte-field to the other node's hello challenge</param>
        public static void sendHelloMessageV6(RemoteEndpoint endpoint, bool sendHelloData, int challenge)
        {
            using (MemoryStream m = new MemoryStream(1856))
            {
                using (BinaryWriter writer = new BinaryWriter(m))
                {
                    string publicHostname = IxianHandler.getFullPublicAddress();

                    // Send the node version
                    writer.WriteIxiVarInt(6);

                    // Send the public node address
                    byte[] address = IxianHandler.getWalletStorage().getPrimaryAddress();
                    writer.WriteIxiVarInt(address.Length);
                    writer.Write(address);

                    // Send the testnet designator
                    writer.Write(IxianHandler.isTestNet);

                    char node_type = PresenceList.myPresenceType;
                    writer.Write(node_type);

                    // Send the version
                    writer.Write(CoreConfig.productVersion);

                    // Send the node device id
                    writer.WriteIxiVarInt(CoreConfig.device_id.Length);
                    writer.Write(CoreConfig.device_id);

                    // Send the wallet public key
                    writer.WriteIxiVarInt(IxianHandler.getWalletStorage().getPrimaryPublicKey().Length);
                    writer.Write(IxianHandler.getWalletStorage().getPrimaryPublicKey());

                    // Send listening port
                    writer.WriteIxiVarInt(IxianHandler.publicPort);

                    // Send timestamp
                    long timestamp = Clock.getTimestamp() + endpoint.calculateTimeDifference();
                    writer.WriteIxiVarInt(timestamp);

                    // generate signature
                    using (MemoryStream mSig = new MemoryStream(1024))
                    {
                        using (BinaryWriter sigWriter = new BinaryWriter(mSig))
                        {
                            sigWriter.Write(ConsensusConfig.ixianChecksumLock);
                            sigWriter.Write(CoreConfig.device_id);
                            sigWriter.Write(timestamp);
                            sigWriter.Write(publicHostname);
                            sigWriter.Write(challenge);
                        }
                        byte[] signature = CryptoManager.lib.getSignature(mSig.ToArray(), IxianHandler.getWalletStorage().getPrimaryPrivateKey());
                        writer.WriteIxiVarInt(signature.Length);
                        writer.Write(signature);
                    }

                    if (sendHelloData)
                    {
                        Block block = IxianHandler.getLastBlock();
                        if (block == null)
                        {
                            Logging.warn("Clients are connecting, but we have no blocks yet to send them!");
                            sendBye(endpoint, ProtocolByeCode.notReady, string.Format("The node isn't ready yet, please try again later."), "", true);
                            return;
                        }


                        writer.WriteIxiVarInt(block.blockNum);

                        writer.WriteIxiVarInt(block.blockChecksum.Length);
                        writer.Write(block.blockChecksum);

                        writer.WriteIxiVarInt(block.version);

                        writer.Write(endpoint.getFullAddress(true));

#if TRACE_MEMSTREAM_SIZES
                        Logging.info(String.Format("CoreProtocolMessage::sendHelloMessage: {0}", m.Length));
#endif

                        endpoint.sendData(ProtocolMessageCode.helloData, m.ToArray());
                    }
                    else
                    {
                        byte[] challenge_bytes = IxiVarInt.GetIxiVarIntBytes(challenge);
                        endpoint.challenge = BitConverter.GetBytes(challenge);
                        writer.Write(challenge_bytes);

#if TRACE_MEMSTREAM_SIZES
                        Logging.info(String.Format("CoreProtocolMessage::sendHelloMessage: {0}", m.Length));
#endif

                        endpoint.sendData(ProtocolMessageCode.hello, m.ToArray());
                    }
                }
            }
        }