private bool handleBlock(InventoryItem item, RemoteEndpoint endpoint) { InventoryItemBlock iib = (InventoryItemBlock)item; ulong last_block_height = IxianHandler.getLastBlockHeight(); if (iib.blockNum > last_block_height) { byte include_tx = 2; if (Node.isMasterNode()) { include_tx = 0; } BlockProtocolMessages.broadcastGetBlock(last_block_height + 1, null, endpoint, include_tx, true); if (iib.blockNum == last_block_height + 1) { return(true); } } return(false); }
// Removes event subscriptions for the provided endpoint public static void handleBlockSignature(byte[] data, RemoteEndpoint endpoint) { if (Node.blockSync.synchronizing) { return; } if (data == null) { Logging.warn(string.Format("Invalid protocol message signature data")); return; } 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); int sig_len = reader.ReadInt32(); byte[] sig = reader.ReadBytes(sig_len); int sig_addr_len = reader.ReadInt32(); byte[] sig_addr = reader.ReadBytes(sig_addr_len); ulong last_bh = IxianHandler.getLastBlockHeight(); lock (Node.blockProcessor.localBlockLock) { if (last_bh + 1 < block_num || (last_bh + 1 == block_num && Node.blockProcessor.getLocalBlock() == null)) { Logging.info("Received signature for block {0} which is missing", block_num); // future block, request the next block BlockProtocolMessages.broadcastGetBlock(last_bh + 1, null, endpoint); return; } } if (PresenceList.getPresenceByAddress(sig_addr) == null) { Logging.info("Received signature for block {0} whose signer isn't in the PL", block_num); return; } Node.inventoryCache.setProcessedFlag(InventoryItemTypes.blockSignature, InventoryItemSignature.getHash(sig_addr, checksum), true); if (Node.blockProcessor.addSignatureToBlock(block_num, checksum, sig, sig_addr, endpoint)) { Node.blockProcessor.acceptLocalNewBlock(); if (Node.isMasterNode()) { broadcastBlockSignature(sig, sig_addr, block_num, checksum, endpoint); } } else { // discard - it might have already been applied } } } }
public static void handleSigfreezedBlockSignatures(byte[] data, RemoteEndpoint endpoint) { 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); ulong last_block_height = IxianHandler.getLastBlockHeight(); Block target_block = Node.blockChain.getBlock(block_num, true); if (target_block == null) { if (block_num == last_block_height + 1) { // target block missing, request the next block Logging.warn("Target block {0} missing, requesting...", block_num); BlockProtocolMessages.broadcastGetBlock(block_num, null, endpoint); } else { // target block missing Logging.warn("Target block {0} missing", block_num); } return; } else if (!target_block.blockChecksum.SequenceEqual(checksum)) { // incorrect target block Logging.warn("Incorrect target block {0} - {1}, possibly forked", block_num, Crypto.hashToString(checksum)); return; } Block sf_block = null; if (block_num + 4 == last_block_height) { sf_block = Node.blockProcessor.getLocalBlock(); } else if (block_num + 4 > last_block_height) { Logging.warn("Sigfreezing block {0} missing", block_num + 5); return; } else { // block already sigfreezed, do nothing return; } lock (target_block) { if (sf_block != null) { if (target_block.calculateSignatureChecksum().SequenceEqual(sf_block.signatureFreezeChecksum)) { // we already have the correct sigfreeze return; } } else { // sf_block missing Logging.warn("Sigfreezing block {0} missing", block_num + 5); return; } int sig_count = reader.ReadInt32(); if (sig_count > ConsensusConfig.maximumBlockSigners) { sig_count = ConsensusConfig.maximumBlockSigners; } Block dummy_block = new Block(); dummy_block.blockNum = block_num; dummy_block.blockChecksum = checksum; dummy_block.blockProposer = sf_block.blockProposer; for (int i = 0; i < sig_count; i++) { if (m.Position == m.Length) { break; } int sig_len = reader.ReadInt32(); byte[] sig = reader.ReadBytes(sig_len); int addr_len = reader.ReadInt32(); byte[] addr = reader.ReadBytes(addr_len); Node.inventoryCache.setProcessedFlag(InventoryItemTypes.blockSignature, InventoryItemSignature.getHash(addr, checksum), true); dummy_block.addSignature(sig, addr); } Node.blockProcessor.handleSigFreezedBlock(dummy_block, endpoint); } } } }
private bool requestMissingBlocks() { if (syncDone) { return(false); } if (syncTargetBlockNum == 0) { return(false); } long currentTime = Clock.getTimestamp(); // Check if the block has already been requested lock (requestedBlockTimes) { Dictionary <ulong, long> tmpRequestedBlockTimes = new Dictionary <ulong, long>(requestedBlockTimes); foreach (var entry in tmpRequestedBlockTimes) { if (!running) { return(false); } ulong blockNum = entry.Key; // Check if the request expired (after 10 seconds) if (currentTime - requestedBlockTimes[blockNum] > 10) { // Re-request block if (BlockProtocolMessages.broadcastGetBlock(blockNum, null, null, 1, true) == false) { Logging.warn(string.Format("Failed to rebroadcast getBlock request for {0}", blockNum)); Thread.Sleep(500); } else { // Re-set the block request time requestedBlockTimes[blockNum] = currentTime; } } } } ulong syncToBlock = syncTargetBlockNum; ulong firstBlock = getLowestBlockNum(); lock (pendingBlocks) { ulong lastBlock = syncToBlock; if (missingBlocks == null) { missingBlocks = new List <ulong>(Enumerable.Range(0, (int)(lastBlock - firstBlock + 1)).Select(x => (ulong)x + firstBlock)); missingBlocks.Sort(); } int total_count = 0; int requested_count = 0; // whatever is left in missingBlocks is what we need to request if (missingBlocks.Count() == 0) { receivedAllMissingBlocks = true; return(false); } List <ulong> tmpMissingBlocks = new List <ulong>(missingBlocks.Take(maxBlockRequests * 2)); foreach (ulong blockNum in tmpMissingBlocks) { if (!running) { return(false); } total_count++; lock (requestedBlockTimes) { if (requestedBlockTimes.ContainsKey(blockNum)) { requested_count++; continue; } } bool readFromStorage = false; if (blockNum <= lastBlockToReadFromStorage) { readFromStorage = true; } ulong last_block_height = IxianHandler.getLastBlockHeight(); if (blockNum > last_block_height + (ulong)maxBlockRequests) { if (last_block_height > 0 || (last_block_height == 0 && total_count > 10)) { break; } } // First check if the missing block can be found in storage Block block = Node.blockChain.getBlock(blockNum, readFromStorage); if (block != null) { if (CoreConfig.preventNetworkOperations || Config.recoverFromFile) { if (!lastBlocks.Exists(x => x.blockNum == blockNum)) { lastBlocks.Add(new Block(block)); if (lastBlocks.Count > maxBlockRequests * 2) { lastBlocks.RemoveAt(0); } } } Node.blockSync.onBlockReceived(block, null); } else { if (readFromStorage) { Logging.warn("Expecting block {0} in storage but had to request it from network.", blockNum); } // Didn't find the block in storage, request it from the network if (BlockProtocolMessages.broadcastGetBlock(blockNum, null, null, 1, true) == false) { Logging.warn(string.Format("Failed to broadcast getBlock request for {0}", blockNum)); Thread.Sleep(500); } else { requested_count++; // Set the block request time lock (requestedBlockTimes) { requestedBlockTimes.Add(blockNum, currentTime); } } } } if (requested_count > 0) { return(true); } } return(false); }
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); } } } }