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

  1. Genesis Block: First block in the chain
  2. Add Transactions: Add to pending pool
  3. Mine Block: Create new block with transactions
  4. Validate Chain: Ensure blockchain integrity
  5. Transfer Funds: Update balances

Complete Implementation

RUST
impl 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

RUST
fn 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!

Hard

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"));
}