Beispiel #1
0
    def test_invalid_chain_transactions(self):
        # Mine 10 coins to initial_address
        coinbase_transaction = {
            'sender': '0',
            'recipient': self.initial_address,
            'amount': 10
        }
        transactions_hash = self.mempool.hash([coinbase_transaction])
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)
        self.blockchain.create_block(nonce, previous_block_hash,
                                     [coinbase_transaction])

        # Include a transaction in block with to much coins spent
        signed_transaction = self.wallet.sign_transaction(
            self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 100)
        self.mempool.current_transactions.append(signed_transaction)
        transactions_hash = self.mempool.hash(
            self.mempool.current_transactions)
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)
        self.blockchain.create_block(nonce, previous_block_hash,
                                     self.mempool.current_transactions)

        self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain))
Beispiel #2
0
    def test_proof_of_work(self):
        transactions_hash = self.mempool.hash([])
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)

        encoded = f'{transactions_hash}{previous_block_hash}{nonce}'.encode()
        hashed = hashlib.sha256(encoded).hexdigest()

        self.assertEqual(hashed[:4], '0000')
        self.assertTrue(
            ProofOfWork.valid_proof(transactions_hash, previous_block_hash,
                                    nonce))
Beispiel #3
0
def mine():
    # Create a coinbase transaction to collect the block reward (10 coins) the address of the sender has to be "0"
    coinbase_transaction = {
        'sender': '0',
        'recipient': wallet.addresses[0],
        'amount': 10,
        'signature': 'coinbase transaction'
    }

    # Include all transactions of the mempool in the next block including the coinbase transaction
    transactions_of_block = blockchain.mempool.current_transactions
    transactions_of_block.append(coinbase_transaction)

    # Run the Proof of Work algorithm to find a valid nonce for the block
    previous_block = blockchain.last_block
    previous_block_hash = blockchain.hash(previous_block)
    transactions_hash = blockchain.mempool.hash(transactions_of_block)
    nonce = ProofOfWork.proof_of_work(transactions_hash, previous_block_hash)

    # Create the new block
    block = blockchain.create_block(nonce, previous_block_hash,
                                    transactions_of_block)

    response = {
        'message': "New block added to the chain",
        'index': block['index'],
        'timestamp': block['timestamp'],
        'nonce': block['nonce'],
        'transactions_hash': block['transactions_hash'],
        'previous_block_hash': block['previous_block_hash'],
        'transactions': block['transactions']
    }
    return jsonify(response), 200
Beispiel #4
0
    def test_proof_of_work_invalid_nonce(self):
        transactions_hash = self.mempool.hash([])
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = 12345

        self.assertFalse(
            ProofOfWork.valid_proof(transactions_hash, previous_block_hash,
                                    nonce))
Beispiel #5
0
    def test_valid_chain(self):
        signed_transaction = self.wallet.sign_transaction(
            self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0)
        self.mempool.add_transaction(signed_transaction, self.blockchain)
        transactions_hash = self.mempool.hash(
            self.mempool.current_transactions)
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)
        self.blockchain.create_block(nonce, previous_block_hash,
                                     self.mempool.current_transactions)

        self.assertTrue(self.blockchain.valid_chain(self.blockchain.chain))
Beispiel #6
0
    def test_block_hash(self):
        signed_transaction = self.wallet.sign_transaction(
            self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0)
        self.mempool.add_transaction(signed_transaction, self.blockchain)
        transactions_hash = self.mempool.hash(
            self.mempool.current_transactions)
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)
        self.blockchain.create_block(nonce, previous_block_hash,
                                     self.mempool.current_transactions)
        created_block = self.blockchain.last_block

        block_encoded = json.dumps(created_block, sort_keys=True).encode()
        block_hash = hashlib.sha256(block_encoded).hexdigest()

        self.assertEqual(len(self.blockchain.hash(created_block)), 64)
        self.assertEqual(self.blockchain.hash(created_block), block_hash)
