import hashlib import json import base64 import os import requests from datetime import datetime from flask import Flask, jsonify, request, render_template, flash, redirect, url_for 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() def calculate_hash(self): data_string = json.dumps(self.data, sort_keys=True) hash_data = str(self.index) + self.timestamp + data_string + self.previous_hash + str(self.nonce) return hashlib.sha256(hash_data.encode()).hexdigest() def mine_block(self, difficulty): target = '0' * difficulty while self.hash[:difficulty] != target: self.nonce += 1 self.hash = self.calculate_hash() print(f"Mining block {self.index}: Nonce = {self.nonce}, Hash = {self.hash}") print(f"Block {self.index} mined successfully!") class Blockchain: def __init__(self): self.chain = [] self.difficulty = 4 self.load_chain() def create_genesis_block(self): return Block(0, "0000-00-00 00:00:00", "Genesis Block", "0") def get_latest_block(self): return self.chain[-1] def add_block(self, new_block): new_block.previous_hash = self.get_latest_block().hash new_block.hash = new_block.calculate_hash() self.chain.append(new_block) self.save_chain() def load_chain(self): if os.path.exists('blockchain.json'): with open('blockchain.json', 'r') as file: chain_data = json.load(file) for block_data in chain_data: block = Block(block_data['index'], block_data['timestamp'], block_data['data'], block_data['previous_hash']) block.hash = block_data['hash'] self.chain.append(block) else: self.chain.append(self.create_genesis_block()) def save_chain(self): chain_data = [] for block in self.chain: chain_data.append({ 'index': block.index, 'timestamp': block.timestamp, 'data': block.data, 'previous_hash': block.previous_hash, 'hash': block.hash }) with open('blockchain.json', 'w') as file: json.dump(chain_data, file) def is_chain_valid(self): 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.calculate_hash(): return False if current_block.previous_hash != previous_block.hash: return False if current_block.hash[:self.difficulty] != '0' * self.difficulty: return False return True app = Flask(__name__) app.secret_key = 'lesecretkey' blockchain = Blockchain() CONNECTED_NODES = [] @app.route('/') def index(): return render_template('index.html') @app.route('/upload', methods=['POST']) def upload_image(): file = request.files['image'] image_data = base64.b64encode(file.read()).decode('utf-8') current_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S") block = Block(len(blockchain.chain), current_time, image_data, blockchain.get_latest_block().hash) block.mine_block(blockchain.difficulty) blockchain.add_block(block) if blockchain.is_chain_valid(): flash('Image uploaded successfully.', 'success') else: flash('Corrupted blocks detected. Image upload failed.', 'danger') blockchain.chain.pop() return redirect(url_for('index')) @app.route('/chain', methods=['GET']) def get_chain(): chain_data = [] for block in blockchain.chain: chain_data.append({ 'index': block.index, 'timestamp': block.timestamp, 'data': block.data, 'previous_hash': block.previous_hash, 'hash': block.hash }) return jsonify(chain_data) @app.route('/register_node', methods=['POST']) def register_node(): node_url = request.form['node_url'] if not node_url.startswith('http://') and not node_url.startswith('https://'): node_url = 'http://' + node_url if node_url not in CONNECTED_NODES: CONNECTED_NODES.append(node_url) return redirect(url_for('index')) @app.route('/sync_chain', methods=['GET']) def sync_chain(): longest_chain = None current_len = len(blockchain.chain) for node_url in CONNECTED_NODES: response = requests.get(f'{node_url}/chain') if response.status_code == 200: chain_data = response.json() chain_len = len(chain_data) if chain_len > current_len: current_len = chain_len longest_chain = chain_data if longest_chain: blockchain.chain = [Block(block['index'], block['timestamp'], block['data'], block['previous_hash']) for block in longest_chain] blockchain.save_chain() flash('Blockchain synchronized successfully', 'success') else: flash('Blockchain is already up to date', 'info') return redirect(url_for('index')) @app.route('/validate', methods=['GET']) def validate_blockchain(): is_valid = blockchain.is_chain_valid() if is_valid: return jsonify({"message": "Blockchain is valid"}) else: return jsonify({"message": "Blockchain is invalid"}), 400 @app.route('/nodes', methods=['GET']) def get_nodes(): return jsonify(CONNECTED_NODES) if __name__ == '__main__': app.run(host='0.0.0.0', port=5000, debug=True)