def is_transaction_chain_valid(chain): """ Validate chain with blocks of transactions -- Only one reward per transaction. -- Each transaction must only apprear once in chain. """ transaction_ids = [] for i in range(len(chain)): block = chain[i] contains_mining_reward = False for transaction_json in block.data: transaction_obj = Transaction.from_json(transaction_json) if transaction_obj.id in transaction_ids: raise Exception( f"Transaction: {transaction_obj.id} is not unique") transaction_ids.append(transaction_obj.id) if transaction_obj.input == MINIING_REWARD_INPUT: if contains_mining_reward: raise Exception( f'Duplicate mining reward in block: {block.hash}') contains_mining_reward = True else: blockchain_tillnow = BlockChain() blockchain_tillnow.chain = chain[0:i] balance_tillnow = Wallet.calculate_balance( blockchain_tillnow, transaction_obj.input["address"]) if balance_tillnow != transaction_obj.input["amount"]: raise Exception( f"Transaction: {transaction_obj.id} has invalid input" ) Transaction.is_transaction_valid(transaction_obj)
def test_invalid_reward(): wallet = Wallet() reward = Transaction.reward(wallet) reward.output[wallet.address] = 100 with pytest.raises(Exception, match="Invalid reward transaction"): Transaction.is_transaction_valid(reward)
def test_is_transaction_valid_with_invalid_signature(): sender_wallet = Wallet() transaction = Transaction(sender_wallet, 'abcd', 50) transaction.input['signature'] = Wallet().sign(transaction.output) with pytest.raises(Exception, match="Invalid Signature"): Transaction.is_transaction_valid(transaction)
def test_is_transaction_valid_with_invalid_outputs(): sender_wallet = Wallet() transaction = Transaction(sender_wallet, 'abcd', 50) transaction.output[sender_wallet.address] = 1001 with pytest.raises( Exception, match= "Invalid transaction. Input amount and sum of output amounts doesnt match" ): Transaction.is_transaction_valid(transaction)
def test_valid_reward(): reward = Transaction.reward(Wallet()) Transaction.is_transaction_valid(reward)
def test_valid_transaction(): transaction = Transaction(Wallet(), "abcd", 20) Transaction.is_transaction_valid(transaction)