Building a Complete Blockchain
Putting it all together: building a functional blockchain from scratch.
Advanced⏱️ 60 min📚 Prerequisites: 1
Building a Complete Blockchain
Let's build a complete, functional blockchain that combines all the concepts we've learned!
Project Structure
RUST// Complete blockchain implementation use std::collections::HashMap; use std::time::{SystemTime, UNIX_EPOCH}; struct Transaction { from: String, to: String, amount: u64, fee: u64, timestamp: u64, } struct Block { index: u64, timestamp: u64, transactions: Vec<Transaction>, previous_hash: String, hash: String, nonce: u64, } struct Blockchain { blocks: Vec<Block>, balances: HashMap<String, u64>, pending_transactions: Vec<Transaction>, }
Core Functionality
- Genesis Block: First block in the chain
- Add Transactions: Add to pending pool
- Mine Block: Create new block with transactions
- Validate Chain: Ensure blockchain integrity
- Transfer Funds: Update balances
Complete Implementation
RUSTimpl Blockchain { fn new() -> Self { let mut chain = Blockchain { blocks: Vec::new(), balances: HashMap::new(), pending_transactions: Vec::new(), }; // Create genesis block let genesis = Block { index: 0, timestamp: current_timestamp(), transactions: Vec::new(), previous_hash: String::from("0"), hash: String::from("genesis"), nonce: 0, }; chain.blocks.push(genesis); chain } fn add_transaction(&mut self, tx: Transaction) -> Result<(), String> { // Validate transaction let balance = self.balances.get(&tx.from).copied().unwrap_or(0); if balance < tx.amount + tx.fee { return Err(String::from("Insufficient balance")); } self.pending_transactions.push(tx); Ok(()) } fn mine_block(&mut self, difficulty: usize) -> Result<(), String> { if self.pending_transactions.is_empty() { return Err(String::from("No transactions to mine")); } // Take transactions from pool let transactions: Vec<Transaction> = self.pending_transactions.drain(..).collect(); // Create block let previous_block = self.blocks.last().unwrap(); let mut block = Block { index: previous_block.index + 1, timestamp: current_timestamp(), transactions, previous_hash: previous_block.hash.clone(), hash: String::new(), nonce: 0, }; // Mine block (simplified) block.hash = format!("block_hash_{}", block.index); // Update balances for tx in &block.transactions { *self.balances.entry(tx.from.clone()).or_insert(0) -= tx.amount + tx.fee; *self.balances.entry(tx.to.clone()).or_insert(0) += tx.amount; } self.blocks.push(block); Ok(()) } fn get_balance(&self, address: &str) -> u64 { self.balances.get(address).copied().unwrap_or(0) } fn height(&self) -> usize { self.blocks.len() } }
Usage Example
RUSTfn main() { let mut blockchain = Blockchain::new(); // Initialize accounts blockchain.balances.insert(String::from("0xAlice"), 1000); blockchain.balances.insert(String::from("0xBob"), 500); // Add transactions blockchain.add_transaction(Transaction { from: String::from("0xAlice"), to: String::from("0xBob"), amount: 100, fee: 10, timestamp: current_timestamp(), }).unwrap(); // Mine block blockchain.mine_block(2).unwrap(); println!("Blockchain height: {}", blockchain.height()); println!("Alice balance: {}", blockchain.get_balance("0xAlice")); println!("Bob balance: {}", blockchain.get_balance("0xBob")); }
Next Steps
- Add cryptographic hashing
- Implement proper mining
- Add digital signatures
- Build P2P networking
- Create consensus mechanism
Code Examples
Complete Blockchain
Full blockchain implementation
RUST
use std::collections::HashMap;
struct Transaction {
from: String,
to: String,
amount: u64,
fee: u64,
}
struct Block {
index: u64,
transactions: Vec<Transaction>,
previous_hash: String,
hash: String,
}
struct Blockchain {
blocks: Vec<Block>,
balances: HashMap<String, u64>,
pending_transactions: Vec<Transaction>,
}
impl Blockchain {
fn new() -> Self {
let mut chain = Blockchain {
blocks: Vec::new(),
balances: HashMap::new(),
pending_transactions: Vec::new(),
};
chain.blocks.push(Block {
index: 0,
transactions: Vec::new(),
previous_hash: String::from("0"),
hash: String::from("genesis"),
});
chain
}
fn add_transaction(&mut self, tx: Transaction) -> Result<(), String> {
let balance = self.balances.get(&tx.from).copied().unwrap_or(0);
if balance < tx.amount + tx.fee {
return Err(String::from("Insufficient balance"));
}
self.pending_transactions.push(tx);
Ok(())
}
fn mine_block(&mut self) -> Result<(), String> {
if self.pending_transactions.is_empty() {
return Err(String::from("No transactions"));
}
let transactions = self.pending_transactions.drain(..).collect();
let previous = self.blocks.last().unwrap();
let block = Block {
index: previous.index + 1,
transactions,
previous_hash: previous.hash.clone(),
hash: format!("hash_{}", previous.index + 1),
};
for tx in &block.transactions {
*self.balances.entry(tx.from.clone()).or_insert(0) -= tx.amount + tx.fee;
*self.balances.entry(tx.to.clone()).or_insert(0) += tx.amount;
}
self.blocks.push(block);
Ok(())
}
fn get_balance(&self, address: &str) -> u64 {
self.balances.get(address).copied().unwrap_or(0)
}
}
fn main() {
let mut blockchain = Blockchain::new();
blockchain.balances.insert(String::from("0xAlice"), 1000);
blockchain.balances.insert(String::from("0xBob"), 0);
blockchain.add_transaction(Transaction {
from: String::from("0xAlice"),
to: String::from("0xBob"),
amount: 200,
fee: 10,
}).unwrap();
blockchain.mine_block().unwrap();
println!("Alice: {} tokens", blockchain.get_balance("0xAlice"));
println!("Bob: {} tokens", blockchain.get_balance("0xBob"));
println!("Blockchain height: {}", blockchain.blocks.len());
}Explanation:
This complete blockchain implementation includes transaction processing, block mining, and balance management. It demonstrates how all blockchain concepts work together.
Blockchain Operations
Common blockchain operations
RUST
struct Blockchain {
blocks: Vec<String>,
balances: std::collections::HashMap<String, u64>,
}
impl Blockchain {
fn new() -> Self {
let mut chain = Blockchain {
blocks: vec![String::from("genesis")],
balances: std::collections::HashMap::new(),
};
chain.balances.insert(String::from("0xAlice"), 1000);
chain
}
fn add_block(&mut self, block_hash: String) {
self.blocks.push(block_hash);
}
fn get_latest_block(&self) -> Option<&String> {
self.blocks.last()
}
fn get_chain_length(&self) -> usize {
self.blocks.len()
}
fn verify_chain(&self) -> bool {
!self.blocks.is_empty()
}
}
fn main() {
let mut blockchain = Blockchain::new();
blockchain.add_block(String::from("block1"));
blockchain.add_block(String::from("block2"));
println!("Chain length: {}", blockchain.get_chain_length());
println!("Latest block: {:?}", blockchain.get_latest_block());
println!("Chain valid: {}", blockchain.verify_chain());
}Explanation:
Common blockchain operations include adding blocks, getting the latest block, checking chain length, and verifying chain integrity. These are fundamental operations for any blockchain node.
Exercises
Build a Simple Blockchain
Create a blockchain that can add blocks and track balances!
Starter Code:
RUST
use std::collections::HashMap;
struct Block {
index: u64,
hash: String,
}
struct Blockchain {
blocks: Vec<Block>,
balances: HashMap<String, u64>,
}
fn main() {
let mut chain = Blockchain::new();
chain.balances.insert(String::from("0xAlice"), 1000);
chain.add_block(Block { index: 1, hash: String::from("hash1") });
println!("Alice balance: {}", chain.get_balance("0xAlice"));
}