区块链技术自比特币诞生以来,已经走过了十多年的发展历程。虽然这项技术常与加密货币联系在一起,但其底层原理实际上是一种分布式账本技术,具有去中心化、不可篡改、透明可追溯等特性。本文将带领读者用 Rust 语言从零开始实现一个简化版的区块链,通过实践来深入理解区块链的核心原理。
区块链的核心概念
在开始编码之前,我们先简要回顾一下区块链的几个核心概念:
- 区块(Block):区块链的基本组成单元,包含交易数据、时间戳、前一个区块的哈希值等信息
- 哈希(Hash):将任意长度的数据映射为固定长度字符串的数学函数,具有单向性和抗碰撞性
- 工作量证明(Proof of Work):一种共识机制,要求节点完成一定量的计算工作
- 链式结构:每个区块都包含前一个区块的哈希值,形成不可篡改的链式结构
项目结构设计
首先创建一个新的 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);
//