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)