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!
Total Blocks: 0
Average Mining Time: 0 ms
Mining in blockchain is essentially a mathematical puzzle that requires finding a hash that meets certain criteria. Here's how it works:
// 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);
}