Interactive Blockchain Demo

How it Works:

  1. Data Structure: While blockchain shares some characteristics with linked lists (using pointers to connect elements), it's fundamentally different. Unlike a simple linked list, blockchain uses cryptographic hashes as links and requires computational work (mining) to add new blocks. This makes it immutable and secure.
  2. Blocks: The boxes below represent blocks in a chain. The first is the "Genesis Block". Each block is connected to the previous one through a cryptographic hash, creating an immutable chain.
  3. Data: Each block holds data. You can type anything into the 'Data' text areas. However, once a block is mined, its data cannot be changed without invalidating the entire chain.
  4. Hash: A unique digital fingerprint (SHA-256) of the block's content (Index, Timestamp, Data, Previous Hash, Nonce). It changes instantly if *any* content changes. This is different from a simple pointer in a linked list - it's a cryptographic proof of the block's content.
  5. Previous Hash: Links a block to the one before it, creating the 'chain'. Unlike a linked list's pointer, this hash is a cryptographic proof that depends on the previous block's entire content. The Genesis Block has "0".
  6. Nonce & Mining: To add a block securely (in a real blockchain), it must be 'mined'. Click 'Mine' to find a 'Nonce' (a random number) that makes the block's Hash start with "00" (our simple difficulty rule). This takes computational effort, which is a key difference from simple data structures.
  7. Immutability: Try changing data in a *mined* block (green background). Notice its hash changes and no longer starts with "00". This breaks the 'Previous Hash' link for the *next* block, invalidating the chain! The chain status below will turn red. This immutability is a core feature that distinguishes blockchain from traditional data structures.
  8. Fixing the Chain: To make a broken chain valid again, you must re-mine the tampered block *and* all subsequent blocks in order. This is because each block's hash depends on the previous block's content, creating a chain of cryptographic proofs.

Goal: Add blocks, mine them, and try tampering with data to see how the hashes and chain validity change. Notice how this differs from a simple linked list - you can't just modify a pointer to fix a broken chain!

Chain Status: VALID

Total Blocks: 0

Average Mining Time: 0 ms

More zeros = longer mining time

The Mathematics Behind Mining

Mining in blockchain is essentially a mathematical puzzle that requires finding a hash that meets certain criteria. Here's how it works:

Code Examples

// JavaScript Mining Implementation using Web Crypto API

// Function to mine a block with a given difficulty
async function mineBlock(data, difficulty) {
    let nonce = 0;  // Start with nonce = 0
    const prefix = '0'.repeat(difficulty);  // Create target prefix (e.g., "000")
    
    // Keep trying different nonces until we find a valid hash
    while (true) {
        const hash = await calculateHash(data + nonce);
        // Check if hash meets difficulty requirement
        if (hash.startsWith(prefix)) {
            return { nonce, hash };  // Found a valid hash!
        }
        nonce++;  // Try next nonce value
    }
}

// Helper function to calculate SHA-256 hash using Web Crypto API
async function calculateHash(input) {
    // Convert input string to bytes
    const encoder = new TextEncoder();
    const data = encoder.encode(input);
    
    // Calculate SHA-256 hash
    const hashBuffer = await crypto.subtle.digest('SHA-256', data);
    
    // Convert hash buffer to hexadecimal string
    return Array.from(new Uint8Array(hashBuffer))
        .map(b => b.toString(16).padStart(2, '0'))
        .join('');
}

// Example usage with a sample block
const blockData = {
    index: 1,
    timestamp: Date.now(),
    data: "Transaction Data",
    previousHash: "0".repeat(64)  // Previous hash (64 zeros for example)
};

// Try to mine the block with difficulty 4 (four leading zeros)
const result = await mineBlock(JSON.stringify(blockData), 4);
console.log(`Found nonce: ${result.nonce}, Hash: ${result.hash}`);
# Python Mining Implementation using hashlib
import hashlib
import json
import time

