从零到一:用 Rust 实现一个简单的区块链

8 阅读1分钟

区块链技术自比特币诞生以来,已经走过了十多年的发展历程。虽然这项技术常与加密货币联系在一起,但其底层原理实际上是一种分布式账本技术,具有去中心化、不可篡改、透明可追溯等特性。本文将带领读者用 Rust 语言从零开始实现一个简化版的区块链,通过实践来深入理解区块链的核心原理。

区块链的核心概念

在开始编码之前,我们先简要回顾一下区块链的几个核心概念:

  1. 区块(Block):区块链的基本组成单元,包含交易数据、时间戳、前一个区块的哈希值等信息
  2. 哈希(Hash):将任意长度的数据映射为固定长度字符串的数学函数,具有单向性和抗碰撞性
  3. 工作量证明(Proof of Work):一种共识机制,要求节点完成一定量的计算工作
  4. 链式结构:每个区块都包含前一个区块的哈希值,形成不可篡改的链式结构

项目结构设计

首先创建一个新的 Rust 项目:

cargo new simple_blockchain
cd simple_blockchain

Cargo.toml 中添加依赖:

[package]
name = "simple_blockchain"
version = "0.1.0"
edition = "2021"

[dependencies]
chrono = "0.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
sha2 = "0.10"
hex = "0.4"

实现区块结构

让我们从定义区块结构开始。在 src/main.rs 中:

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::fmt;

// 定义交易结构
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Transaction {
    sender: String,
    receiver: String,
    amount: f64,
    timestamp: DateTime<Utc>,
}

impl Transaction {
    fn new(sender: &str, receiver: &str, amount: f64) -> Self {
        Transaction {
            sender: sender.to_string(),
            receiver: receiver.to_string(),
            amount,
            timestamp: Utc::now(),
        }
    }
}

// 定义区块结构
#[derive(Debug, Clone, Serialize, Deserialize)]
struct Block {
    index: u64,
    timestamp: DateTime<Utc>,
    transactions: Vec<Transaction>,
    previous_hash: String,
    hash: String,
    nonce: u64,
    difficulty: u64,
}

impl Block {
    // 创建创世区块
    fn genesis() -> Self {
        let mut block = Block {
            index: 0,
            timestamp: Utc::now(),
            transactions: vec![Transaction::new(
                "0",
                "Genesis",
                1000000.0,
            )],
            previous_hash: "0".repeat(64),
            hash: String::new(),
            nonce: 0,
            difficulty: 4,
        };
        
        block.hash = block.calculate_hash();
        block
    }
    
    // 创建新区块
    fn new(
        index: u64,
        transactions: Vec<Transaction>,
        previous_hash: String,
        difficulty: u64,
    ) -> Self {
        let mut block = Block {
            index,
            timestamp: Utc::now(),
            transactions,
            previous_hash,
            hash: String::new(),
            nonce: 0,
            difficulty,
        };
        
        block.mine_block();
        block
    }
    
    // 计算区块哈希
    fn calculate_hash(&self) -> String {
        let data = format!(
            "{}{}{:?}{}{}",
            self.index,
            self.timestamp,
            self.transactions,
            self.previous_hash,
            self.nonce
        );
        
        let mut hasher = Sha256::new();
        hasher.update(data.as_bytes());
        let result = hasher.finalize();
        
        hex::encode(result)
    }
    
    // 挖矿:工作量证明
    fn mine_block(&mut self) {
        println!("开始挖矿区块 #{}...", self.index);
        
        let target = "0".repeat(self.difficulty as usize);
        
        loop {
            self.hash = self.calculate_hash();
            
            if &self.hash[0..self.difficulty as usize] == target {
                println!("区块 #{} 挖矿成功!哈希: {}", self.index, self.hash);
                println!("尝试次数: {}", self.nonce);
                break;
            }
            
            self.nonce += 1;
        }
    }
    
    // 验证区块是否有效
    fn is_valid(&self) -> bool {
        if self.hash != self.calculate_hash() {
            return false;
        }
        
        let target = "0".repeat(self.difficulty as usize);
        if &self.hash[0..self.difficulty as usize] != target {
            return false;
        }
        
        true
    }
}

impl fmt::Display for Block {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "区块 #{} [\n  时间戳: {}\n  交易数: {}\n  前哈希: {}...\n  当前哈希: {}...\n  随机数: {}\n  难度: {}\n]",
            self.index,
            self.timestamp,
            self.transactions.len(),
            &self.previous_hash[0..16],
            &self.hash[0..16],
            self.nonce,
            self.difficulty
        )
    }
}

实现区块链结构

接下来,我们实现区块链结构,它将管理所有的区块:

// 定义区块链结构
struct Blockchain {
    chain: Vec<Block>,
    difficulty: u64,
    pending_transactions: Vec<Transaction>,
}

impl Blockchain {
    fn new(difficulty: u64) -> Self {
        let mut blockchain = Blockchain {
            chain: Vec::new(),
            difficulty,
            pending_transactions: Vec::new(),
        };
        
        // 添加创世区块
        blockchain.chain.push(Block::genesis());
        blockchain
    }
    
    // 获取最后一个区块
    fn get_last_block(&self) -> &Block {
        self.chain.last().unwrap()
    }
    
    // 添加交易到待处理交易池
    fn add_transaction(&mut self, transaction: Transaction) {
        self.pending_transactions.push(transaction);
    }
    
    // 挖矿新区块
    fn mine_pending_transactions(&mut self, miner_address: &str) {
        // 添加矿工奖励交易
        let reward = Transaction::new(
            "0",
            miner_address,
            50.0, // 挖矿奖励
        );
        
        let mut transactions = self.pending_transactions.clone();
        transactions.push(reward);
        
        let new_block = Block::new(
            self.chain.len() as u64,
            transactions,
            self.get_last_block().hash.clone(),
            self.difficulty,
        );
        
        self.chain.push(new_block);
        self.pending_transactions.clear();
    }
    
    // 验证区块链的完整性
    fn is_chain_valid(&self) -> bool {
        for i in 1..self.chain.len() {
            let current_block = &self.chain[i];
            let previous_block = &self.chain[i - 1];
            
            // 验证当前区块的哈希是否正确
            if !current_block.is_valid() {
                println!("区块 #{} 无效", current_block.index);
                return false;
            }
            
            // 验证当前区块的前哈希是否等于前一个区块的哈希
            if current_block.previous_hash != previous_block.hash {
                println!("区块 #{} 的前哈希不匹配", current_block.index);
                return false;
            }
        }
        
        true
    }
    
    // 获取账户余额
    fn get_balance(&self, address: &str) -> f64 {
        let mut balance = 0.0;
        
        for block in &self.chain {
            for transaction in &block.transactions {
                if transaction.sender == address {
                    balance -= transaction.amount;
                }
                if transaction.receiver == address {
                    balance += transaction.amount;
                }
            }
        }
        
        balance
    }
    
    // 打印区块链信息
    fn print_chain(&self) {
        println!("\n=== 区块链信息 ===");
        println!("区块数量: {}", self.chain.len());
        println!("当前难度: {}", self.difficulty);
        println!("待处理交易: {}", self.pending_transactions.len());
        
        for block in &self.chain {
            println!("\n{}", block);
        }
        
        println!("区块链有效: {}", self.is_chain_valid());
    }
}

测试我们的区块链

现在让我们创建一个主函数来测试我们的区块链实现:

fn main() {
    println!("=== 简单区块链实现 ===\n");
    
    // 创建区块链,设置挖矿难度为4
    let mut blockchain = Blockchain::new(4);
    
    //