引言
区块链技术自比特币诞生以来,已经走过了十多年的发展历程。尽管这项技术听起来高深莫测,但其核心原理并不复杂。今天,我将带领大家用 Rust 语言从零开始实现一个极简的区块链系统。通过这个实践项目,你不仅能深入理解区块链的工作原理,还能掌握 Rust 在系统编程中的实际应用。
区块链的核心概念
在开始编码之前,我们先简要回顾一下区块链的几个核心概念:
- 区块(Block):存储交易数据的基本单位
- 链(Chain):按时间顺序连接的区块序列
- 哈希(Hash):区块的唯一标识符
- 工作量证明(Proof of Work):保证区块链安全性的共识机制
- 分布式网络:多个节点共同维护区块链的状态
项目结构设计
首先,我们创建项目的基本结构:
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)]
pub struct Transaction {
pub sender: String,
pub receiver: String,
pub amount: f64,
pub timestamp: DateTime<Utc>,
}
impl Transaction {
pub fn new(sender: String, receiver: String, amount: f64) -> Self {
Self {
sender,
receiver,
amount,
timestamp: Utc::now(),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Block {
pub index: u64,
pub timestamp: DateTime<Utc>,
pub transactions: Vec<Transaction>,
pub previous_hash: String,
pub hash: String,
pub nonce: u64,
}
impl Block {
pub fn new(
index: u64,
transactions: Vec<Transaction>,
previous_hash: String,
) -> Self {
let timestamp = Utc::now();
let mut block = Self {
index,
timestamp,
transactions,
previous_hash,
hash: String::new(),
nonce: 0,
};
block.hash = block.calculate_hash();
block
}
pub 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);
let result = hasher.finalize();
hex::encode(result)
}
pub fn mine_block(&mut self, difficulty: usize) {
let prefix = "0".repeat(difficulty);
while !self.hash.starts_with(&prefix) {
self.nonce += 1;
self.hash = self.calculate_hash();
}
println!("Block mined: {}", self.hash);
}
}
impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"Block #{} [Hash: {}, Previous: {}, Transactions: {}]",
self.index,
self.hash,
self.previous_hash,
self.transactions.len()
)
}
}
实现区块链结构
接下来,我们实现区块链的主体结构:
pub struct Blockchain {
pub chain: Vec<Block>,
pub pending_transactions: Vec<Transaction>,
pub difficulty: usize,
pub mining_reward: f64,
}
impl Blockchain {
pub fn new() -> Self {
let mut blockchain = Self {
chain: Vec::new(),
pending_transactions: Vec::new(),
difficulty: 2,
mining_reward: 100.0,
};
// 创建创世区块
blockchain.create_genesis_block();
blockchain
}
fn create_genesis_block(&mut self) {
let genesis_block = Block::new(
0,
vec![Transaction::new(
"0".to_string(),
"genesis".to_string(),
0.0,
)],
"0".to_string(),
);
self.chain.push(genesis_block);
}
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, mining_reward_address: String) {
let mut block = Block::new(
self.chain.len() as u64,
self.pending_transactions.clone(),
self.get_latest_block().hash.clone(),
);
block.mine_block(self.difficulty);
self.chain.push(block);
self.pending_transactions = vec![Transaction::new(
"0".to_string(),
mining_reward_address,
self.mining_reward,
)];
}
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 chain link 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
}
}
实现 P2P 网络基础
为了让我们的区块链能够运行在分布式网络中,我们需要实现基本的 P2P 功能。创建一个新的文件 src/network.rs:
use std::collections::HashSet;
use std::net::{TcpListener, TcpStream};
use std::io::{Read, Write};
use std::sync::{Arc, Mutex};
use std::thread;
use crate::{Blockchain, Transaction};
pub struct Node {
pub blockchain: Arc<Mutex<Blockchain>>,
pub peers: Arc<Mutex<HashSet<String>>>,
pub address: String,
}
impl Node {
pub fn new(address: String) -> Self {
Self {
blockchain: Arc::new(Mutex::new(Blockchain::new())),
peers: Arc::new(Mutex::new(HashSet::new())),
address: address.clone(),
}
}
pub fn start_server(&self) {
let listener = TcpListener::bind(&self.address).unwrap();
let blockchain_clone = Arc::clone(&self.blockchain);
let peers_clone = Arc::clone(&self.peers);
thread::spawn(move || {
for stream in listener.incoming() {
match stream {
Ok(stream) => {
let blockchain = Arc::clone(&blockchain_clone);
let peers = Arc::clone(&peers_clone);
thread::spawn(move || {
handle_connection(stream, blockchain, peers);
});
}
Err(e) => {
eprintln!("Failed to establish connection: {}", e);
}
}
}
});
}
pub fn connect_to_peer(&mut self, address: &str) {
let mut peers = self.peers.lock().unwrap();
peers.insert(address.to_string());
// 发送握手消息
if let Ok(mut stream) = TcpStream::connect(address) {
let message = format!("CONNECT {}", self.address);
stream.write_all(message.as_bytes()).unwrap();
}
}
pub fn broadcast_transaction(&self, transaction: &Transaction) {
let peers = self.peers.lock().unwrap();
let message = serde_json::to_string(transaction).unwrap();
for peer in peers.iter() {
if let Ok(mut stream) = TcpStream::connect(peer) {
let msg = format!("TRANSACTION {}", message);
stream.write_all(msg.as_bytes()).