Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
def main():
    """Example use of the Blockchain, with the ability to read and write to a file."""

    try:
        with open("chain_data.json", "r") as chain_data_h:
            chain_data_raw = chain_data_h.read()
    except:
        print("Chain data missing or invalid, writing default chain.")
        chain_data_raw = write_default_blockchain()

    chain_data = []
    try:
        # Convert the file contents (JSON) to a list of Blocks represented as dicts.
        chain_data = json.loads(chain_data_raw)
    except:
        print("Invalid chain data detected.")
        sys.exit(-1)

    # Initialise the Blockchain with the imported data.
    chain = Blockchain(chain_data)
    print(f"The blockchain has {len(chain.blocks)} blocks.")
    print(f"Hash of genesis block is {chain.blocks[0].generate_hash()}")
    print("Valid?", chain.validate())

    # If you're tinkering... here you could try adding or removing Blocks.
    # You may wish to use chain.add_data(data: str), or even add a
    # malicious block using the chain.blocks list directly.

    # In case of any modifications, write the chain to a file again.
    save_chain(chain)
Ejemplo n.º 3
0
def mine():
    # Run the proof-of-work algorithm to get the next proof
    last_block = Blockchain.last_block
    proof = Blockchain.proof_of_work(last_block)

    # Receive a reward for finding the proof
    # A sender "0" signifies that the node has mined a new coin
    Blockchain.new_transaction(
        sender="0",
        recipient=node_identifier,
        amount=1,
    )

    # Forge a new block by adding transaction to the chain
    previous_hash = Blockchain.hash(last_block)
    block = Blockchain.new_block(proof, previous_hash)

    response = {
        'message': "New Block forged",
        'index': block['index'],
        'transactions': block['transactions'],
        'proof': block['proof'],
        'previous_hash': block['previous_hash'],
    }

    return jsonify(response), 200
Ejemplo n.º 4
0
 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)
Ejemplo n.º 5
0
def test_add_block():
    bc = Blockchain()
    client1 = Client()
    client2 = Client()
    tx = Transaction("Hello from the beginning", client1, client2)
    bc.unconfirmed_transactions.append(tx.get_tx_dict())
    bc.mine(bc.chain[-1])
    assert bc.chain[-1].transactions is not None
Ejemplo n.º 6
0
    def test_replace(self):
        # Create a new blockchain, only has genesis
        blockchain = Blockchain()

        # Try replacing chain with longer chain
        blockchain.replace(self.blockchain.chain)

        # Assert that chain was replaced by longer one
        self.assertEqual(blockchain.chain, self.blockchain.chain)
Ejemplo n.º 7
0
    def test_replace_incoming_not_valid(self):
        # Create a new blockchain, only has genesis
        blockchain = Blockchain()

        self.blockchain.chain[1].data = "Some bad data"

        with self.assertRaises(ChainReplacementError):
            # Try replacing chain with shorter chain
            blockchain.replace(self.blockchain.chain)
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
def register_nodes():
    values = request.get_json()
    print(f'Values is: {values}')
    nodes = values.get('nodes')
    if nodes is None:
        return "Error: Please supply a valid list of nodes", 400
    for node in nodes:
        Blockchain.register_node(node)
    response = {
        'message': 'New nodes have been added',
        'total_nodes': list(Blockchain.nodes),
    }
    return jsonify(response), 201
Ejemplo n.º 10
0
def write_default_blockchain() -> str:
    """Returns the string representation of the default Blockchain data."""

    genesis_block = Block()
    genesis_block.data = "This is the sickest Blockchain implementation ever."
    genesis_block.timestamp = time.time()
    genesis_block.previous_hash = ""

    # Create a temporary chain which we can convert to JSON.
    default_chain = Blockchain([])
    default_chain.blocks.append(genesis_block)
    save_chain(default_chain)

    return default_chain.to_json()
Ejemplo n.º 11
0
    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)
Ejemplo n.º 12
0
def is_valid():
    if Blockchain.is_chain_valid(blockchain.chain):
        response = {'message': 'All good. The Blockchain is valid.'}
    else:
        response = {
            'message':
            'Houston, we have a problem. The Blockchain is not valid.'
        }

    return jsonify(response), 200
