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))
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))
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