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); } }
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(); } }
static void Main(string[] args) { var startTime = DateTime.Now; //var wBank = new WalletBank(); //for (var i = 0; i < 100; i++) wBank.CreateWallet(); //foreach (var wallet in wBank) //{ // var isOk = wallet.VerifyAddress(wallet.Address); // Console.WriteLine(isOk); //} //var blockChain = new BlockChain(); //blockChain.Print(); //var txList = new List<Transaction>(); //for(var i = 0; i<10000; i++) { //Transaction tx1 = new Transaction() //{ // Id = null, // Inputs = new List<TxInput>() // { // new TxInput() { // Id = new byte[] {}, // PubKey = new byte[]{0x01}, // Out = i // } // } , // Outputs = new List<TxOutput>() { new TxOutput() // { // Value = i, // } } //}; //tx1.CalculateHash(); // txList.Add(tx1); //} //var merkleTree = new MerkleTree(txList); //merkleTree.LevelOrder(); var list = new List <Transaction>(); var bank = new WalletBank(); var _loggedUserWallet = bank.FindWallet("112H2TcYAvxWGPSWXz4bzGvm5RXEdFDCms"); var _friChain = new BlockChain("x"); var utxoSet = new UTXOSet(_friChain); for (int i = 0; i < 20; i++) { var tx = Transaction.NewTransaction("112H2TcYAvxWGPSWXz4bzGvm5RXEdFDCms", "1fp9JwtnMMnYVLaABMEQuKGtpXUnJm7Cz", 2, utxoSet); if (tx == null) { return; } list.Add(tx); } var block = _friChain.MineBlock(list); utxoSet.Update(block); _friChain.GetBalance("112H2TcYAvxWGPSWXz4bzGvm5RXEdFDCms"); var endTime = DateTime.Now; Console.WriteLine($"Duration: {endTime - startTime}"); Console.Read(); }