private void BeforeSave(CurrencyBlock block) { foreach (var transaction in block.Transactions) { transaction.Hash = HashProvider.ComputeHashBytes(transaction); } block.Hash = block.ToHashBytes(HashProvider); }
public bool CheckBlock(CurrencyBlock newBlock, CurrencyBlock previousBlock) { var blockHash = newBlock.ToHashBytes(_hashProvider); if (previousBlock.Index + 1 != newBlock.Index) { // Check if the block is the last one var message = $"Invalid index: expected '{previousBlock.Index + 1}' but got '{newBlock.Index}'"; _logger?.LogError(message); throw new BlockAssertionException(message); } if (previousBlock.Hash != newBlock.PreviousHash) { // Check if the previous block is correct var message = $"Invalid previoushash: expected '{previousBlock.Hash}' got '{newBlock.PreviousHash}'"; _logger?.LogError(message); throw new BlockAssertionException(message); } if (blockHash != newBlock.Hash) { // Check if the hash is correct var message = $"Invalid hash: expected '{blockHash}' got '{newBlock.Hash}'"; throw new BlockAssertionException(message); } if (newBlock.GetDifficulty() >= GetDifficulty(newBlock.Index ?? 0)) { // If the difficulty level of the proof-of-work challenge is correct var message = $"Invalid proof-of-work difficulty: expected '{newBlock.GetDifficulty()}' to be smaller than '{GetDifficulty(newBlock.Index ?? 0)}'"; _logger?.LogError(message); throw new BlockAssertionException(message); } // For each transaction in this block, check if it is valid foreach (var transaction in newBlock.Transactions) { CheckTransaction(transaction); } // Check if the sum of output transactions are equal the sum of input transactions + the reward for the block miner { var sumOfInputsAmount = newBlock.Transactions.SelectMany(x => x.Data.Inputs).Select(x => x.Amount).Sum(); var sumOfOutputsAmount = newBlock.Transactions.SelectMany(x => x.Data.Outputs).Select(x => x.Amount).Sum(); if (sumOfInputsAmount < sumOfOutputsAmount) { var message = $"Invalid block balance: inputs sum '{sumOfInputsAmount}', outputs sum '{sumOfOutputsAmount}'"; _logger?.LogError(message); throw new BlockAssertionException(message); } } // Check if there is only 1 fee transaction and 1 reward transaction { var feeTransactions = newBlock.Transactions.Count(x => x.Type == TransactionType.Fee); if (feeTransactions > 1) { var message = $"Invalid fee transaction count: expected '1' got '${feeTransactions}'"; _logger?.LogError(message); throw new BlockAssertionException(message); } var rewardTransactions = newBlock.Transactions.Count(x => x.Type == TransactionType.Reward); if (rewardTransactions > 1) { var message = $"Invalid reward transaction count: expected '1' got '${rewardTransactions}'"; _logger?.LogError(message); throw new BlockAssertionException(message); } } return(true); }