2024-10-03 15:14:06 +05:30
|
|
|
"""
|
|
|
|
# Title: Proof of Work Algorithm for Blockchain
|
|
|
|
|
|
|
|
## Algorithm Statement:
|
2024-10-03 09:55:24 +00:00
|
|
|
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
|
2024-10-03 15:25:02 +05:30
|
|
|
difficulty is defined by the number of leading zeros required in the block hash.
|
2024-10-03 15:14:06 +05:30
|
|
|
"""
|
|
|
|
|
|
|
|
import hashlib
|
|
|
|
import time
|
|
|
|
|
2024-10-03 09:55:24 +00:00
|
|
|
|
2024-10-03 15:14:06 +05:30
|
|
|
class Block:
|
|
|
|
def __init__(self, index, previous_hash, transactions, timestamp, difficulty):
|
|
|
|
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):
|
|
|
|
"""
|
|
|
|
Generates the hash of the block content.
|
2024-10-03 09:49:33 +00:00
|
|
|
Combines index, previous hash, transactions, timestamp, and nonce into a string,
|
2024-10-03 15:14:06 +05:30
|
|
|
which is then hashed using SHA-256.
|
|
|
|
"""
|
2024-10-03 15:25:02 +05:30
|
|
|
block_string = (
|
|
|
|
f"{self.index}{self.previous_hash}{self.transactions}{self.timestamp}"
|
|
|
|
f"{self.nonce}"
|
|
|
|
)
|
2024-10-03 15:14:06 +05:30
|
|
|
return hashlib.sha256(block_string.encode()).hexdigest()
|
|
|
|
|
|
|
|
def mine_block(self):
|
|
|
|
"""
|
|
|
|
Performs Proof of Work by adjusting the nonce until a valid hash is found.
|
2024-10-03 09:55:24 +00:00
|
|
|
A valid hash has the required number of leading zeros based on the difficulty
|
2024-10-03 15:25:02 +05:30
|
|
|
level.
|
2024-10-03 15:14:06 +05:30
|
|
|
"""
|
2024-10-03 09:55:24 +00:00
|
|
|
target = (
|
|
|
|
"0" * self.difficulty
|
|
|
|
) # Target hash should start with 'difficulty' zeros
|
|
|
|
while self.hash[: self.difficulty] != target:
|
2024-10-03 15:14:06 +05:30
|
|
|
self.nonce += 1
|
|
|
|
self.hash = self.compute_hash()
|
|
|
|
|
|
|
|
print(f"Block mined with nonce {self.nonce}, hash: {self.hash}")
|
|
|
|
|
2024-10-03 09:55:24 +00:00
|
|
|
|
2024-10-03 15:14:06 +05:30
|
|
|
class Blockchain:
|
|
|
|
def __init__(self, difficulty):
|
|
|
|
self.chain = []
|
|
|
|
self.difficulty = difficulty
|
|
|
|
self.create_genesis_block()
|
|
|
|
|
|
|
|
def create_genesis_block(self):
|
|
|
|
"""
|
|
|
|
Creates the first block in the blockchain (the Genesis block).
|
|
|
|
"""
|
|
|
|
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):
|
|
|
|
"""
|
|
|
|
Adds a new block to the blockchain after performing Proof of Work.
|
|
|
|
"""
|
|
|
|
previous_block = self.chain[-1]
|
2024-10-03 09:55:24 +00:00
|
|
|
new_block = Block(
|
|
|
|
len(self.chain),
|
|
|
|
previous_block.hash,
|
|
|
|
transactions,
|
|
|
|
time.time(),
|
|
|
|
self.difficulty,
|
|
|
|
)
|
2024-10-03 15:14:06 +05:30
|
|
|
new_block.mine_block()
|
|
|
|
self.chain.append(new_block)
|
|
|
|
|
|
|
|
def is_chain_valid(self):
|
|
|
|
"""
|
2024-10-03 09:55:24 +00:00
|
|
|
Verifies the integrity of the blockchain by ensuring each block's previous
|
2024-10-03 15:25:02 +05:30
|
|
|
hash matches and that all blocks meet the Proof of Work requirement.
|
2024-10-03 15:14:06 +05:30
|
|
|
"""
|
|
|
|
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
|
|
|
|
|
2024-10-03 09:55:24 +00:00
|
|
|
|
2024-10-03 15:14:06 +05:30
|
|
|
# Test cases
|
|
|
|
|
2024-10-03 09:55:24 +00:00
|
|
|
|
2024-10-03 15:14:06 +05:30
|
|
|
def test_blockchain():
|
|
|
|
"""
|
|
|
|
Test cases for the Blockchain proof of work algorithm.
|
|
|
|
"""
|
|
|
|
# Create blockchain with difficulty level of 4 (hash should start with 4 zeros)
|
|
|
|
blockchain = Blockchain(difficulty=4)
|
|
|
|
|
|
|
|
# Add new blocks
|
|
|
|
blockchain.add_block("Transaction 1: Alice pays Bob 5 BTC")
|
|
|
|
blockchain.add_block("Transaction 2: Bob pays Charlie 3 BTC")
|
|
|
|
|
|
|
|
# Verify the integrity of the blockchain
|
2024-10-03 15:25:02 +05:30
|
|
|
assert blockchain.is_chain_valid(), "Blockchain should be valid"
|
2024-10-03 15:14:06 +05:30
|
|
|
|
|
|
|
# Tamper with the blockchain and check validation
|
2024-10-03 09:55:24 +00:00
|
|
|
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"
|
2024-10-03 15:14:06 +05:30
|
|
|
|
|
|
|
print("All test cases passed.")
|
|
|
|
|
2024-10-03 09:55:24 +00:00
|
|
|
|
2024-10-03 15:14:06 +05:30
|
|
|
if __name__ == "__main__":
|
|
|
|
test_blockchain()
|
|
|
|
|
|
|
|
"""
|
|
|
|
# Output:
|
|
|
|
- Block mined with nonce X, hash: 0000abcd...
|
|
|
|
- Block mined with nonce Y, hash: 0000xyz...
|
|
|
|
- Block mined with nonce Z, hash: 0000pqrs...
|
|
|
|
- All test cases passed.
|
|
|
|
"""
|