private void HandleBlock(CommandMessage message) { var block = new Block().DeSerialize(message.Data); logger.Debug("Recieved new block from: " + message.Client.ToString()); chain.AddBlock(block); logger.Debug("block added ID:" + Convert.ToBase64String(block.Hash) + "index: " + block.Index); BlockOnTheFly.Remove(HexadecimalEncoding.ToHexString(block.Hash)); //--progress bar if (highestIndex < block.Index) { highestIndex = block.Index; //check best index } NewBlockArrived?.Invoke(this, new ProgressBarEventArgs(highestIndex, blocksInTransit.Count, reducedBlockCount)); //invoke this, mainly for progress bar now. //--progress bar end if (blocksInTransit.Count > 0) { var blockHash = blocksInTransit[0]; SendGetData(message.Client.ToString(), "block", blockHash); BlockOnTheFly.Add(HexadecimalEncoding.ToHexString(blockHash)); blocksInTransit.RemoveAt(0); } else { if (BlockOnTheFly.Count != 0) { return; } reindexing = true; chain.ReindexUTXO(); // asynch WholeChainDownloaded?.Invoke(this, EventArgs.Empty); // invoke this after all is downloaded, cause downloading from lastest to oldest, could cause problems after displaying after each block isBusy = false; reindexing = false; ProcessNextMessage(); } }
private void MineTransactions() { miningInProgress = true; logger.Debug("Mining started"); var startTime = DateTime.Now; var txList = new List <Transaction>(); var coinBaseTx = Transaction.CoinBaseTx(_loggedUser.Address, ""); //add later coinBaseTx.Inputs[0].MagicValue = chain.GetBestHeight() + 1; coinBaseTx.MagicVK = chain.GetBestHeight() + 1; coinBaseTx.Id = coinBaseTx.CalculateHash(); txList.Add(coinBaseTx); //fill txList from TransactionPool foreach (var txPair in TransactionPool) { var tx = txPair.Value; if (chain.VerifyTransaction(tx)) { txList.Add(tx); } } if (txList.Count == 0) { logger.Debug("All txs invalid"); miningInProgress = false; return; } chain.HashDiscovered += HashDiscovered; NotifyGUIisMining(true); var newBlock = chain.MineBlock(txList); if (newBlock != null) { //skew for synch if (handlingNewBlock || (DateTime.Now - timeSkewBetweenHandlingBlock).Milliseconds < 200) { // mined same time as block came logger.Debug($"!New block mined, mining duration: {DateTime.Now - startTime} But discard it, cause handling newRemoteBlock"); miningInProgress = false; return; } NotifyGUIisMining(false); handlingNewBlock = true; logger.Debug($"New block mined, mining duration: {DateTime.Now - startTime}"); chain.AddBlock(newBlock); //30.4 var utxoSet = new UTXOSet(chain); utxoSet.Update(newBlock); // //7.4.19 if (InMemoryBlockChains.Count > 0) { logger.Debug("Find best chain"); InMemoryBlockChain bestChain = null; var count = 1; var bestIndex = chain.GetBestHeight(); foreach (var chain in InMemoryBlockChains) { var currentIndex = chain.GetLastIndex(); if (currentIndex > bestIndex) { bestIndex = currentIndex; count = 1; bestChain = chain; } else if (currentIndex == bestIndex) { count++; } } if (count == 1) { logger.Debug("Best chain found"); BreakMining();//redundant if (bestChain != null) { logger.Debug("Best chain found in subchains, restructualize chain"); //if not restruct to new one chain.RestructualizeSubchain(bestChain); InMemoryBlockChains.Clear(); //clear InMemoryChains } else { //if bestChain is null, chain stays local logger.Debug("Best chain found in localchain, do nothing"); } } else { logger.Debug("Best chain not found"); } } handlingNewBlock = false; if (IncomingMinedNewBlocksMessages.Count > 0) { ProcessMessage(IncomingMinedNewBlocksMessages.Dequeue()); } //7.4.19 //this means pow was broke chain.ReindexUTXO(); chain.HashDiscovered -= HashDiscovered; WholeChainDownloaded?.Invoke(this, EventArgs.Empty); SendNewBlockMined(newBlock); //remove txs from Transaction pool RemoveTransactionsFromPool(txList); } else { logger.Debug("block added by remote client"); //I delete txs from txpool in NewBlockMined //chain.ReindexUTXO(); } miningInProgress = false; if (TransactionPool.Count > 0) { MineTransactions(); } }
private void HandleNewBlockMined(CommandMessage rxMsg) { try { handlingNewBlock = true; PauseMining(); //pause mining if mining Block minedBlock = new Block().DeSerialize(rxMsg.Data); var transactions = minedBlock.Transactions; logger.Debug("Recieved block, somebody mined: " + Convert.ToBase64String(minedBlock.Hash)); var isValid = IsPreviousHashValid(minedBlock.PreviousHash); if (!isValid) { logger.Debug("Previous hash invalid, try add to fork subchain"); if (!VerifyTransactions(transactions)) { logger.Debug("Transactions not valid"); ResumeMining(); handlingNewBlock = false; return; } //try to add to fork chains var added = false; foreach (var memChain in InMemoryBlockChains) { if (memChain.BelongsToThisChain(minedBlock)) { added = memChain.AddBlock(minedBlock); RemoveTransactionsFromPool(minedBlock.Transactions); logger.Debug("Added to subchain"); } } if (!added) { var newForkChain = new InMemoryBlockChain(); newForkChain.AddBlock(minedBlock); InMemoryBlockChains.Add(newForkChain); logger.Debug("Created new subchain"); } PrintCurrentForkChains(InMemoryBlockChains); } else { logger.Debug("Previous hash VALID, add to local chain"); if (!VerifyTransactions(transactions)) { ResumeMining(); handlingNewBlock = false; timeSkewBetweenHandlingBlock = DateTime.Now; return; } BreakMining(); RemoveTransactionsFromPool(minedBlock.Transactions); //remove new block transactions from pool chain.AddBlock(minedBlock); //30.4 var utxoSet = new UTXOSet(chain); utxoSet.Update(minedBlock); // } if (InMemoryBlockChains.Count > 0) { logger.Debug("Find best chain"); InMemoryBlockChain bestChain = null; var count = 1; var bestIndex = chain.GetBestHeight(); //local blockchain foreach (var chain in InMemoryBlockChains) //subchains { var currentIndex = chain.GetLastIndex(); if (currentIndex > bestIndex) { bestIndex = currentIndex; count = 1; bestChain = chain; } else if (currentIndex == bestIndex) { count++; } } if (count == 1) { logger.Debug("Best chain found"); BreakMining(); if (bestChain != null) { logger.Debug("Best chain found in subchains, restructualize chain"); //if not restruct to new one chain.RestructualizeSubchain(bestChain); InMemoryBlockChains.Clear(); //clear InMemoryChains } else { //if bestChain is null, chain stays local logger.Debug("Best chain found in localchain, do nothing"); } } else { logger.Debug("Best chain not found"); } } WholeChainDownloaded?.Invoke(this, EventArgs.Empty); chain.ReindexUTXO(); // asynch handlingNewBlock = false; if (IncomingMinedNewBlocksMessages.Count > 0) { ProcessMessage(IncomingMinedNewBlocksMessages.Dequeue()); } } catch (Exception e) { logger.Error(e.Message); logger.Error(e.StackTrace); } }