Ejemplo n.º 13
0
    def test_replace_incoming_not_longer(self):
        # Create a new blockchain, only has genesis
        incoming = Blockchain()

        with self.assertRaisesRegex(
                ChainReplacementError,
                "Cannot replace. Incoming chain must be longer than local chain.",
        ):
            # Try replacing chain with shorter chain
            self.blockchain.replace(incoming.chain)
 def __init__(self, PORT_ADDRESS):
     self.nodes = list()
     self.PORT_ADDRESS = PORT_ADDRESS
     self.transactions = []
     Blockchain.__init__(self)
     try:
         json_file_read = open('nodes.txt', 'r')
         data = json.load(json_file_read)
         for p in data['nodes']:
             self.nodes.append(p)
         json_file_read.close()
     except FileNotFoundError:
         print("Creating file nodes.txt...")
     finally:
         self.nodes.append(PORT_ADDRESS)
         json_file_write = open('nodes.txt', 'w')
         data = {"nodes": self.nodes}
         json.dump(data, json_file_write)
         json_file_write.close()
Ejemplo n.º 15
0
def mine():
    last_block = blockchain.last_block
    last_proof = blockchain.last_block['proof']

    proof = blockchain.proof_of_work(last_proof)
    blockchain.new_transactions("0", node_identifier, 1)

    previous_hash = Blockchain.hash_block(last_block)
    block = blockchain.new_block(previous_hash, proof)

    return jsonify({'message': 'New block forged', 'block': block}), 200
Ejemplo n.º 16
0
    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)
Ejemplo n.º 17
0
        def wait_chains():
            try:
                new_chain_json = self.chain_syncher.get_chain()
                new_blockchain = Blockchain.from_json(new_chain_json)

                self.blockchain.replace_chain(new_blockchain, self.entry_pool)

                self.entry_pool.filter(self.blockchain)

                print('\nBlockchain synchronisiert')
            except Exception as e:
                print(f'\nBlockchain nicht synchronisiert -> {e}')
Ejemplo n.º 18
0
    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,
        )
Ejemplo n.º 19
0
def consensus():
    replaced = Blockchain.resolve_conflicts()
    if replaced:
        response = {
            'message': 'Chain was replaced',
            'new_chain': Blockchain.chain
        }
    else:
        response = {
            'message': 'Chain is authoritative',
            'chain': Blockchain.chain
        }
    return jsonify(response), 200
Ejemplo n.º 20
0
def new_transaction():
    values = request.get_json()

    # Are the required fields in the POSTed data?
    required = ['sender', 'receiver', 'amount']
    if not all(k in values for k in required):
        return 'Missing Values', 400

    # Create a new transaction
    index = Blockchain.new_transaction(values['sender'], values['receiver'],
                                       values['amount'])
    response = {'message': f'Transaction will be added to Block {index}'}

    return jsonify(response), 201
Ejemplo n.º 21
0
def save_chain(chain: Blockchain, location: str = "chain_data.json") -> bool:
    """
    Returns a bool indicating whether or not the data was saved.
    
    Parameters:
    chain       -- the Blockchain to write to the file.
    location    -- the path to the file in which the data will be written.
    """

    try:
        with open(location, "w") as chain_data_h:
            chain_data_h.write(chain.to_json())
            return True
    except:
        return False
Ejemplo n.º 22
0
    def message(self, pubnub, message_object):

        if message_object.channel == 'BLOCK':
            sender_addr = message_object.message["sender_address"]
            if sender_addr != self.keychain.address:
                print(
                    f'\nBlock empfangen von Node: {sender_addr} -> {Block.from_json(message_object.message["block"])}'
                )
                block = Block.from_json(message_object.message["block"])
                new_chain = self.blockchain.chain[:]
                new_chain.append(block)
                try:
                    self.blockchain.replace_chain(Blockchain(new_chain),
                                                  self.entry_pool)
                    self.entry_pool.filter(self.blockchain)
                    print('\nBlockchain ergänzt')
                except Exception as e:
                    print(f'\nFehler bei Ergänzung -> {e}')

        if message_object.channel == 'ENTRY':
            try:
                entry = json_to_entry(message_object.message)
                self.entry_pool.add_entry(entry)
                print(f'\nEintrag empfangen: {entry}')
            except Exception as e:
                print(f'\nFehler beim Empfangen eines Eintrags -> {e}')

        if message_object.channel == 'CHAIN':
            recipient_addr = message_object.message["recipient_address"]
            if recipient_addr == self.keychain.address:
                self.chain_syncher.add_chain(message_object.message["chain"])
                print('\nChain empfangen')

        if message_object.channel == 'SYNC':
            sender_addr = message_object.message["sender_address"]
            if self.keychain.address != sender_addr:
                self.p2p.send_chain(self.blockchain, sender_addr)
                print(f'\nChain gesendet an Node: {sender_addr}')
Ejemplo n.º 23
0
from flask import Flask, jsonify, request
from uuid import uuid4
from blockchain.blockchain import Blockchain

# Создаем икземплярнашего узла
app = Flask(__name__)

# Генерируем уникальный адрес для нашего узла
node_identifier = str(uuid4()).replace('-', '')

