This week I worked mostly on a blockchain project. The concept is to learn more about cryptocurrencies and hashing.
server.py:
from datetime import datetime
import time
import socket
from wallet import Wallet
from block import Blockchain, Block
blockchain = Blockchain()
ace = Wallet()
def mine_new_blocks(blockchain):
last_block = blockchain.get_latest_block()
new_index = last_block.index + 1
current_time = datetime.now()
coins_per_block = 1
data = f"wilmoth +0 coins! orlando -0 coins!"
ace.add_balance(coins_per_block)
new_block = Block(new_index, current_time, data, last_block.hash)
blockchain.add_block(new_block)
mined_hash = new_block.hash
print(f"Mined Hash: {mined_hash}")
# Broadcast the new block to all connected peers
broadcast_new_block(new_block)
peers = []
def broadcast_new_block(block):
for peer in peers:
send_block_to_peer(peer, block)
def start_server(host='localhost', port=12345):
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind((host, port))
server_socket.listen(10) # Allow multiple connections
print(f"Server listening on {host}:{port}")
while True:
client_socket, addr = server_socket.accept()
print(f"Connection from {addr}")
if len(peers) < 5: # Limit the number of connected peers for simplicity
peers.append(client_socket)
else:
client_socket.close()
def handle_client(client_socket):
data = client_socket.recv(1024).decode()
if data == "validate":
is_valid = blockchain.validate_chain()
if is_valid:
response = "Chain is valid"
else:
response = "Chain is invalid"
client_socket.sendall(response.encode())
elif data.startswith("BLOCK"):
block_data = data.split(" ", 1)[1]
received_block = Block.from_string(block_data)
if validate_and_add_block(received_block):
response = "Block added successfully"
else:
response = "Invalid block"
client_socket.sendall(response.encode())
client_socket.close()
def send_block_to_peer(peer, block):
peer.sendall(f"BLOCK {block.to_string()}".encode())
def validate_and_add_block(block):
try:
for i in range(1, len(blockchain.chain)):
blockchain.chain[i].validate_block(blockchain.chain[i - 1])
if not blockchain.validate_chain():
return False
blockchain.add_block(block)
return True
except Exception as e:
print(f"Error validating block: {e}")
return False
if __name__ == "__main__":
import threading
server_thread = threading.Thread(target=start_server, args=())
server_thread.start()
while True:
mine_new_blocks(blockchain)
time.sleep(1) # Adjust the sleep time as needed
client.py:
from datetime import datetime
import time
import socket
from wallet import Wallet
from block import Blockchain, Block
blockchain = Blockchain()
ace = Wallet()
def start_client(host=’localhost’, port=12345):
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((host, port))
print(f”Connected to {host}:{port}”)
while True:
data = input(“Enter command (validate/block/exit): “)
if data == “validate”:
is_valid = blockchain.validate_chain()
if is_valid:
response = “Chain is valid”
else:
response = “Chain is invalid”
print(response)
elif data.startswith(“BLOCK”):
block_data = data.split(” “, 1)[1]
received_block = Block.from_string(block_data)
if validate_and_add_block(received_block):
response = “Block added successfully”
else:
response = “Invalid block”
print(response)
elif data == “exit”:
break
client_socket.close()
def validate_and_add_block(block):
try:
for i in range(1, len(blockchain.chain)):
blockchain.chain[i].validate_block(blockchain.chain[i – 1])
if not blockchain.validate_chain():
return False
blockchain.add_block(block)
return True
except Exception as e:
print(f”Error validating block: {e}”)
return False
if __name__ == “__main__”:
start_client()
block.py:
import hashlib
from datetime import datetime
import json
class Block:
def __init__(self, index, timestamp, data, previous_hash, nonce=0):
self.index = index
self.timestamp = timestamp
self.data = data
self.previous_hash = previous_hash
self.nonce = nonce
self.hash = self.calculate_hash()
@staticmethod
def from_string(block_data):
data_dict = json.loads(block_data)
return Block(
index=data_dict['index'],
timestamp=datetime.strptime(data_dict['timestamp'], "%Y-%m-%d %H:%M:%S"),
data=data_dict['data'],
previous_hash=data_dict['previous_hash'],
nonce=data_dict.get('nonce', 0)
)
def calculate_hash(self):
return hashlib.sha256(f"{self.index}{self.timestamp}{self.data}{self.previous_hash}{self.nonce}".encode()).hexdigest()
def validate_block(self, previous_block):
if self.previous_hash != previous_block.hash:
return False
if not self.calculate_hash().startswith('0' * 4):
return False
return True
class Blockchain:
def __init__(self, difficulty=4):
self.chain = [self.create_genesis_block()]
self.difficulty = difficulty
def create_genesis_block(self):
return Block(0, datetime.now(), "Genesis_Block", "0")
def get_latest_block(self):
return self.chain[-1]
def proof_of_work(self, block):
nonce = 0
while True:
block.nonce = nonce
if block.calculate_hash().startswith('0' * self.difficulty):
return block.hash
nonce += 1
def add_block(self, new_block):
new_block.previous_hash = self.get_latest_block().hash
new_block.hash = self.proof_of_work(new_block)
self.chain.append(new_block)
def validate_chain(self):
for i in range(1, len(self.chain)):
block = self.chain[i]
previous_block = self.chain[i - 1]
if not block.validate_block(previous_block):
return False
return True
wallet.py:
import random
import string
class Wallet:
def __init__(self):
self.balance = 0.0
self.address = self.generate_address()
@staticmethod
def generate_address():
return ''.join([random.choice(string.ascii_letters + string.digits) for _ in range(32)])
def add_balance(self, amount):
self.balance += amount
def spend_balance(self, amount):
if amount > self.balance:
raise ValueError("Insufficient balance")
self.balance -= amount
Leave a Reply