def test_is_valid_transaction_chain_duplicate_transactions(blockchain_three_blocks): transaction = Transaction(Wallet(), 'recipient', 1).to_json() blockchain_three_blocks.add_block([transaction, transaction]) with pytest.raises(Exception, match='is not unique'): Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
def test_is_valid_transaction_chain_bad_transaction(blockchain_three_blocks): bad_transaction = Transaction(Wallet(), 'recipient', 1) bad_transaction.input['signature'] = Wallet().sign(bad_transaction.output) blockchain_three_blocks.add_block([bad_transaction.to_json()]) # No exception match, in case does any of the transaction is corrupted with pytest.raises(Exception): Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
def test_is_valid_transaction_chain_multiple_rewards(blockchain_three_blocks): reward_1 = Transaction.reward_transaction(Wallet()).to_json() reward_2 = Transaction.reward_transaction(Wallet()).to_json() blockchain_three_blocks.add_block([reward_1, reward_2]) with pytest.raises(Exception, match='one mining reward per block'): Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
def test_is_valid_transaction_chain_bad_historic_balance(blockchain_three_blocks): wallet = Wallet() bad_transaction = Transaction(wallet, 'recipient', 1) bad_transaction.output[wallet.address] = 9000 bad_transaction.input['amount'] = 9001 bad_transaction.input['signature'] = wallet.sign(bad_transaction.output) blockchain_three_blocks.add_block([bad_transaction.to_json()]) with pytest.raises(Exception, match='has an invalid input amount'): Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
def test_clear_blockchain_transaction(): transaction_pool = TransactionPool() transaction_1 = Transaction(Wallet(), 'recipient', 1) transaction_2 = Transaction(Wallet(), 'recipient', 2) transaction_pool.set_transaction(transaction_1) transaction_pool.set_transaction(transaction_2) blockchain = Blockchain() blockchain.add_block([transaction_1.to_json(), transaction_2.to_json()]) assert transaction_1.id in transaction_pool.transaction_map assert transaction_2.id in transaction_pool.transaction_map transaction_pool.clear_blockchain_transactions(blockchain) assert not transaction_1.id in transaction_pool.transaction_map assert not transaction_2.id in transaction_pool.transaction_map
def test_calulate_balance(): blockchain = Blockchain() wallet = Wallet() assert Wallet.calculate_balance(blockchain, wallet.address) == STARTING_BALANCE amount = 50 transaction = Transaction(wallet, 'recipient', amount) blockchain.add_block([transaction.to_json()]) assert Wallet.calculate_balance(blockchain, wallet.address) == \ STARTING_BALANCE - amount received_amount_1 = 25 received_transaction_1 = Transaction(Wallet(), wallet.address, received_amount_1) received_amount_2 = 123 received_transaction_2 = Transaction(Wallet(), wallet.address, received_amount_2) blockchain.add_block( [received_transaction_1.to_json(), received_transaction_2.to_json()]) assert Wallet.calculate_balance(blockchain, wallet.address) == \ STARTING_BALANCE - amount + received_amount_1 + received_amount_2
import os import random import requests from flask import Flask, jsonify, request from flask_cors import CORS from backend.models.blockchain import Blockchain from backend.models.wallet import Wallet from backend.models.transaction import Transaction from backend.models.transaction_pool import TransactionPool from backend.pubsub import PubSub app = Flask(__name__) CORS(app, resources={r'/*': {'origins': 'http://*****:*****@app.route('/') def route_default(): return 'Welcome to the blockchain ;)' @app.route('/blockchain') def route_blockchain(): return jsonify(blockchain.to_json())
from backend.routes.blueprints import WALLET, BLOCKCHAIN, TRANSACTION from backend.config import PORT, ROOT_PORT app = Flask(__name__) @app.route('/') def route_default(): return 'Welcome to the blockchain ;)' app.register_blueprint(BLOCKCHAIN, url_prefix="/blockchain") app.register_blueprint(TRANSACTION, url_prefix="/transactions") app.register_blueprint(WALLET, url_prefix="/wallet") CORS(app, resources={r'/*': {'origins': 'http://localhost:3001'}}) if os.environ.get('PEER') == 'True': PORT = random.randint(5001, 6000) result = requests.get(f'http://localhost:{ROOT_PORT}/blockchain') result_blockchain = Blockchain.from_json(result.json()) try: Blockchain.replace_chain(result_blockchain.chain) print('\n -- Succesfully synchronized the local chain') except Exception as e: print(f'\n --Error synchronizing: {e}') app.run(port=PORT)
import os import random from flask import Blueprint, jsonify, request from backend.models.blockchain import Blockchain from backend.models.wallet import Wallet from backend.models.transaction import Transaction from backend.models.transaction_pool import TransactionPool from backend.pubsub import PubSub blockchain = Blockchain() wallet = Wallet(blockchain) transaction_pool = TransactionPool() pubsub = PubSub(blockchain, transaction_pool) BLOCKCHAIN = Blueprint('BLOCKCHAIN', __name__) @BLOCKCHAIN.route('/', methods=['GET']) def default_blockchain_route(): return jsonify(blockchain.to_json()) @BLOCKCHAIN.route('/range', methods=['GET']) # http://localhost:5000/blockchain/range?start=3&&end=6 def route_blockchain_range(): start = int(request.args.get('start')) end = int(request.args.get('end')) return jsonify(blockchain.to_json()[::-1][start:end])
def test_add_block(): blockchain = Blockchain() data = 'test_data' blockchain.add_block(data) assert blockchain.chain[-1].data == data
import time from backend.models.blockchain import Blockchain from backend.config import SECONDS blockchain = Blockchain() times = [] for i in range(1000): start_time = time.time_ns() blockchain.add_block(i) end_time = time.time_ns() time_to_mine = (end_time - start_time) / SECONDS times.append(time_to_mine) average_time = sum(times) / len(times) print(f'Block number: {i+1}') print(f'New block difficulty: {blockchain.chain[-1].difficulty}') print(f'Time to mine new block: {time_to_mine}s') print(f'Average time to add blocks: {average_time}s\n')
def test_blockchain_instance(): blockchain = Blockchain() assert blockchain.chain[0].hash == GENESIS_DATA['hash']
def blockchain_three_blocks(): blockchain = Blockchain() for i in range(3): blockchain.add_block([Transaction(Wallet(), 'recipient', i).to_json()]) return blockchain
from flask import Blueprint, jsonify, request from backend.models.blockchain import Blockchain from backend.models.transaction import Transaction from backend.models.transaction_pool import TransactionPool from backend.models.wallet import Wallet from backend.pubsub import PubSub blockchain = Blockchain() wallet = Wallet(blockchain) transaction_pool = TransactionPool() pubsub = PubSub(blockchain, transaction_pool) WALLET = Blueprint('WALLET', __name__) @WALLET.route('/info', methods=['GET']) def route_wallet_info(): return jsonify({'address': wallet.address, 'balance': wallet.balance}) @WALLET.route('/transact', methods=['POST']) def route_wallet_transact(): transaction_data = request.get_json() transaction = transaction_pool.existing_transaction(wallet.address) if transaction: transaction.update(wallet, transaction_data['recipient'], transaction_data['amount']) else: transaction = Transaction(wallet, transaction_data['recipient'],
def test_is_valid_chain(blockchain_three_blocks): # Compare two different instances of the same class in python, it will results as False. # E.g foo = Block.genesis(), bar = Block.genesis(), foo == bar => False Blockchain.is_valid_chain(blockchain_three_blocks.chain)
def test_valid_transaction_chain(blockchain_three_blocks): Blockchain.is_valid_transaction_chain(blockchain_three_blocks.chain)
def test_replace_chain_bad_chain(blockchain_three_blocks): blockchain = Blockchain() blockchain_three_blocks.chain[1].hash = 'evil_hash' with pytest.raises(Exception, match= 'The incomming chain is invalid'): blockchain.replace_chain(blockchain_three_blocks.chain)
def test_replace_chain_not_longer(blockchain_three_blocks): blockchain = Blockchain() with pytest.raises(Exception, match= 'The incoming chain must be longer'): blockchain_three_blocks.replace_chain(blockchain.chain)
def test_replace_chain(blockchain_three_blocks): blockchain = Blockchain() blockchain.replace_chain(blockchain_three_blocks.chain) assert blockchain.chain == blockchain_three_blocks.chain
def test_is_valid_chain_bad_genesis(blockchain_three_blocks): blockchain_three_blocks.chain[0].hash = 'evil_hash' with pytest.raises(Exception, match='genesis block must be valid'): Blockchain.is_valid_chain(blockchain_three_blocks.chain)