static void handleInventory2(byte[] data, RemoteEndpoint endpoint) { using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { ulong item_count = reader.ReadIxiVarUInt(); if (item_count > (ulong)CoreConfig.maxInventoryItems) { Logging.warn("Received {0} inventory items, max items is {1}", item_count, CoreConfig.maxInventoryItems); item_count = (ulong)CoreConfig.maxInventoryItems; } ulong last_block_height = IxianHandler.getLastBlockHeight(); Dictionary <ulong, List <InventoryItemSignature> > sig_lists = new Dictionary <ulong, List <InventoryItemSignature> >(); List <InventoryItemKeepAlive> ka_list = new List <InventoryItemKeepAlive>(); List <byte[]> tx_list = new List <byte[]>(); bool request_next_block = false; for (ulong i = 0; i < item_count; i++) { ulong len = reader.ReadIxiVarUInt(); byte[] item_bytes = reader.ReadBytes((int)len); InventoryItem item = InventoryCache.decodeInventoryItem(item_bytes); if (item.type == InventoryItemTypes.transaction) { PendingTransactions.increaseReceivedCount(item.hash, endpoint.presence.wallet); } PendingInventoryItem pii = Node.inventoryCache.add(item, endpoint); if (!pii.processed && pii.lastRequested == 0) { // first time we're seeing this inventory item switch (item.type) { case InventoryItemTypes.keepAlive: ka_list.Add((InventoryItemKeepAlive)item); pii.lastRequested = Clock.getTimestamp(); break; case InventoryItemTypes.transaction: tx_list.Add(item.hash); pii.lastRequested = Clock.getTimestamp(); break; case InventoryItemTypes.blockSignature: var iis = (InventoryItemSignature)item; if (iis.blockNum < last_block_height - 5 && iis.blockNum > last_block_height + 6) { continue; } if (!sig_lists.ContainsKey(iis.blockNum)) { sig_lists.Add(iis.blockNum, new List <InventoryItemSignature>()); } sig_lists[iis.blockNum].Add(iis); pii.lastRequested = Clock.getTimestamp(); break; case InventoryItemTypes.block: var iib = ((InventoryItemBlock)item); if (iib.blockNum <= last_block_height) { Node.inventoryCache.processInventoryItem(pii); } else { pii.lastRequested = Clock.getTimestamp(); request_next_block = true; if (iib.blockNum > endpoint.blockHeight) { endpoint.blockHeight = iib.blockNum; } if (iib.blockNum > Node.blockProcessor.highestNetworkBlockNum) { Node.blockProcessor.highestNetworkBlockNum = iib.blockNum; } } break; default: Node.inventoryCache.processInventoryItem(pii); break; } } } PresenceProtocolMessages.broadcastGetKeepAlives(ka_list, endpoint); if (Node.blockSync.synchronizing) { return; } TransactionProtocolMessages.broadcastGetTransactions(tx_list, 0, endpoint); if (request_next_block) { byte include_tx = 2; if (Node.isMasterNode()) { include_tx = 0; } BlockProtocolMessages.broadcastGetBlock(last_block_height + 1, null, endpoint, include_tx, true); } foreach (var sig_list in sig_lists) { SignatureProtocolMessages.broadcastGetSignatures(sig_list.Key, sig_list.Value, endpoint); } } } }
public static void handleGetBlock3(byte[] data, RemoteEndpoint endpoint) { if (!Node.isMasterNode()) { Logging.warn("Block data was requested, but this node isn't a master node"); return; } if (Node.blockSync.synchronizing) { return; } using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { ulong block_number = reader.ReadIxiVarUInt(); byte include_transactions = reader.ReadByte(); bool full_header = false; try { full_header = reader.ReadBoolean(); } catch (Exception) { } //Logging.info(String.Format("Block #{0} has been requested.", block_number)); ulong last_block_height = IxianHandler.getLastBlockHeight() + 1; if (block_number > last_block_height) { return; } Block block = null; if (block_number == last_block_height) { bool haveLock = false; try { Monitor.TryEnter(Node.blockProcessor.localBlockLock, 1000, ref haveLock); if (!haveLock) { throw new TimeoutException(); } Block tmp = Node.blockProcessor.getLocalBlock(); if (tmp != null && tmp.blockNum == last_block_height) { block = tmp; } } finally { if (haveLock) { Monitor.Exit(Node.blockProcessor.localBlockLock); } } } else { block = Node.blockChain.getBlock(block_number, Config.storeFullHistory); } if (block == null) { Logging.warn("Unable to find block #{0} in the chain!", block_number); return; } //Logging.info(String.Format("Block #{0} ({1}) found, transmitting...", block_number, Crypto.hashToString(block.blockChecksum.Take(4).ToArray()))); // Send the block if (include_transactions == 1) { TransactionProtocolMessages.handleGetBlockTransactions3(block_number, false, endpoint); } else if (include_transactions == 2) { TransactionProtocolMessages.handleGetBlockTransactions3(block_number, true, endpoint); } if (!Node.blockProcessor.verifySigFreezedBlock(block)) { Logging.warn("Sigfreezed block {0} was requested. but we don't have the correct sigfreeze!", block.blockNum); } bool frozen_sigs_only = true; if (block_number + 5 > IxianHandler.getLastBlockHeight()) { if (block.getFrozenSignatureCount() < Node.blockChain.getRequiredConsensus(block_number)) { frozen_sigs_only = false; } } endpoint.sendData(ProtocolMessageCode.blockData, block.getBytes(full_header, frozen_sigs_only), BitConverter.GetBytes(block.blockNum), 0, MessagePriority.high); } } }
// Unified protocol message parsing public static void parseProtocolMessage(ProtocolMessageCode code, byte[] data, RemoteEndpoint endpoint) { if (endpoint == null) { Logging.error("Endpoint was null. parseProtocolMessage"); return; } try { switch (code) { case ProtocolMessageCode.hello: handleHello(data, endpoint); break; case ProtocolMessageCode.helloData: handleHelloData(data, endpoint); break; case ProtocolMessageCode.getBlock: BlockProtocolMessages.handleGetBlock(data, endpoint); break; case ProtocolMessageCode.getBalance: WalletStateProtocolMessages.handleGetBalance(data, endpoint); break; case ProtocolMessageCode.getTransaction: TransactionProtocolMessages.handleGetTransaction(data, endpoint); break; case ProtocolMessageCode.getTransaction2: TransactionProtocolMessages.handleGetTransaction2(data, endpoint); break; case ProtocolMessageCode.getTransaction3: TransactionProtocolMessages.handleGetTransaction3(data, endpoint); break; case ProtocolMessageCode.newTransaction: case ProtocolMessageCode.transactionData: TransactionProtocolMessages.handleTransactionData(data, endpoint); break; case ProtocolMessageCode.bye: CoreProtocolMessage.processBye(data, endpoint); break; case ProtocolMessageCode.newBlock: case ProtocolMessageCode.blockData: BlockProtocolMessages.handleBlockData(data, endpoint); break; case ProtocolMessageCode.syncWalletState: WalletStateProtocolMessages.handleSyncWalletState(data, endpoint); break; case ProtocolMessageCode.walletState: WalletStateProtocolMessages.handleWalletState(data, endpoint); break; case ProtocolMessageCode.getWalletStateChunk: WalletStateProtocolMessages.handleGetWalletStateChunk(data, endpoint); break; case ProtocolMessageCode.walletStateChunk: WalletStateProtocolMessages.handleWalletStateChunk(data, endpoint); break; case ProtocolMessageCode.updatePresence: PresenceProtocolMessages.handleUpdatePresence(data, endpoint); break; case ProtocolMessageCode.keepAlivePresence: PresenceProtocolMessages.handleKeepAlivePresence(data, endpoint); break; case ProtocolMessageCode.getPresence: PresenceProtocolMessages.handleGetPresence(data, endpoint); break; case ProtocolMessageCode.getPresence2: PresenceProtocolMessages.handleGetPresence2(data, endpoint); break; case ProtocolMessageCode.getKeepAlives: PresenceProtocolMessages.handleGetKeepAlives(data, endpoint); break; case ProtocolMessageCode.keepAlivesChunk: PresenceProtocolMessages.handleKeepAlivesChunk(data, endpoint); break; // return 10 random presences of the selected type case ProtocolMessageCode.getRandomPresences: PresenceProtocolMessages.handleGetRandomPresences(data, endpoint); break; case ProtocolMessageCode.getUnappliedTransactions: TransactionProtocolMessages.handleGetUnappliedTransactions(data, endpoint); break; case ProtocolMessageCode.blockTransactionsChunk: BlockProtocolMessages.handleBlockTransactionsChunk(data, endpoint); break; case ProtocolMessageCode.attachEvent: NetworkEvents.handleAttachEventMessage(data, endpoint); break; case ProtocolMessageCode.detachEvent: NetworkEvents.handleDetachEventMessage(data, endpoint); break; case ProtocolMessageCode.blockSignature: SignatureProtocolMessages.handleBlockSignature(data, endpoint); break; case ProtocolMessageCode.getBlockSignatures: { using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { ulong block_num = reader.ReadUInt64(); int checksum_len = reader.ReadInt32(); byte[] checksum = reader.ReadBytes(checksum_len); SignatureProtocolMessages.handleGetBlockSignatures(block_num, checksum, endpoint); } } } break; case ProtocolMessageCode.blockSignatures: SignatureProtocolMessages.handleSigfreezedBlockSignatures(data, endpoint); break; case ProtocolMessageCode.getNextSuperBlock: BlockProtocolMessages.handleGetNextSuperBlock(data, endpoint); break; case ProtocolMessageCode.getBlockHeaders: BlockProtocolMessages.handleGetBlockHeaders(data, endpoint); break; case ProtocolMessageCode.getPIT: BlockProtocolMessages.handleGetPIT(data, endpoint); break; case ProtocolMessageCode.inventory: handleInventory(data, endpoint); break; case ProtocolMessageCode.inventory2: handleInventory2(data, endpoint); break; case ProtocolMessageCode.getSignatures: SignatureProtocolMessages.handleGetSignatures(data, endpoint); break; case ProtocolMessageCode.signaturesChunk: SignatureProtocolMessages.handleSignaturesChunk(data, endpoint); break; case ProtocolMessageCode.getTransactions: TransactionProtocolMessages.handleGetTransactions(data, endpoint); break; case ProtocolMessageCode.getTransactions2: TransactionProtocolMessages.handleGetTransactions2(data, endpoint); break; case ProtocolMessageCode.transactionsChunk: TransactionProtocolMessages.handleTransactionsChunk(data, endpoint); break; case ProtocolMessageCode.transactionsChunk2: TransactionProtocolMessages.handleTransactionsChunk2(data, endpoint); break; case ProtocolMessageCode.getBlockHeaders2: BlockProtocolMessages.handleGetBlockHeaders2(data, endpoint); break; case ProtocolMessageCode.getPIT2: BlockProtocolMessages.handleGetPIT2(data, endpoint); break; case ProtocolMessageCode.getBlock2: BlockProtocolMessages.handleGetBlock2(data, endpoint); break; case ProtocolMessageCode.getBlock3: BlockProtocolMessages.handleGetBlock3(data, endpoint); break; case ProtocolMessageCode.getBalance2: WalletStateProtocolMessages.handleGetBalance2(data, endpoint); break; case ProtocolMessageCode.getBlockSignatures2: { using (MemoryStream m = new MemoryStream(data)) { using (BinaryReader reader = new BinaryReader(m)) { ulong block_num = reader.ReadIxiVarUInt(); int checksum_len = (int)reader.ReadIxiVarUInt(); byte[] checksum = reader.ReadBytes(checksum_len); SignatureProtocolMessages.handleGetBlockSignatures2(block_num, checksum, endpoint); } } } break; case ProtocolMessageCode.blockSignature2: SignatureProtocolMessages.handleBlockSignature2(data, endpoint); break; default: break; } } catch (Exception e) { Logging.error("Error parsing network message. Details: {0}", e.ToString()); } }