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