def calculate_hash(data: str) -> str:
    """Calculate SHA-256 hash of input data."""
    return hashlib.sha256(data.encode()).hexdigest()

def mine_block(block_data: dict, difficulty: int) -> tuple[int, str]:
    """Mine a block by finding a hash with required number of leading zeros.
    
    Args:
        block_data: Dictionary containing block information
        difficulty: Number of leading zeros required
        
    Returns:
        Tuple of (nonce, hash) that satisfies the difficulty requirement
    """
    prefix = '0' * difficulty  # Create target prefix (e.g., "000")
    nonce = 0  # Start with nonce = 0
    
    while True:
        # Add current nonce to block data
        block_data['nonce'] = nonce
        # Convert block data to JSON string (sorted to ensure consistent hashing)
        block_str = json.dumps(block_data, sort_keys=True)
        # Calculate hash of block data with current nonce
        hash_result = calculate_hash(block_str)
        
        # Check if hash meets difficulty requirement
        if hash_result.startswith(prefix):
            return nonce, hash_result  # Found a valid hash!
        nonce += 1  # Try next nonce value

# Example usage with a sample block
block = {
    'index': 1,
    'timestamp': time.time(),
    'data': "Transaction Data",
    'previous_hash': "0" * 64  # Previous hash (64 zeros for example)
}

# Try to mine the block with difficulty 4 (four leading zeros)
nonce, hash_result = mine_block(block, 4)
print(f"Found nonce: {nonce}, Hash: {hash_result}")
// C++ Mining Implementation using OpenSSL
#include <openssl/sha.h>
#include <string>
#include <iomanip>
#include <sstream>

class BlockMiner {
private:
    // Helper function to calculate SHA-256 hash using OpenSSL
    static std::string calculateHash(const std::string& input) {
        unsigned char hash[SHA256_DIGEST_LENGTH];
        SHA256_CTX sha256;
        SHA256_Init(&sha256);
        SHA256_Update(&sha256, input.c_str(), input.length());
        SHA256_Final(hash, &sha256);

        // Convert hash bytes to hexadecimal string
        std::stringstream ss;
        for(int i = 0; i < SHA256_DIGEST_LENGTH; i++) {
            ss << std::hex << std::setw(2) << std::setfill('0') 
               << static_cast(hash[i]);
        }
        return ss.str();
    }

public:
    // Mine a block by finding a hash with required number of leading zeros
    static std::pair mineBlock(
        const std::string& data, 
        int difficulty
    ) {
        std::string prefix(difficulty, '0');  // Create target prefix (e.g., "000")
        uint64_t nonce = 0;  // Start with nonce = 0
        
        while (true) {
            // Combine data and current nonce
            std::string input = data + std::to_string(nonce);
            std::string hash = calculateHash(input);
            
            // Check if hash meets difficulty requirement
            if (hash.substr(0, difficulty) == prefix) {
                return {nonce, hash};  // Found a valid hash!
            }
            nonce++;  // Try next nonce value
        }
    }
};

// Example usage with a sample block
int main() {
    // Create sample block data as JSON string
    std::string blockData = R"({
        "index": 1,
        "timestamp": 1234567890,
        "data": "Transaction Data",
        "previousHash": "0000000000000000000000000000000000000000000000000000000000000000"
    })";
    
    // Try to mine the block with difficulty 4 (four leading zeros)
    auto [nonce, hash] = BlockMiner::mineBlock(blockData, 4);
    std::cout << "Found nonce: " << nonce << ", Hash: " << hash << std::endl;
    return 0;
}
// Java Mining Implementation using MessageDigest
import java.security.MessageDigest;
import java.nio.charset.StandardCharsets;

