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();
            }
        }
Beispiel #3
0
        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();
        }