Beispiel #7
0
    def valid_chain(self, chain):
        """
        Validate a given blockchain by checking the hash, the Proof of Work and the transactions for each block.
        :param chain: <list> The blockchain
        :return: <bool> True if valid, False if not
        """

        previous_block = chain[0]
        block_index = 1

        while block_index < len(chain):
            current_block = chain[block_index]

            # Validate the hash of the block
            if current_block['previous_block_hash'] != self.hash(
                    previous_block):
                return False

            # Validate the Proof of Work
            if not ProofOfWork.valid_proof(current_block['transactions_hash'],
                                           self.hash(previous_block),
                                           current_block['nonce']):
                return False

            # Validate the transactions of the block
            if current_block['transactions']:
                coinbase_transactions = 0
                for current_transaction in current_block['transactions']:
                    # Count the amount of coinbase transactions in the block
                    if current_transaction['sender'] == "0":
                        coinbase_transactions += 1
                    if not self.valid_transaction(current_transaction, chain,
                                                  block_index):
                        return False
                # If the block contains more than one coinbase transaction return False
                if coinbase_transactions > 1:
                    return False

            previous_block = current_block
            block_index += 1

        return True
Beispiel #8
0
def mine():
    # get the last proof of work
    last_block = blockchain.get_most_recent_block()
    last_proof = last_block['data']['proof_of_work']

    new_block_index = last_block['index'] + 1
    logger.info('mining new block with height {}'.format(new_block_index))

    # find the new proof of work for the current block being mined
    # The program will hang here until the proof of work is found
    proof = ProofOfWork(last_proof).calculate()

    # once we find a valid proof of work, we know we can mine a block so
    # we reward the miner by adding a transaction
    transactions.add_transaction({
        'from': 'network',
        'to': MINER_ADDRESS,
        'amount': MINER_REWARD
    })

    new_block_data = {
        'proof_of_work': proof,
        'transactions': transactions.get_transactions()
    }

    new_block_timestamp = str(date.datetime.now())
    last_block_hash = last_block['hash']

    # create the new block
    new_block = Block(
        new_block_index,
        new_block_timestamp,
        new_block_data
    )
    new_block.hash_block(last_block_hash)

    blockchain.write_block_to_disk(new_block)
    transactions.clear_transactions()

    # notify all nodes in network of new block
    network.broadcast_new_block(new_block)
Beispiel #9
0
    def test_invalid_chain_prev_block_hash(self):
        signed_transaction = self.wallet.sign_transaction(
            self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0)
        transactions_hash = self.mempool.hash(
            self.mempool.current_transactions)
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)

        block = {
            'index': len(self.chain) + 1,
            'timestamp': time(),
            'nonce': nonce,
            'transactions_hash': transactions_hash,
            'previous_block_hash': '12345',
            'transactions': [signed_transaction]
        }

        self.blockchain.chain.append(block)

        self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain))
Beispiel #10
0
    def test_invalid_chain_coinbase_transaction_amount(self):
        coinbase_transaction = {
            'sender': '0',
            'recipient': self.initial_address,
            'amount': 100
        }
        transactions_hash = self.mempool.hash([coinbase_transaction])
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)

        block = {
            'index': len(self.chain) + 1,
            'timestamp': time(),
            'nonce': nonce,
            'transactions_hash': transactions_hash,
            'previous_block_hash': previous_block_hash,
            'transactions': [coinbase_transaction]
        }

        self.blockchain.chain.append(block)

        self.assertFalse(self.blockchain.valid_chain(self.blockchain.chain))
Beispiel #11
0
    def test_create_block(self):
        signed_transaction = self.wallet.sign_transaction(
            self.initial_address, '14peaf2JegQP5nmNQESAdpRGLbse8JqgJD', 0)
        self.mempool.add_transaction(signed_transaction, self.blockchain)
        transactions_hash = self.mempool.hash(
            self.mempool.current_transactions)
        previous_block_hash = self.blockchain.hash(self.blockchain.last_block)
        nonce = ProofOfWork.proof_of_work(transactions_hash,
                                          previous_block_hash)
        self.blockchain.create_block(nonce, previous_block_hash,
                                     self.mempool.current_transactions)
        created_block = self.blockchain.last_block

        self.assertEqual(len(self.blockchain.chain), 2)
        self.assertEqual(created_block, self.blockchain.chain[-1])
        self.assertEqual(created_block['index'], 2)
        self.assertIsNotNone(created_block['timestamp'])
        self.assertEqual(created_block['nonce'], nonce)
        self.assertEqual(created_block['transactions_hash'], transactions_hash)
        self.assertEqual(created_block['previous_block_hash'],
                         previous_block_hash)
        self.assertEqual(created_block['transactions'], [signed_transaction])
        self.assertEqual(len(self.mempool.current_transactions), 0)