Я застрял с некоторой логикой c в моей криптовалюте шутки, почему мой метод майнинга делает мою цепочку недействительной? - PullRequest
0 голосов
/ 18 апреля 2020

Когда я проверяю действительность моего блокчейна после майнинга, я получаю неверную цепочку. Я думаю, что это может быть проблема с моими методами майнинга, а не методом verifyChain, но я не уверен.

класс блока

public class Block
    {
        public string Hash { get; set; }
        public string PreviousHash { get; set; }
        public List<Transaction> Transactions {get; set;}
        private DateTime _timestamp;
        private long _nonce;

        public Block(DateTime timestamp, List<Transaction> transactions, string previousHash = "")
        {
            _timestamp = timestamp;
            _nonce = 0;
            Transactions = transactions;
            PreviousHash = previousHash;
            Hash = GenerateHash();

        }

        public void MineBlock(int proofOfWorkDifficulty)
        {
            string hashValidationTemplate = new String('0', proofOfWorkDifficulty);

            while (Hash.Substring(0, proofOfWorkDifficulty) != hashValidationTemplate)
            {
                _nonce++;
                 Hash = GenerateHash();
            }
            Console.WriteLine("Blocked with HASH={0} successfully mined!", Hash);
        }

        public string GenerateHash()
        {
            string hashString = PreviousHash + Transactions + _timestamp + _nonce; ;

            using (SHA256 sha256Hash = SHA256.Create())
            {
                byte[] bytes = sha256Hash.ComputeHash(Encoding.UTF8.GetBytes(hashString));

                // Convert byte array to a string   
                StringBuilder builder = new StringBuilder();
                for (int i = 0; i < bytes.Length; i++)
                {
                    builder.Append(bytes[i].ToString("x2"));
                }
                return builder.ToString();
            }
        }
    }

транзакция класс


    public class Transaction
    {
        public string Sender { get; set; }
        public string Receiver { get; set; }
        public double Amount { get; set; }
        public DateTime Timestamp { get; set; }

        public Transaction(string sender, string receiver, double amount)
        {
            this.Sender = sender;
            this.Receiver = receiver;
            this.Amount = amount;
            this.Timestamp = DateTime.Now;

        }

    }

блокчейн-класс Редактирование: изменен метод MineBlock () - теперь я получаю больше проходов, но все равно получаю ошибку, где Я не должен быть

    public class Blockchain
    {
        private readonly int _difficulty;
        private readonly double _rewardAmount;
        public List<Block> Blocks { get; set; }
        private List<Transaction> Transactions { get; set; }

        public Blockchain(int difficulty, int rewardAmount)
        {
            _difficulty = difficulty;
            _rewardAmount = rewardAmount;
            Transactions = new List<Transaction>();
            Blocks = new List<Block> { CreateGenesisBlock() };

            // SOME KIND OF NODES LIST BELONGS HERE?

            //Socket IO? something to emit to other nodes?
        }


        public Block GetLastBlock()
        {
            return this.Blocks[this.Blocks.Count - 1];
        }

        public long GetChainLength()
        {
            return this.Blocks.Count;
        }

        public void NewTransaction(Transaction transaction)
        {
            this.Transactions.Add(transaction);
        }

        public bool VerifyChain()
        {
            Block previousBlock = Blocks[0];

            for (int i = 1; i < Blocks.Count; i++)
            {
                Block currentBlock = Blocks[i];
                var testHashCurrentBlock = currentBlock.GenerateHash();
                var testHashPreviousBlock = previousBlock.GenerateHash();

                if (currentBlock.PreviousHash != previousBlock.GenerateHash())
                {
                    return false;
                }
                previousBlock = currentBlock;
            }
            return true;
        }

          public void MineBlock(string minerAddress)
        {
            Transaction minerRewardTransaction = new Transaction(null, minerAddress, _rewardAmount);
            NewTransaction(minerRewardTransaction);
            Block block = new Block(DateTime.Now, Transactions);
            block.MineBlock(_difficulty);
            block.PreviousHash = Blocks.Last().Hash;
            VerifyChain();
            Blocks.Add(block);

            Transactions = new List<Transaction>();
        }

        public double GetBalance(string address)
        {
            double balance = 0;

            foreach(Block block in Blocks)
            {
                foreach(Transaction transaction in block.Transactions)
                {
                    if (transaction.Sender == address)
                    {
                        balance -= transaction.Amount;
                    }
                    if(transaction.Receiver == address)
                    {
                        balance += transaction.Amount;
                    }
                }
            }
            return balance;
        }

        private Block CreateGenesisBlock()
        {
            List<Transaction> transactions = new List<Transaction> { new Transaction("", "", 0) };
            return new Block(DateTime.Now, transactions, "0");
        }


    }

program.cs
в этом первом тесте проверки проходов цепи, но после майнинга я получить сбой

        static void Main(String []args)
        {

            const string minerAddress = "miner1";
            const string user1Address = "A";
            const string user2Address = "B";
            Blockchain blockChain = new Blockchain(2, 10);
            blockChain.NewTransaction(new Transaction(user1Address, user2Address, 200));
            blockChain.NewTransaction(new Transaction(user2Address, user1Address, 10));
            Console.WriteLine("Is valid: {0}", blockChain.VerifyChain());
            Console.WriteLine();
            Console.WriteLine("--------- Start mining ---------");
            blockChain.MineBlock(minerAddress);
            Console.WriteLine("after MineBlock()");
            Console.WriteLine(blockChain.Blocks.ToString());
            Console.WriteLine("Is valid: {0}", blockChain.VerifyChain());
            Console.WriteLine("BALANCE of the miner: {0}", blockChain.GetBalance(minerAddress));
            blockChain.NewTransaction(new Transaction(user1Address, user2Address, 5));
            Console.WriteLine("Is valid: {0}", blockChain.VerifyChain());
        }

...