public class BlockMiner {
    // Helper function to calculate SHA-256 hash
    private static String calculateHash(String input) throws Exception {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
        
        StringBuilder hexString = new StringBuilder();
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) hexString.append('0');
            hexString.append(hex);
        }
        return hexString.toString();
    }
    
    // Mine a block by finding a hash with required number of leading zeros
    public static MiningResult mineBlock(String data, int difficulty) throws Exception {
        String prefix = "0".repeat(difficulty);  // Create target prefix (e.g., "000")
        long nonce = 0;  // Start with nonce = 0
        
        while (true) {
            // Combine data and current nonce
            String input = data + nonce;
            String hash = calculateHash(input);
            
            // Check if hash meets difficulty requirement
            if (hash.startsWith(prefix)) {
                return new MiningResult(nonce, hash);  // Found a valid hash!
            }
            nonce++;  // Try next nonce value
        }
    }
    
    // Example usage with a sample block
    public static void main(String[] args) throws Exception {
        // Create sample block data as JSON string
        String blockData = String.format("{" +
            "\"index\": 1," +
            "\"timestamp\": %d," +
            "\"data\": \"Transaction Data\"," +
            "\"previousHash\": \"%s\"" +
            "}", System.currentTimeMillis(), "0".repeat(64));
            
        // Try to mine the block with difficulty 4 (four leading zeros)
        MiningResult result = mineBlock(blockData, 4);
        System.out.printf("Found nonce: %d, Hash: %s%n", 
            result.nonce, result.hash);
    }
    
    // Helper class to hold mining result
    static class MiningResult {
        final long nonce;
        final String hash;
        
        MiningResult(long nonce, String hash) {
            this.nonce = nonce;
            this.hash = hash;
        }
    }
}
# Ruby Mining Implementation using Digest::SHA256
require 'digest'
require 'json'

class BlockMiner
  # Calculate SHA-256 hash of input data
  def self.calculate_hash(input)
    Digest::SHA256.hexdigest(input)
  end
  
  # Mine a block by finding a hash with required number of leading zeros
  def self.mine_block(data, difficulty)
    prefix = '0' * difficulty  # Create target prefix (e.g., "000")
    nonce = 0  # Start with nonce = 0
    
    loop do
      # Combine data and current nonce
      input = data + nonce.to_s
      hash = calculate_hash(input)
      
      # Check if hash meets difficulty requirement
      return [nonce, hash] if hash.start_with?(prefix)  # Found a valid hash!
      nonce += 1  # Try next nonce value
    end
  end
end

# Example usage with a sample block
block_data = {
  index: 1,
  timestamp: Time.now.to_i,
  data: "Transaction Data",
  previous_hash: '0' * 64  # Previous hash (64 zeros for example)
}.to_json

# Try to mine the block with difficulty 4 (four leading zeros)
nonce, hash = BlockMiner.mine_block(block_data, 4)
puts "Found nonce: #{nonce}, Hash: #{hash}"
// Swift Mining Implementation using CryptoKit
import Foundation
import CryptoKit

struct BlockMiner {
    // Calculate SHA-256 hash of input string
    static func calculateHash(_ input: String) -> String {
        let inputData = input.data(using: .utf8)!
        let hash = SHA256.hash(data: inputData)
        // Convert hash bytes to hexadecimal string
        return hash.compactMap { String(format: "%02x", $0) }.joined()
    }
    
    // Mine a block by finding a hash with required number of leading zeros
    static func mineBlock(data: String, difficulty: Int) -> (nonce: Int, hash: String) {
        let prefix = String(repeating: "0", count: difficulty)  // Create target prefix
        var nonce = 0  // Start with nonce = 0
        
        while true {
            // Combine data and current nonce
            let input = data + String(nonce)
            let hash = calculateHash(input)
            
            // Check if hash meets difficulty requirement
            if hash.hasPrefix(prefix) {
                return (nonce, hash)  // Found a valid hash!
            }
            nonce += 1  // Try next nonce value
        }
    }
}

// Example usage with a sample block
let blockData = [
    "index": 1,
    "timestamp": Date().timeIntervalSince1970,
    "data": "Transaction Data",
    "previousHash": String(repeating: "0", count: 64)  // Previous hash (64 zeros)
] as [String : Any]

