private bool requestBlockAgain(ulong blockNum) { lock (pendingBlocks) { if (lastProcessedBlockNum == blockNum) { lastProcessedBlockTime = Clock.getTimestamp(); } if (missingBlocks != null) { if (!missingBlocks.Contains(blockNum)) { Logging.info(String.Format("Requesting missing block #{0} again.", blockNum)); missingBlocks.Add(blockNum); missingBlocks.Sort(); requestedBlockTimes.Add(blockNum, Clock.getTimestamp() - 10); receivedAllMissingBlocks = false; return(true); } } } return(false); }
public static string getRandomMasterNodeAddress() { List <Peer> connectableList = null; lock (peerList) { long curTime = Clock.getTimestamp(); connectableList = peerList.FindAll(x => curTime - x.lastConnectAttempt > 30); if (connectableList != null && connectableList.Count > 0) { Random rnd = new Random(); Peer p = connectableList[rnd.Next(connectableList.Count)]; p.lastConnectAttempt = curTime; return(p.hostname); } } return(""); }
// Internal function that sends data through the socket protected void sendDataInternal(ProtocolMessageCode code, byte[] data, byte[] checksum) { byte[] ba = CoreProtocolMessage.prepareProtocolMessage(code, data, checksum); NetDump.Instance.appendSent(clientSocket, ba, ba.Length); try { for (int sentBytes = 0; sentBytes < ba.Length && running;) { int bytesToSendCount = ba.Length - sentBytes; if (bytesToSendCount > 8000) { bytesToSendCount = 8000; } int curSentBytes = clientSocket.Send(ba, sentBytes, bytesToSendCount, SocketFlags.None); lastDataSentTime = Clock.getTimestamp(); // Sleep a bit to allow other threads to do their thing Thread.Yield(); sentBytes += curSentBytes; // TODO TODO TODO timeout } if (clientSocket.Connected == false) { if (running) { Logging.warn(String.Format("sendRE: Failed senddata to remote endpoint {0}, Closing.", getFullAddress())); } state = RemoteEndpointState.Closed; } } catch (Exception e) { if (running) { Logging.warn(String.Format("sendRE: Socket exception for {0}, closing. {1}", getFullAddress(), e)); } state = RemoteEndpointState.Closed; } }
public long getTimeSinceLastBLock() { return(Clock.getTimestamp() - lastBlockReceivedTime); }
public bool appendBlock(Block b, bool add_to_storage = true) { lock (blocks) { if (blocks.Count > 0) { Block prev_block = blocks[blocks.Count - 1]; // check for invalid block appending if (b.blockNum != prev_block.blockNum + 1) { Logging.warn(String.Format("Attempting to add non-sequential block #{0} after block #{1}.", b.blockNum, prev_block.blockNum)); return(false); } if (!b.lastBlockChecksum.SequenceEqual(prev_block.blockChecksum)) { Logging.error(String.Format("Attempting to add a block #{0} with invalid lastBlockChecksum!", b.blockNum)); return(false); } if (b.signatureFreezeChecksum != null && blocks.Count > 5 && !blocks[blocks.Count - 5].calculateSignatureChecksum().SequenceEqual(b.signatureFreezeChecksum)) { Logging.error(String.Format("Attempting to add a block #{0} with invalid sigFreezeChecksum!", b.blockNum)); return(false); } } lastBlock = b; lastBlockNum = b.blockNum; if (b.version != lastBlockVersion) { lastBlockVersion = b.version; } if (b.lastSuperBlockChecksum != null || b.blockNum == 1) { pendingSuperBlocks.Remove(b.blockNum); lastSuperBlockNum = b.blockNum; lastSuperBlockChecksum = b.blockChecksum; } // special case when we are starting up and have an empty chain if (blocks.Count == 0) { blocks.Add(b); lock (blocksDictionary) { blocksDictionary.Add(b.blockNum, b); } Node.storage.insertBlock(b); return(true); } blocks.Add(b); lock (blocksDictionary) { blocksDictionary.Add(b.blockNum, b); } if (reorgBlockStart <= b.blockNum) { reorgBlockStart = 0; } } if (add_to_storage) { // Add block to storage Node.storage.insertBlock(b); } ConsensusConfig.redactedWindowSize = ConsensusConfig.getRedactedWindowSize(b.version); ConsensusConfig.minRedactedWindowSize = ConsensusConfig.getRedactedWindowSize(b.version); redactChain(); lock (blocks) { if (blocks.Count > 30) { Block tmp_block = getBlock(b.blockNum - 30); if (tmp_block != null) { TransactionPool.compactTransactionsForBlock(tmp_block); tmp_block.compact(); } } compactBlockSigs(b); } // Cleanup transaction pool TransactionPool.performCleanup(); lastBlockReceivedTime = Clock.getTimestamp(); return(true); }
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) { ulong blockNum = entry.Key; // Check if the request expired (after 10 seconds) if (currentTime - requestedBlockTimes[blockNum] > 10) { // Re-request block if (ProtocolMessage.broadcastGetBlock(blockNum, null, null, 1, true) == false) { if (watchDogBlockNum > 0 && (blockNum == watchDogBlockNum - 4 || blockNum == watchDogBlockNum + 1)) { watchDogTime = DateTime.UtcNow; } 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) { 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) { 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 (ProtocolMessage.broadcastGetBlock(blockNum, null, null, 1, true) == false) { if (watchDogBlockNum > 0 && (blockNum == watchDogBlockNum - 4 || blockNum == watchDogBlockNum + 1)) { watchDogTime = DateTime.UtcNow; } 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); }
public void start(Socket socket = null) { if (fullyStopped) { Logging.error("Can't start a fully stopped RemoteEndpoint"); return; } if (running) { return; } if (socket != null) { clientSocket = socket; } if (clientSocket == null) { Logging.error("Could not start NetworkRemoteEndpoint, socket is null"); return; } prepareSocket(clientSocket); remoteIP = (IPEndPoint)clientSocket.RemoteEndPoint; address = remoteIP.Address.ToString(); fullAddress = address + ":" + remoteIP.Port; presence = null; presenceAddress = null; lock (subscribedAddresses) { subscribedAddresses.Clear(); } lastDataReceivedTime = Clock.getTimestamp(); lastDataSentTime = Clock.getTimestamp(); state = RemoteEndpointState.Established; timeDifference = 0; timeSyncComplete = false; timeSyncs.Clear(); running = true; // Abort all related threads if (recvThread != null) { recvThread.Abort(); recvThread = null; } if (sendThread != null) { sendThread.Abort(); sendThread = null; } if (parseThread != null) { parseThread.Abort(); parseThread = null; } try { TLC = new ThreadLiveCheck(); // Start receive thread recvThread = new Thread(new ThreadStart(recvLoop)); recvThread.Name = "Network_Remote_Endpoint_Receive_Thread"; recvThread.Start(); // Start send thread sendThread = new Thread(new ThreadStart(sendLoop)); sendThread.Name = "Network_Remote_Endpoint_Send_Thread"; sendThread.Start(); // Start parse thread parseThread = new Thread(new ThreadStart(parseLoop)); parseThread.Name = "Network_Remote_Endpoint_Parse_Thread"; parseThread.Start(); } catch (Exception e) { Logging.error("Exception start remote endpoint: {0}", e.Message); } }
// Reads data from a socket and returns a byte array protected byte[] readSocketData() { Socket socket = clientSocket; byte[] data = null; // Check for socket availability if (socket.Connected == false) { throw new Exception("Socket already disconnected at other end"); } if (socket.Available < 1) { // Sleep a while to prevent cpu cycle waste Thread.Sleep(10); return(data); } // Read multi-packet messages // TODO: optimize this as it's not very efficient List <byte> big_buffer = new List <byte>(); bool message_found = false; try { int data_length = 0; int header_length = 43; // start byte + int32 (4 bytes) + int32 (4 bytes) + checksum (32 bytes) + header checksum (1 byte) + end byte int bytesToRead = 1; while (message_found == false && socket.Connected && running) { //int pos = bytesToRead > NetworkProtocol.recvByteHist.Length ? NetworkProtocol.recvByteHist.Length - 1 : bytesToRead; /*lock (NetworkProtocol.recvByteHist) * { * NetworkProtocol.recvByteHist[pos]++; * }*/ int byteCounter = socket.Receive(socketReadBuffer, bytesToRead, SocketFlags.None); NetDump.Instance.appendReceived(socket, socketReadBuffer, byteCounter); if (byteCounter > 0) { lastDataReceivedTime = Clock.getTimestamp(); if (big_buffer.Count > 0) { big_buffer.AddRange(socketReadBuffer.Take(byteCounter)); if (big_buffer.Count == header_length) { data_length = getDataLengthFromMessageHeader(big_buffer); if (data_length <= 0) { data_length = 0; big_buffer.Clear(); bytesToRead = 1; } } else if (big_buffer.Count == data_length + header_length) { // we have everything that we need, save the last byte and break message_found = true; } else if (big_buffer.Count < header_length) { bytesToRead = header_length - big_buffer.Count; } else if (big_buffer.Count > data_length + header_length) { Logging.error(String.Format("Unhandled edge case occured in RemoteEndPoint:readSocketData for node {0}", getFullAddress())); return(null); } if (data_length > 0) { bytesToRead = data_length + header_length - big_buffer.Count; if (bytesToRead > 8000) { bytesToRead = 8000; } } } else { if (socketReadBuffer[0] == 'X') // X is the message start byte { big_buffer.Add(socketReadBuffer[0]); bytesToRead = header_length - 1; // header length - start byte } else if (helloReceived == false) { if (socketReadBuffer[0] == 2) { readTimeSyncData(); } } } Thread.Yield(); } else { // sleep a litte while waiting for bytes Thread.Sleep(10); // TODO TODO TODO, should reset the big_buffer if a timeout occurs } } } catch (Exception e) { Logging.error(String.Format("NET: endpoint {0} disconnected {1}", getFullAddress(), e)); throw; } if (message_found) { data = big_buffer.ToArray(); } return(data); }
// Send thread protected void sendLoop() { // Prepare an special message object to use while sending, without locking up the queue messages QueueMessage active_message = new QueueMessage(); if (enableSendTimeSyncMessages) { sendTimeSyncMessages(); } int messageCount = 0; while (running) { TLC.Report(); long curTime = Clock.getTimestamp(); if (curTime - lastDataReceivedTime > CoreConfig.pingTimeout) { // haven't received any data for 10 seconds, stop running Logging.warn(String.Format("Node {0} hasn't received any data from remote endpoint for over {1} seconds, disconnecting.", getFullAddress(), CoreConfig.pingTimeout)); state = RemoteEndpointState.Closed; running = false; break; } if (curTime - lastDataSentTime > CoreConfig.pongInterval) { try { clientSocket.Send(new byte[1] { 1 }, SocketFlags.None); lastDataSentTime = curTime; continue; } catch (Exception) { state = RemoteEndpointState.Closed; running = false; break; } } bool message_found = false; lock (sendQueueMessagesHighPriority) { lock (sendQueueMessagesNormalPriority) { if ((messageCount > 0 && messageCount % 5 == 0) || (sendQueueMessagesNormalPriority.Count == 0 && sendQueueMessagesHighPriority.Count == 0)) { lock (sendQueueMessagesLowPriority) { if (sendQueueMessagesLowPriority.Count > 0) { // Pick the oldest message QueueMessage candidate = sendQueueMessagesLowPriority[0]; active_message.code = candidate.code; active_message.data = candidate.data; active_message.checksum = candidate.checksum; active_message.skipEndpoint = candidate.skipEndpoint; active_message.helperData = candidate.helperData; // Remove it from the queue sendQueueMessagesLowPriority.Remove(candidate); message_found = true; } } messageCount = 0; } if (message_found == false && ((messageCount > 0 && messageCount % 3 == 0) || sendQueueMessagesHighPriority.Count == 0)) { if (sendQueueMessagesNormalPriority.Count > 0) { // Pick the oldest message QueueMessage candidate = sendQueueMessagesNormalPriority[0]; active_message.code = candidate.code; active_message.data = candidate.data; active_message.checksum = candidate.checksum; active_message.skipEndpoint = candidate.skipEndpoint; active_message.helperData = candidate.helperData; // Remove it from the queue sendQueueMessagesNormalPriority.Remove(candidate); message_found = true; } } if (message_found == false && sendQueueMessagesHighPriority.Count > 0) { // Pick the oldest message QueueMessage candidate = sendQueueMessagesHighPriority[0]; active_message.code = candidate.code; active_message.data = candidate.data; active_message.checksum = candidate.checksum; active_message.skipEndpoint = candidate.skipEndpoint; active_message.helperData = candidate.helperData; // Remove it from the queue sendQueueMessagesHighPriority.Remove(candidate); message_found = true; } } } if (message_found) { messageCount++; // Active message set, attempt to send it sendDataInternal(active_message.code, active_message.data, active_message.checksum); if (active_message.code == ProtocolMessageCode.bye) { Thread.Sleep(500); // grace sleep to get the message through running = false; fullyStopped = true; } Thread.Sleep(1); } else { // Sleep for 10ms to prevent cpu waste Thread.Sleep(10); } } }
// Receive thread protected virtual void recvLoop() { socketReadBuffer = new byte[8192]; lastMessageStatTime = DateTime.UtcNow; while (running) { TLC.Report(); // Let the protocol handler receive and handle messages try { byte[] data = readSocketData(); if (data != null) { parseDataInternal(data, this); messagesPerSecond++; } } catch (Exception e) { if (running) { Logging.warn(string.Format("recvRE: Disconnected client {0} with exception {1}", getFullAddress(), e.ToString())); } state = RemoteEndpointState.Closed; } // Check if the client disconnected if (state == RemoteEndpointState.Closed) { running = false; break; } TimeSpan timeSinceLastStat = DateTime.UtcNow - lastMessageStatTime; if (timeSinceLastStat.TotalSeconds < 0 || timeSinceLastStat.TotalSeconds > 2) { lastMessageStatTime = DateTime.UtcNow; lastMessagesPerSecond = (int)(messagesPerSecond / timeSinceLastStat.TotalSeconds); messagesPerSecond = 0; } if (lastMessagesPerSecond < 1) { lastMessagesPerSecond = 1; } // Sleep a while to throttle the client // Check if there are too many messages // TODO TODO TODO this can be handled way better int total_message_count = NetworkQueue.getQueuedMessageCount() + NetworkQueue.getTxQueuedMessageCount(); if (total_message_count > 500) { Thread.Sleep(100 * lastMessagesPerSecond); if (messagesPerSecond == 0) { lastMessageStatTime = DateTime.UtcNow; } lastDataReceivedTime = Clock.getTimestamp(); } else if (total_message_count > 100) { Thread.Sleep(total_message_count / 10); } else { Thread.Sleep(1); } } }
private void rollForward() { bool sleep = false; ulong lowestBlockNum = getLowestBlockNum(); ulong syncToBlock = syncTargetBlockNum; if (Node.blockChain.Count > 5) { lock (pendingBlocks) { pendingBlocks.RemoveAll(x => x.blockNum < Node.blockChain.getLastBlockNum() - 5); } } lock (pendingBlocks) { // Loop until we have no more pending blocks do { ulong next_to_apply = lowestBlockNum; if (Node.blockChain.Count > 0) { next_to_apply = Node.blockChain.getLastBlockNum() + 1; } if (next_to_apply > syncToBlock) { // we have everything, clear pending blocks and break pendingBlocks.Clear(); lock (requestedBlockTimes) { requestedBlockTimes.Clear(); } break; } Block b = pendingBlocks.Find(x => x.blockNum == next_to_apply); if (b == null) { lock (requestedBlockTimes) { if (requestBlockAgain(next_to_apply)) { // the node isn't connected yet, wait a while sleep = true; } } break; } b = new Block(b); if (Node.blockChain.Count == 0 && b.blockNum > 1) { Block tmp_b = Node.blockChain.getBlock(b.blockNum - 1, true, true); if (tmp_b != null) { Node.blockChain.setLastBlockVersion(tmp_b.version); } else { Node.blockChain.setLastBlockVersion(b.version); } } if (b.version > Block.maxVersion) { Logging.error("Received block {0} with a version higher than this node can handle, discarding the block.", b.blockNum); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); Node.blockProcessor.networkUpgraded = true; sleep = true; break; } else { Node.blockProcessor.networkUpgraded = false; } if (next_to_apply > 5) { ulong targetBlock = next_to_apply - 5; Block tb = pendingBlocks.Find(x => x.blockNum == targetBlock); if (tb != null) { Block local_block = Node.blockChain.getBlock(tb.blockNum); if (local_block != null && tb.blockChecksum.SequenceEqual(local_block.blockChecksum) && Node.blockProcessor.verifyBlockBasic(tb) == BlockVerifyStatus.Valid) { if (Node.blockProcessor.verifyBlockSignatures(tb, null)) { Node.blockChain.refreshSignatures(tb, true); } else { Logging.warn("Target block " + tb.blockNum + " does not have the required consensus."); } } pendingBlocks.RemoveAll(x => x.blockNum == tb.blockNum); } } try { Logging.info("Sync: Applying block #{0}/{1}.", b.blockNum, syncToBlock); bool ignoreWalletState = true; if (b.blockNum > wsSyncConfirmedBlockNum || Config.fullStorageDataVerification) { ignoreWalletState = false; } b.powField = null; // wallet state is correct as of wsConfirmedBlockNumber, so before that we call // verify with a parameter to ignore WS tests, but do all the others BlockVerifyStatus b_status = BlockVerifyStatus.Valid; if (b.fromLocalStorage) { // TODO TODO improve this section with NodeStorage.getTransactionsInBlock once rocksdb switch happens bool missing = false; foreach (byte[] txid in b.transactions) { if (!running) { break; } Transaction t = TransactionPool.getUnappliedTransaction(txid); if (t == null) { t = Node.storage.getTransaction(txid, b.blockNum); if (t != null) { t.applied = 0; TransactionPool.addTransaction(t, true, null, Config.fullStorageDataVerification); } else { CoreProtocolMessage.broadcastGetTransaction(txid, b.blockNum); missing = true; } } } if (missing) { Logging.info("Requesting missing transactions for block {0}", b.blockNum); Thread.Sleep(100); break; } } if (b.blockNum > wsSyncConfirmedBlockNum || b.fromLocalStorage == false || Config.fullStorageDataVerification) { b_status = Node.blockProcessor.verifyBlock(b, ignoreWalletState); } else { b_status = Node.blockProcessor.verifyBlockBasic(b, false); } if (b_status == BlockVerifyStatus.Indeterminate) { if (lastProcessedBlockNum < b.blockNum) { lastProcessedBlockNum = b.blockNum; lastProcessedBlockTime = Clock.getTimestamp(); } if (Clock.getTimestamp() - lastProcessedBlockTime > ConsensusConfig.blockGenerationInterval * 2) { Logging.info("Sync: Discarding indeterminate block #{0}, due to timeout...", b.blockNum); Node.blockProcessor.blacklistBlock(b); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); } else { Logging.info("Sync: Waiting for missing transactions from block #{0}...", b.blockNum); } Thread.Sleep(100); return; } if (b_status != BlockVerifyStatus.Valid) { Logging.warn("Block #{0} {1} is invalid. Discarding and requesting a new one.", b.blockNum, Crypto.hashToString(b.blockChecksum)); Node.blockProcessor.blacklistBlock(b); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); if (b_status == BlockVerifyStatus.PotentiallyForkedBlock && b.blockNum + 7 > lastBlockToReadFromStorage) { Node.blockProcessor.handleForkedFlag(); } return; } if (!b.fromLocalStorage && !Node.blockProcessor.verifyBlockSignatures(b, null) && Node.blockChain.Count > 16) { Logging.warn("Block #{0} {1} doesn't have the required consensus. Discarding and requesting a new one.", b.blockNum, Crypto.hashToString(b.blockChecksum)); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); return; } bool sigFreezeCheck = Node.blockProcessor.verifySignatureFreezeChecksum(b, null); // Apply transactions when rolling forward from a recover file without a synced WS if (b.blockNum > wsSyncConfirmedBlockNum) { if (Node.blockChain.Count <= 5 || sigFreezeCheck) { Node.walletState.beginTransaction(b.blockNum, false); bool applied = false; try { applied = Node.blockProcessor.applyAcceptedBlock(b); if (applied) { Node.walletState.commitTransaction(b.blockNum); } }catch (Exception e) { Logging.error("Error occured during block sync, while applying/commiting transactions: " + e); } if (!applied) { Logging.warn("Error applying Block #{0} {1}. Reverting, discarding and requesting a new one.", b.blockNum, Crypto.hashToString(b.blockChecksum)); Node.walletState.revertTransaction(b.blockNum); Node.blockChain.revertBlockTransactions(b); Node.blockProcessor.blacklistBlock(b); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); return; } else { if (b.version >= BlockVer.v5 && b.lastSuperBlockChecksum == null) { // skip WS checksum check } else { if (b.lastSuperBlockChecksum != null) { byte[] wsChecksum = Node.walletState.calculateWalletStateChecksum(); if (wsChecksum == null || !wsChecksum.SequenceEqual(b.walletStateChecksum)) { Logging.error("After applying block #{0}, walletStateChecksum is incorrect!. Block's WS: {1}, actual WS: {2}", b.blockNum, Crypto.hashToString(b.walletStateChecksum), Crypto.hashToString(wsChecksum)); Node.walletState.revertTransaction(b.blockNum); Node.blockChain.revertBlockTransactions(b); Node.blockProcessor.blacklistBlock(b); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); return; } } } if (b.blockNum % Config.saveWalletStateEveryBlock == 0) { DLT.Meta.WalletStateStorage.saveWalletState(b.blockNum); } } } } else { if (syncToBlock == b.blockNum) { if (b.version >= BlockVer.v5 && b.lastSuperBlockChecksum == null) { // skip WS checksum check } else { byte[] wsChecksum = Node.walletState.calculateWalletStateChecksum(); if (wsChecksum == null || !wsChecksum.SequenceEqual(b.walletStateChecksum)) { Logging.warn("Block #{0} is last and has an invalid WSChecksum. Discarding and requesting a new one.", b.blockNum); Node.blockProcessor.blacklistBlock(b); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); return; } } } } if (Node.blockChain.Count <= 5 || sigFreezeCheck) { //Logging.info(String.Format("Appending block #{0} to blockChain.", b.blockNum)); if (b.blockNum <= wsSyncConfirmedBlockNum) { if (!TransactionPool.setAppliedFlagToTransactionsFromBlock(b)) { Node.blockChain.revertBlockTransactions(b); Node.blockProcessor.blacklistBlock(b); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); return; } } if (b.blockNum > 12 && b.blockNum + 5 >= IxianHandler.getHighestKnownNetworkBlockHeight()) { if (Node.isMasterNode() && b.blockNum > 7) { byte[][] signature_data = b.applySignature(); // applySignature() will return signature_data, if signature was applied and null, if signature was already present from before if (signature_data != null) { Node.inventoryCache.setProcessedFlag(InventoryItemTypes.blockSignature, InventoryItemSignature.getHash(signature_data[1], b.blockChecksum), true); // ProtocolMessage.broadcastNewBlock(localNewBlock); SignatureProtocolMessages.broadcastBlockSignature(signature_data[0], signature_data[1], b.blockNum, b.blockChecksum, null, null); } } } Node.blockChain.appendBlock(b, !b.fromLocalStorage); } else if (Node.blockChain.Count > 5 && !sigFreezeCheck) { if (CoreConfig.preventNetworkOperations || Config.recoverFromFile) { var last_block = lastBlocks.Find(x => x.blockNum == b.blockNum - 5); if (last_block != null) { pendingBlocks.Add(last_block); } return; } // invalid sigfreeze, waiting for the correct block Logging.warn("Block #{0} {1} doesn't have the correct sigfreezed block. Discarding and requesting a new one.", b.blockNum, Crypto.hashToString(b.blockChecksum)); pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); requestBlockAgain(b.blockNum); return; } } catch (Exception e) { Logging.error("Exception occured while syncing block #{0}: {1}", b.blockNum, e); } if (Config.enableChainReorgTest) { if (!Node.blockProcessor.chainReorgTest(b.blockNum)) { pendingBlocks.RemoveAll(x => x.blockNum + 6 < b.blockNum); } } else { pendingBlocks.RemoveAll(x => x.blockNum == b.blockNum); } Node.blockProcessor.cleanupBlockBlacklist(); } while (pendingBlocks.Count > 0 && running); } if (!sleep && Node.blockChain.getLastBlockNum() >= syncToBlock) { if (verifyLastBlock()) { sleep = false; } else { sleep = true; } } if (sleep) { Thread.Sleep(500); } }