引言
区块链技术自比特币诞生以来,已经走过了十多年的发展历程。虽然这项技术常常与加密货币联系在一起,但其底层原理——分布式账本、共识机制、密码学等——在金融、供应链、数字身份等领域都有着广泛的应用前景。
对于开发者来说,理解区块链最好的方式就是亲手实现一个简化版本。今天,我将带领大家使用 Rust 语言,从零开始构建一个简单的区块链系统。选择 Rust 是因为它的安全性、性能和并发特性特别适合构建区块链这类对安全性要求极高的系统。
一、区块链基础概念回顾
在开始编码之前,让我们先回顾几个核心概念:
- 区块(Block):区块链的基本组成单位,包含交易数据、时间戳、前一个区块的哈希等
- 哈希(Hash):将任意长度的数据映射为固定长度的字符串,具有单向性和抗碰撞性
- 工作量证明(Proof of Work):一种共识机制,要求节点完成一定的计算工作
- 默克尔树(Merkle Tree):高效验证数据完整性的数据结构
二、项目结构设计
首先创建我们的项目:
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"
三、核心数据结构实现
3.1 交易结构
// src/transaction.rs
use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Transaction {
pub sender: String,
pub receiver: String,
pub amount: f64,
pub timestamp: i64,
}
impl Transaction {
pub fn new(sender: String, receiver: String, amount: f64) -> Self {
Self {
sender,
receiver,
amount,
timestamp: chrono::Utc::now().timestamp(),
}
}
}
impl fmt::Display for Transaction {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Transaction {{ sender: {}, receiver: {}, amount: {}, timestamp: {} }}",
self.sender, self.receiver, self.amount, self.timestamp
)
}
}
3.2 区块结构
// src/block.rs
use crate::transaction::Transaction;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use std::fmt;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Block {
pub index: u64,
pub timestamp: i64,
pub transactions: Vec<Transaction>,
pub previous_hash: String,
pub hash: String,
pub nonce: u64,
pub difficulty: u64,
}
impl Block {
pub fn new(
index: u64,
transactions: Vec<Transaction>,
previous_hash: String,
difficulty: u64,
) -> Self {
let timestamp = Utc::now().timestamp();
let mut block = Self {
index,
timestamp,
transactions,
previous_hash,
hash: String::new(),
nonce: 0,
difficulty,
};
block.hash = block.calculate_hash();
block
}
pub fn calculate_hash(&self) -> String {
let mut hasher = Sha256::new();
let data = format!(
"{}{}{:?}{}{}",
self.index,
self.timestamp,
self.transactions,
self.previous_hash,
self.nonce
);
hasher.update(data);
let result = hasher.finalize();
hex::encode(result)
}
pub fn mine_block(&mut self) {
println!("Mining block {}...", self.index);
while !self.is_hash_valid() {
self.nonce += 1;
self.hash = self.calculate_hash();
}
println!("Block mined: {}", self.hash);
}
fn is_hash_valid(&self) -> bool {
let target = "0".repeat(self.difficulty as usize);
&self.hash[0..self.difficulty as usize] == target
}
}
impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let datetime: DateTime<Utc> = DateTime::from_timestamp(self.timestamp, 0).unwrap();
write!(
f,
"Block #{} [\n Hash: {}\n Previous Hash: {}\n Timestamp: {}\n Transactions: {}\n Nonce: {}\n Difficulty: {}\n]",
self.index,
self.hash,
self.previous_hash,
datetime.format("%Y-%m-%d %H:%M:%S"),
self.transactions.len(),
self.nonce,
self.difficulty
)
}
}
3.3 区块链结构
// src/blockchain.rs
use crate::block::Block;
use crate::transaction::Transaction;
use std::fmt;
pub struct Blockchain {
pub chain: Vec<Block>,
pub difficulty: u64,
pub pending_transactions: Vec<Transaction>,
}
impl Blockchain {
pub fn new(difficulty: u64) -> Self {
let mut blockchain = Self {
chain: Vec::new(),
difficulty,
pending_transactions: Vec::new(),
};
// 创建创世区块
blockchain.create_genesis_block();
blockchain
}
fn create_genesis_block(&mut self) {
let genesis_block = Block::new(
0,
vec![Transaction::new(
"0".to_string(),
"0".to_string(),
0.0,
)],
"0".to_string(),
self.difficulty,
);
self.chain.push(genesis_block);
println!("Genesis block created");
}
pub fn get_latest_block(&self) -> &Block {
self.chain.last().unwrap()
}
pub fn add_transaction(&mut self, transaction: Transaction) {
self.pending_transactions.push(transaction);
}
pub fn mine_pending_transactions(&mut self, miner_address: String) {
if self.pending_transactions.is_empty() {
println!("No transactions to mine");
return;
}
// 添加矿工奖励交易
let reward = Transaction::new(
"system".to_string(),
miner_address,
1.0, // 挖矿奖励
);
let mut transactions = std::mem::take(&mut self.pending_transactions);
transactions.push(reward);
let mut new_block = Block::new(
self.chain.len() as u64,
transactions,
self.get_latest_block().hash.clone(),
self.difficulty,
);
new_block.mine_block();
self.chain.push(new_block);
println!("Block successfully mined and added to chain");
}
pub 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.hash != current_block.calculate_hash() {
println!("Invalid hash at block {}", i);
return false;
}
// 检查是否链接到前一个区块
if current_block.previous_hash != previous_block.hash {
println!("Invalid previous hash at block {}", i);
return false;
}
// 检查工作量证明
if !current_block.is_hash_valid() {
println!("Invalid proof of work at block {}", i);
return false;
}
}
true
}
pub 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
}
}
impl fmt::Display for Blockchain {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Blockchain ({} blocks):", self.chain.len())?;
writeln!(f, "Difficulty: {}", self.difficulty)?;
writeln!(f, "Pending transactions: {}", self.pending_transactions.len())?;
for (i, block) in self.