// Convert block data to JSON string
let jsonData = try! JSONSerialization.data(withJSONObject: blockData)
let jsonString = String(data: jsonData, encoding: .utf8)!

// Try to mine the block with difficulty 4 (four leading zeros)
let (nonce, hash) = BlockMiner.mineBlock(data: jsonString, difficulty: 4)
print("Found nonce: \(nonce), Hash: \(hash)")
// Go Mining Implementation using crypto/sha256
package main

import (
    "crypto/sha256"
    "encoding/hex"
    "encoding/json"
    "fmt"
    "strings"
    "time"
)

// Calculate SHA-256 hash of input string
func calculateHash(input string) string {
    hash := sha256.Sum256([]byte(input))
    return hex.EncodeToString(hash[:])
}

// Mine a block by finding a hash with required number of leading zeros
func mineBlock(data string, difficulty int) (int, string) {
    prefix := strings.Repeat("0", difficulty)  // Create target prefix (e.g., "000")
    nonce := 0  // Start with nonce = 0
    
    for {
        // Combine data and current nonce
        input := data + fmt.Sprint(nonce)
        hash := calculateHash(input)
        
        // Check if hash meets difficulty requirement
        if strings.HasPrefix(hash, prefix) {
            return nonce, hash  // Found a valid hash!
        }
        nonce++  // Try next nonce value
    }
}

func main() {
    // Create sample block data
    blockData := struct {
        Index        int       `json:"index"`
        Timestamp    int64     `json:"timestamp"`
        Data         string    `json:"data"`
        PreviousHash string    `json:"previousHash"`
    }{
        Index:        1,
        Timestamp:    time.Now().Unix(),
        Data:         "Transaction Data",
        PreviousHash: strings.Repeat("0", 64),  // Previous hash (64 zeros)
    }
    
    // Convert block data to JSON string
    jsonData, _ := json.Marshal(blockData)
    
    // Try to mine the block with difficulty 4 (four leading zeros)
    nonce, hash := mineBlock(string(jsonData), 4)
    fmt.Printf("Found nonce: %d, Hash: %s\n", nonce, hash)
}
// Rust Mining Implementation using sha2 crate
use sha2::{Sha256, Digest};
use serde::{Serialize, Deserialize};
use std::time::{SystemTime, UNIX_EPOCH};

// Block structure definition
#[derive(Serialize)]
struct Block {
    index: u32,
    timestamp: u64,
    data: String,
    previous_hash: String,
}

// Calculate SHA-256 hash of input string
fn calculate_hash(input: &str) -> String {
    let mut hasher = Sha256::new();
    hasher.update(input.as_bytes());
    format!("{:x}", hasher.finalize())
}

// Mine a block by finding a hash with required number of leading zeros
fn mine_block(data: &str, difficulty: usize) -> (u64, String) {
    let prefix = "0".repeat(difficulty);  // Create target prefix (e.g., "000")
    let mut nonce = 0u64;  // Start with nonce = 0
    
    loop {
        // Combine data and current nonce
        let input = format!("{}{}", data, nonce);
        let hash = calculate_hash(&input);
        
        // Check if hash meets difficulty requirement
        if hash.starts_with(&prefix) {
            return (nonce, hash);  // Found a valid hash!
        }
        nonce += 1;  // Try next nonce value
    }
}

fn main() {
    // Create sample block data
    let block = Block {
        index: 1,
        timestamp: SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap()
            .as_secs(),
        data: String::from("Transaction Data"),
        previous_hash: "0".repeat(64),  // Previous hash (64 zeros)
    };
    
    // Convert block data to JSON string
    let json_data = serde_json::to_string(&block).unwrap();
    
    // Try to mine the block with difficulty 4 (four leading zeros)
    let (nonce, hash) = mine_block(&json_data, 4);
    println!("Found nonce: {}, Hash: {}", nonce, hash);
}

Understanding the Mathematics of Mining