public static void ValidateBlock(Block block) { // first validate the Nonce matches the difficulty mask string mineHash = Sha256Hash.Hash(BitConverter.GetBytes(block.Nonce), block.PreviousBlockHash); if (!Regex.IsMatch(mineHash, block.DifficultyMask)) { throw new Exception("Nonce does not match difficulty mask"); } for (int i = 0; i < block.Transactions.Count; i++) { Transaction t = block.Transactions[i]; TransactionValidatorService.ValidateTransaction(t); } }
public static void ValidateTransaction(Transaction transaction) { bool isCoinbase = transaction.Inputs.Count == 0; decimal totalInput = 0, totalOutput = 0; // verify the inputs are able to be spent with the public key the transaction is signed with for (int i = 0; i < transaction.Inputs.Count; i++) { TransactionInput txIn = transaction.Inputs[i]; Transaction lastTxInTrans = TransactionFactory.TransactionFromTxInput(txIn); TransactionOutput lastTxInOutput = lastTxInTrans.Outputs.ElementAt((int)txIn.PreviousTransactionOutIndex); if (!transaction.VerifySignature(lastTxInOutput.To)) { throw new Exception("Transaction sign chain is invalid"); } TransactionValidatorService.ValidateTransaction(lastTxInTrans); totalInput += lastTxInOutput.Amount; } if (isCoinbase) { if (transaction.Inputs.Count != 1 && transaction.Outputs.Count != 1) { throw new Exception("Coinbase transaction must have one input and one output"); } return; } for (int i = 0; i < transaction.Outputs.Count; i++) { TransactionOutput txOut = transaction.Outputs[i]; totalOutput += txOut.Amount; } if (!isCoinbase && totalOutput > totalInput) { throw new Exception("Output must not exceed input"); } }