Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| import networkx as nx | |
| import matplotlib.pyplot as plt | |
| import hashlib | |
| import time | |
| import io | |
| from PIL import Image | |
| # ------------------- BLOCKCHAIN LOGIC -------------------- # | |
| class Block: | |
| def __init__(self, index, data, previous_hash="0"): | |
| self.index = index | |
| self.timestamp = time.time() | |
| self.data = data | |
| self.previous_hash = previous_hash | |
| self.nonce = 0 | |
| self.hash = self.calculate_hash() | |
| def calculate_hash(self): | |
| block_string = ( | |
| str(self.index) + | |
| str(self.timestamp) + | |
| str(self.data) + | |
| str(self.previous_hash) + | |
| str(self.nonce) | |
| ) | |
| return hashlib.sha256(block_string.encode()).hexdigest() | |
| def mine_block(block, difficulty=1): | |
| """ | |
| A quick "proof-of-work": | |
| The block's hash must start with '0' * difficulty, e.g. '0' for difficulty=1. | |
| If this is still slow for you, set difficulty=0 to skip "mining" entirely. | |
| """ | |
| target_prefix = "0" * difficulty | |
| while not block.hash.startswith(target_prefix): | |
| block.nonce += 1 | |
| block.hash = block.calculate_hash() | |
| def create_genesis_block(): | |
| genesis = Block(index=0, data="Genesis Block", previous_hash="0") | |
| mine_block(genesis, difficulty=1) | |
| return genesis | |
| # The global chain | |
| chain = [] | |
| # Initialize the chain with a genesis block if empty | |
| if not chain: | |
| chain.append(create_genesis_block()) | |
| def add_block_to_chain(data): | |
| previous_block = chain[-1] | |
| new_block = Block( | |
| index=len(chain), | |
| data=data, | |
| previous_hash=previous_block.hash | |
| ) | |
| mine_block(new_block, difficulty=1) | |
| chain.append(new_block) | |
| # ------------------- VISUALIZATION -------------------- # | |
| def visualize_chain(chain): | |
| """ | |
| Creates a LINEAR graph of the blockchain using NetworkX | |
| and returns it as a PIL image. | |
| We'll place blocks in a line (x=index, y=0) to avoid | |
| expensive layout computations each time. | |
| """ | |
| G = nx.DiGraph() | |
| # Add nodes | |
| for blk in chain: | |
| # node label shows index + partial hash | |
| node_label = f"Block {blk.index}\nHash: {blk.hash[:6]}..." | |
| G.add_node(blk.index, label=node_label) | |
| # Add edges | |
| for i in range(len(chain) - 1): | |
| G.add_edge(chain[i].index, chain[i+1].index) | |
| # Fixed, linear layout: x = index, y = 0 | |
| pos = {blk.index: (blk.index, 0) for blk in chain} | |
| # Draw the graph | |
| plt.figure(figsize=(10, 3)) | |
| nx.draw_networkx_nodes(G, pos, node_color="lightblue", node_size=1500) | |
| nx.draw_networkx_edges(G, pos, arrowstyle='->', arrowsize=20) | |
| node_labels = nx.get_node_attributes(G, 'label') | |
| nx.draw_networkx_labels(G, pos, labels=node_labels, font_size=8) | |
| plt.title("Toy Blockchain Visualization (Linear Layout)") | |
| plt.axis("off") | |
| # Convert the Matplotlib figure to a PIL image | |
| buf = io.BytesIO() | |
| plt.savefig(buf, format='png', bbox_inches='tight') | |
| buf.seek(0) | |
| plt.close() | |
| return Image.open(buf) | |
| def add_and_visualize_block(data): | |
| # Add a new block with user-provided data | |
| add_block_to_chain(data) | |
| # Generate the updated visualization | |
| return visualize_chain(chain) | |
| # ------------------- GRADIO INTERFACE -------------------- # | |
| demo = gr.Interface( | |
| fn=add_and_visualize_block, | |
| inputs=gr.Textbox(lines=2, label="Data for New Block", placeholder="e.g. 'My transaction'"), | |
| outputs="image", | |
| title="Toy Blockchain Demo (Faster Visualization)", | |
| description=( | |
| "Enter any data to create a new block. " | |
| "Mining difficulty is set to 1, so it should be fast. " | |
| "Blocks are displayed in a linear chain." | |
| ), | |
| ) | |
| demo.launch(debug=True) |