# Title: Proof of Work Algorithm for Blockchain ## Algorithm Statement: # The algorithm implements the Proof of Work (PoW) consensus mechanism used in # blockchain to validate blocks. PoW ensures participants (miners) perform a # computational task to create a valid block and add it to the blockchain. The # difficulty is defined by the number of leading zeros required in the block hash. import hashlib import time class Block: def __init__( self, index: int, previous_hash: str, transactions: str, timestamp: float, difficulty: int, ) -> None: """ Initializes a Block object with the specified parameters. Parameters: - index (int): The index of the block in the blockchain. - previous_hash (str): The hash of the previous block. - transactions (str): The list of transactions in the block. - timestamp (float): The time when the block was created (in Unix timestamp format). - difficulty (int): The difficulty level for mining this block. """ self.index = index self.previous_hash = previous_hash self.transactions = transactions self.timestamp = timestamp self.nonce = 0 # Start with nonce 0 self.difficulty = difficulty self.hash = self.compute_hash() def compute_hash(self) -> str: """ Generates the hash of the block content. Combines index, previous hash, transactions, timestamp, and nonce into a string, which is then hashed using SHA-256. Returns: - str: The hash of the block. """ block_string = ( f"{self.index}{self.previous_hash}{self.transactions}{self.timestamp}" f"{self.nonce}" ) return hashlib.sha256(block_string.encode()).hexdigest() def mine_block(self) -> None: """ Performs Proof of Work by adjusting the nonce until a valid hash is found. A valid hash has the required number of leading zeros based on the difficulty level. Returns: - None """ target = ( "0" * self.difficulty ) # Target hash should start with 'difficulty' zeros while self.hash[: self.difficulty] != target: self.nonce += 1 self.hash = self.compute_hash() print(f"Block mined with nonce {self.nonce}, hash: {self.hash}") class Blockchain: def __init__(self, difficulty: int) -> None: """ Initializes the blockchain with a given difficulty level. Parameters: - difficulty (int): The difficulty level for mining blocks in this blockchain. Returns: - None """ self.chain: list[Block] = [] # Adding type hint for the list of blocks self.difficulty = difficulty self.create_genesis_block() def create_genesis_block(self) -> None: """ Creates the first block in the blockchain (the Genesis block). Returns: - None """ genesis_block = Block(0, "0", "Genesis Block", time.time(), self.difficulty) genesis_block.mine_block() self.chain.append(genesis_block) def add_block(self, transactions: str) -> None: """ Adds a new block to the blockchain after performing Proof of Work. Parameters: - transactions (str): The list of transactions to be added in the new block. Returns: - None """ previous_block = self.chain[-1] new_block = Block( len(self.chain), previous_block.hash, transactions, time.time(), self.difficulty, ) new_block.mine_block() self.chain.append(new_block) def is_chain_valid(self) -> bool: """ Verifies the integrity of the blockchain by ensuring each block's previous hash matches and that all blocks meet the Proof of Work requirement. Returns: - bool: True if the blockchain is valid, False otherwise. """ for i in range(1, len(self.chain)): current_block = self.chain[i] previous_block = self.chain[i - 1] if current_block.hash != current_block.compute_hash(): print(f"Invalid block at index {i}. Hash mismatch.") return False if current_block.previous_hash != previous_block.hash: print(f"Invalid chain at index {i}. Previous hash mismatch.") return False return True # Test cases ## Test Case 1: Blockchain Initialization and Genesis Block # This test verifies if the blockchain is correctly initialized with a Genesis block # and if the block is successfully mined. def test_blockchain() -> None: """ Test cases for the Blockchain proof of work algorithm. Returns: - None """ # Create blockchain with difficulty level of 4 (hash should start with 4 zeros) blockchain = Blockchain(difficulty=4) ## Test Case 2: Add a block and verify the block is mined # This test adds a new block with transactions and ensures it's mined according # to the proof of work mechanism. blockchain.add_block("Transaction 1: Alice pays Bob 5 BTC") blockchain.add_block("Transaction 2: Bob pays Charlie 3 BTC") ## Test Case 3: Verify blockchain integrity # This test checks that the blockchain remains valid after adding new blocks assert blockchain.is_chain_valid(), "Blockchain should be valid" ## Test Case 4: Tampering with the blockchain # This test simulates tampering with the blockchain and checks that the validation # correctly detects the tampering. blockchain.chain[ 1 ].transactions = "Transaction 1: Alice pays Bob 50 BTC" # Tampering assert ( not blockchain.is_chain_valid() ), "Blockchain should be invalid due to tampering" ## Test Case 5: Correct blockchain validation # This test checks if the blockchain becomes invalid after tampering and verifies # if the PoW still holds after tampering is done. print("All test cases passed.") if __name__ == "__main__": test_blockchain()