# Создаем экзеипляр Blockchain
blockchain = Blockchain()


@app.route('/', methods=['GET'])
def index():
    return 'Our very first REAL BLOCKCHAIN!!!'


@app.route('/my/address', methods=['GET'])
def my_address():
    response = {"address": node_identifier}

    return jsonify(response), 200


@app.route('/mine', methods=['GET'])
def mine():
    # Запускаем алгоритм PoW для того чтобы найти proof ...
    last_block = blockchain.last_block
    last_proof = last_block['proof']
Ejemplo n.º 24
0
def test_genesis_block():
    bc = Blockchain()
    assert bc.chain[0]
Ejemplo n.º 25
0
class BlockchainTest(TestCase):
    KEYS = [
        ("ak_zPoY7cSHy2wBKFsdWJGXM7LnSjVt6cn1TWBDdRBUMC7Tur2NQ",
         "36595b50bf097cd19423c40ee66b117ed15fc5ec03d8676796bdf32bc8fe367d82517293a0f82362eb4f93d0de77af5724fba64cbcf55542328bc173dbe13d33"
         ),
        ("ak_gLYH5tAexTCvvQA6NpXksrkPJKCkLnB9MTDFTVCBuHNDJ3uZv",
         "6eb127925aa10d6d468630a0ca28ff5e1b8ad00db151fdcc4878362514d6ae865951b78cf5ef047cab42218e0d5a4020ad34821ca043c0f1febd27aaa87d5ed7"
         ),
        ("ak_23p6pT7bajYMJRbnJ5BsbFUuYGX2PBoZAiiYcsrRHZ1BUY2zSF",
         "e15908673cda8a171ea31333538437460d9ca1d8ba2e61c31a9a3d01a8158c398a14cd12266e480f85cc1dc3239ed5cfa99f3d6955082446bebfe961449dc48b"
         ),
    ]

    def setUp(self):
        self.bc = Blockchain()

    def test_mint(self):
        pubkey = self.KEYS[0][0]
        amount = int(1.234e8)

        balance_pre = self.bc.get_balance(pubkey)

        response = self.client.post("/blockchain/mint", {
            "receiver_pubkey": pubkey,
            "amount": amount,
        })

        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            json.loads(response.content.decode("utf-8"))["status"], "ok")

        balance_post = self.bc.get_balance(pubkey)

        self.assertEqual(balance_post, balance_pre + amount)

    def test_transfer_aeter(self):
        pubkey = self.KEYS[0][0]
        amount = int(1.234e8)

        balance_pre = self.bc.get_balance_aeter(pubkey)

        response = self.client.post("/blockchain/transfer_aeter", {
            "receiver_pubkey": pubkey,
            "amount": amount,
        })

        self.assertEqual(response.status_code, 200)
        self.assertEqual(
            json.loads(response.content.decode("utf-8"))["status"], "ok")

        balance_post = self.bc.get_balance_aeter(pubkey)

        self.assertEqual(balance_post, balance_pre + amount)

    def test_get_balance(self):
        pubkey = self.KEYS[0][0]

        response = self.client.get("/blockchain/get_balance", {
            "pubkey": pubkey,
        })

        self.assertEqual(response.status_code, 200)
        self.assertTrue(response.content.decode("utf-8").isdigit())

    def test_get_nonce(self):
        pubkey = self.KEYS[0][0]

        response = self.client.get("/blockchain/get_nonce", {
            "pubkey": pubkey,
        })

        self.assertEqual(response.status_code, 200)
        self.assertTrue(response.content.decode("utf-8").isdigit())

    def test_get_transfer_tx(self):
        # TODO
        pass

    def test_broadcast_signed_tx(self):
        # TODO
        pass
Ejemplo n.º 26
0
 def setUp(self):
     self.bc = Blockchain()
def test_add_block():
    blockchain=Blockchain()
    data='test-data'
    blockchain.addBlock(data)

    assert blockchain.ledger[-1].data==data
def test_replaceLedgerBadLedger(blockchain_three_blocks):
    blockchain = Blockchain()
    blockchain_three_blocks.ledger[1].hash = 'bad_hash'

    with pytest.raises(Exception, match='cannot replace. The incoming chain is invalid:'):
        blockchain.replaceLedger(blockchain_three_blocks.ledger)
def test_blockchain_instance():
    blockchain=Blockchain()
    assert blockchain.ledger[0].hash==GENESIS_DATA['hash']
def test_replaceLedgerNotLonger(blockchain_three_blocks):
    blockchain = Blockchain()

    with pytest.raises(Exception, match='cannot replace. The incoming chain must be longer.'):
        blockchain_three_blocks.replaceLedger(blockchain.ledger)