def test_transaction_update_amount_exceeds_balance(self): sender_wallet = Wallet() transaction = Transaction(sender_wallet, "richard_west", 40) # Wallet starts with the default starting balance so ensure transaction amount exceeds that. with self.assertRaises(InsufficientFundsError): transaction.update(sender_wallet, "jing_wang", 99999)
def test_invalid_reward_transaction_bad_amount(self): miner_wallet = Wallet() reward_transaction = Transaction.reward(miner_wallet) reward_transaction.output[miner_wallet.address] = 10000 with self.assertRaises(MiningRewardError): Transaction.is_valid(reward_transaction)
def test_calculate_balance(self): blockchain = Blockchain() wallet = Wallet() self.assertEqual( Wallet.calculate_balance(blockchain, wallet.address), STARTING_BALANCE ) amount = 50 transaction = Transaction(wallet, "recipient_address", amount) blockchain.add_block([transaction.serialize()]) self.assertEqual( Wallet.calculate_balance(blockchain, wallet.address), STARTING_BALANCE - amount, ) # Add some transactions where wallet receives an amount blockchain.add_block( [ Transaction(Wallet(), wallet.address, 30).serialize(), Transaction(Wallet(), wallet.address, 75).serialize(), ] ) self.assertEqual( Wallet.calculate_balance(blockchain, wallet.address), STARTING_BALANCE - amount + 30 + 75, )
def route_Wallet_Transact(): transactionData = request.get_json() transaction = transactionPool.existingTransaction(wallet.address) if not transaction: transaction = Transaction(wallet, transactionData['pollID'], transactionData['option']) pubsub.broadcastTransaction(transaction) return jsonify(transaction.toJson())
def test_contains_valid_transactions_duplicate_rewards(self): self.blockchain.add_block([ Transaction.reward(Wallet()).serialize(), Transaction.reward(Wallet()).serialize(), ]) # Block contains multiple reward transactions so we expect an exception with self.assertRaises(ContainsInvalidTransactionError): Blockchain.contains_valid_transactions(self.blockchain.chain)
def test_is_valid_bad_output_values(self): sender_wallet = Wallet() # A wallet starts with default value of 1000 recipient_address = "recipient_address" transaction = Transaction(sender_wallet, recipient_address, 100) # Replicates a sender trying to inflate own balance transaction.output[sender_wallet] = 9999 with self.assertRaises(TransactionValuesError): Transaction.is_valid(transaction)
def test_is_valid_bad_signature(self): sender_wallet = Wallet() recipient_address = "recipient_address" transaction = Transaction(sender_wallet, recipient_address, 100) # Corrupt signature. Same transaction output, but signature is from a different wallet. transaction.input["signature"] = Wallet().sign(transaction.output) with self.assertRaises(TransactionSignatureError): Transaction.is_valid(transaction)
def test_contains_valid_transactions_bad_transaction(self): bad_transaction = Transaction(Wallet(), "recipient", 1) # Use same transaction output but signed by wrong wallet bad_transaction.input["signature"] = Wallet().sign( bad_transaction.output) self.blockchain.add_block([bad_transaction.serialize()]) with self.assertRaises(TransactionSignatureError): Blockchain.contains_valid_transactions(self.blockchain.chain)
def test_reward(self): miner_wallet = Wallet() transaction = Transaction.reward(miner_wallet) self.assertEqual(transaction.input, MINING_REWARD_INPUT) self.assertEqual(transaction.output[miner_wallet.address], MINING_REWARD)
def test_transaction(self): sender_wallet = Wallet() recipient = "richard_west" amount = 100 transaction = Transaction(sender_wallet, recipient, amount) # Assert that transaction output contains the correct recipient amount self.assertEqual(transaction.output[recipient], amount) # Assert that transaction output contains the correct new/remaining balance of senders wallet self.assertEqual(transaction.output[sender_wallet.address], sender_wallet.balance - amount) # Assert a timestamp exists in the transaction input self.assertIn("timestamp", transaction.input) # Assert correct values in the transaction input self.assertEqual(transaction.input["amount"], sender_wallet.balance) self.assertEqual(transaction.input["address"], sender_wallet.address) self.assertEqual(transaction.input["public_key"], sender_wallet.public_key) # Verify the signature to ensure correctness self.assertTrue( Wallet.verify( transaction.input["public_key"], transaction.output, transaction.input["signature"], ))
def test_contains_valid_transactions_duplicate_transaction(self): transaction = Transaction(Wallet(), "recipient", 1).serialize() self.blockchain.add_block([transaction, transaction]) with self.assertRaises(ContainsInvalidTransactionError): Blockchain.contains_valid_transactions(self.blockchain.chain)
def transaction(): data = request.get_json() # Check to see if a transaction already exists in the pool for this nodes wallet. # If it does, no need to create a new transaction, just update the existing one. # This will also be broadcast to all nodes and replace the exiting transaction. transaction = transaction_pool.get_transaction_for_address(wallet.address) if transaction: transaction.update(wallet, data["recipient_address"], data["amount"]) else: transaction = Transaction(wallet, data["recipient_address"], data["amount"]) pubsub.broadcast_transaction(transaction) return jsonify(transaction.serialize())
def test_contains_valid_transactions_bad_historic_balance(self): wallet = Wallet() bad_transaction = Transaction(wallet, "recipient", 1) # Tamper with transaction, giving wallet a high amount bad_transaction.output[wallet.address] = 1000 # Ensure input amount and transaction amount are still correct so validation doesn't fail at that point bad_transaction.input["amount"] = 1001 # Re-sign wallet.sign(bad_transaction.output) self.blockchain.add_block([bad_transaction.serialize()]) with self.assertRaises(ContainsInvalidTransactionError): Blockchain.contains_valid_transactions(self.blockchain.chain)
def test_add_transaction(self): transaction_pool = TransactionPool() transaction = Transaction(Wallet(), "recipient_address", 10) transaction_pool.add_transaction(transaction) self.assertIn(transaction.id, transaction_pool.transactions) self.assertEqual(transaction_pool.transactions[transaction.id], transaction)
def mine(): # When a block is mined, add the serialized transactions from the transaction pool as it's data. transaction_data = transaction_pool.get_serialized_transactions() transaction_data.append(Transaction.reward(wallet).serialize()) transaction_data = [BlockHelper.order_dict(dict) for dict in transaction_data] blockchain.add_block(transaction_data) block = blockchain.previous_block pubsub.broadcast_block(block) transaction_pool.clear_transactions(blockchain) return jsonify(block.serialize())
def test_clear_transaction(self): transaction_pool = TransactionPool() transaction1 = Transaction(Wallet(), "recipient_address", 1) transaction2 = Transaction(Wallet(), "recipient_address", 2) transaction_pool.add_transaction(transaction1) transaction_pool.add_transaction(transaction2) blockchain = Blockchain() blockchain.add_block( [transaction1.serialize(), transaction2.serialize()]) self.assertIn(transaction1.id, transaction_pool.transactions) self.assertIn(transaction2.id, transaction_pool.transactions) transaction_pool.clear_transactions(blockchain) self.assertNotIn(transaction1.id, transaction_pool.transactions) self.assertNotIn(transaction2.id, transaction_pool.transactions)
def test_transaction_update(self): sender_wallet = Wallet() first_recipient_address = "richard_west" first_recipient_amount = 25 second_recipient_address = "jing_wang" second_recipient_amount = 25 transaction = Transaction(sender_wallet, first_recipient_address, first_recipient_amount) # Update transaction transaction.update(sender_wallet, second_recipient_address, second_recipient_amount) # Assert that transaction output contains the correct first recipient amount self.assertEqual(transaction.output[first_recipient_address], first_recipient_amount) # Assert that transaction output contains the correct second recipients amount self.assertEqual(transaction.output[second_recipient_address], second_recipient_amount) # Assert that transaction output contains the correct new/remaining balance of senders wallet self.assertEqual( transaction.output[sender_wallet.address], sender_wallet.balance - first_recipient_amount - second_recipient_amount, ) # Verify the signature to ensure correctness. This will have been resigned. self.assertTrue( Wallet.verify( transaction.input["public_key"], transaction.output, transaction.input["signature"], )) # Test sending an additional amount to the same recipient first_recipient_additional_amount = 25 transaction.update(sender_wallet, first_recipient_address, first_recipient_additional_amount) # Assert that transaction output contains the correct first recipient amount self.assertEqual( transaction.output[first_recipient_address], first_recipient_amount + first_recipient_additional_amount, ) # Assert that transaction output contains the correct new/remaining balance of senders wallet self.assertEqual( transaction.output[sender_wallet.address], sender_wallet.balance - first_recipient_amount - second_recipient_amount - first_recipient_additional_amount, ) # Verify the signature to ensure correctness. This will have been resigned. self.assertTrue( Wallet.verify( transaction.input["public_key"], transaction.output, transaction.input["signature"], ))
def setUp(self): self.blockchain = Blockchain() for i in range(4): self.blockchain.add_block( [Transaction(Wallet(), "recipient_address", i).serialize()])
def test_is_valid_reward_transaction(self): reward_transaction = Transaction.reward(Wallet()) Transaction.is_valid(reward_transaction)
def test_invalid_reward_transaction_extra_recipient(self): reward_transaction = Transaction.reward(Wallet()) reward_transaction.output["recipient_address"] = 50 with self.assertRaises(MiningRewardError): Transaction.is_valid(reward_transaction)
def test_transaction_amount_exceeds_balance(self): # Wallet starts with the default starting balance so ensure transaction amount exceeds that. with self.assertRaises(InsufficientFundsError): Transaction(Wallet(), "richard_west", 99999)
# Synchronize with the blockchain blockchain.replace(result_blockchain.chain) print("Successfully synchronized the node.") except ChainReplacementError as e: print("Error synchronizing the node - {}".format(e.message)) if ( os.environ.get("SEED") == "1" or os.environ.get("SEED") == "True" or "seed" in sys.argv ): for i in range(10): blockchain.add_block( [ Transaction( Wallet(), Wallet().address, random.randint(2, 50) ).serialize(), Transaction( Wallet(), Wallet().address, random.randint(2, 50) ).serialize(), ] ) for i in range(3): transaction_pool.add_transaction( Transaction(Wallet(), Wallet().address, random.randint(2, 50)) ) app.run(port=PORT)
def test_is_valid(self): Transaction.is_valid(Transaction(Wallet(), "recipient_address", 100))