Spaces:
Sleeping
Sleeping
File size: 3,724 Bytes
c56049d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
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) |