Solana Architecture Overview

Solana is a high-performance blockchain designed for speed and scale. This chapter provides a comprehensive overview of Solana's architecture before we dive into specific components.

Why Solana?

Solana was designed to solve the blockchain trilemma—achieving decentralization, security, AND scalability without major compromises.

Performance Targets

MetricEthereumSolana
Block Time~12 seconds~400ms
Throughput~30 TPS65,000+ TPS (theoretical)
Finality~13 minutes~400ms (confirmed)
Transaction Cost$1-50+~$0.00025

Key Innovations

Solana achieves this through eight core innovations:

Text
1. Proof of History (PoH)
   └── Cryptographic clock for ordering

2. Tower BFT
   └── PoH-optimized consensus

3. Turbine
   └── Block propagation protocol

4. Gulf Stream
   └── Mempool-less transaction forwarding

5. Sealevel
   └── Parallel smart contract runtime

6. Pipelining
   └── Transaction processing optimization

7. Cloudbreak
   └── Horizontally-scaled accounts database

8. Archivers
   └── Distributed ledger storage

Architecture Diagram

Text
                         ┌─────────────────────────────────────┐
                         │           Solana Network            │
                         └─────────────────────────────────────┘
                                          │
              ┌───────────────────────────┼───────────────────────────┐
              │                           │                           │
              ▼                           ▼                           ▼
     ┌─────────────────┐         ┌─────────────────┐         ┌─────────────────┐
     │   Validator 1   │         │   Validator 2   │         │   Validator N   │
     │                 │◄───────►│                 │◄───────►│                 │
     │ ┌─────────────┐ │         │ ┌─────────────┐ │         │ ┌─────────────┐ │
     │ │  PoH Gen    │ │         │ │  PoH Verify │ │         │ │  PoH Verify │ │
     │ └─────────────┘ │         │ └─────────────┘ │         │ └─────────────┘ │
     │ ┌─────────────┐ │         │ ┌─────────────┐ │         │ ┌─────────────┐ │
     │ │  TPU        │ │         │ │  TVU        │ │         │ │  TVU        │ │
     │ └─────────────┘ │         │ └─────────────┘ │         │ └─────────────┘ │
     │ ┌─────────────┐ │         │ ┌─────────────┐ │         │ ┌─────────────┐ │
     │ │  Sealevel   │ │         │ │  Sealevel   │ │         │ │  Sealevel   │ │
     │ └─────────────┘ │         │ └─────────────┘ │         │ └─────────────┘ │
     └────────┬────────┘         └────────┬────────┘         └────────┬────────┘
              │                           │                           │
              │         Gossip Protocol   │                           │
              └───────────────────────────┴───────────────────────────┘
                                          │
                         ┌────────────────┼────────────────┐
                         │                │                │
                    ┌────┴────┐      ┌────┴────┐      ┌────┴────┐
                    │ RPC Node│      │ RPC Node│      │ RPC Node│
                    └────┬────┘      └────┬────┘      └────┬────┘
                         │                │                │
                    ┌────┴────┐      ┌────┴────┐      ┌────┴────┐
                    │  dApp   │      │  dApp   │      │  Wallet │
                    └─────────┘      └─────────┘      └─────────┘

Core Components

1. Transaction Processing Unit (TPU)

The TPU is the leader's transaction processing pipeline:

Text
Transaction Flow Through TPU:
─────────────────────────────────────────────────────────────────►

┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
│  Fetch   │──►│ SigVerify│──►│  Banking │──►│Broadcast │
│  Stage   │   │  Stage   │   │  Stage   │   │  Stage   │
└──────────┘   └──────────┘   └──────────┘   └──────────┘
     │              │              │              │
     │              │              │              │
  Receive       Verify         Execute       Propagate
  packets     signatures    transactions      blocks

Time: ─────────────────────────────────────────────────►
      ~100μs       ~100μs        ~200μs         ASAP

2. Transaction Validation Unit (TVU)

Non-leader validators run the TVU:

Text
Block Verification Flow:
─────────────────────────────────────────────────────────────────►

┌──────────┐   ┌──────────┐   ┌──────────┐   ┌──────────┐
│ Receive  │──►│  Verify  │──►│  Replay  │──►│   Vote   │
│ Shreds   │   │  Shreds  │   │  Blocks  │   │          │
└──────────┘   └──────────┘   └──────────┘   └──────────┘
     │              │              │              │
     │              │              │              │
  Turbine       Erasure       Re-execute     Cast vote
  protocol      coding        transactions   for block

3. The Bank

The Bank manages account state:

TypeScript
// Conceptual Bank structure
interface Bank {
  // Current slot number
  slot: number;

  // Parent bank (for fork management)
  parent: Bank | null;

  // Account state
  accounts: AccountsDB;

  // PoH state
  pohState: ProofOfHistory;

  // Process a transaction
  processTransaction(tx: Transaction): Result<(), Error>;

  // Freeze the bank (no more changes)
  freeze(): void;

  // Get account data
  getAccount(pubkey: PublicKey): Account | null;
}

Transaction Lifecycle

Understanding how a transaction flows through Solana:

Text
1. CLIENT CREATES TRANSACTION
   ├── Specify instructions
   ├── List all accounts (with read/write flags)
   ├── Add recent blockhash
   └── Sign with required keys

2. TRANSACTION SENT TO RPC
   └── RPC forwards to current leader via Gulf Stream

3. LEADER RECEIVES (TPU)
   ├── Fetch stage: Receive from network
   ├── SigVerify stage: GPU-accelerated signature verification
   └── Banking stage: Execute in Sealevel

4. EXECUTION (Sealevel)
   ├── Load accounts from AccountsDB
   ├── Execute program instructions
   ├── Update account state
   └── Log results

5. ENTRY CREATED
   ├── Transactions grouped into entry
   ├── PoH hash recorded
   └── Entry added to block

6. BLOCK PROPAGATED (Turbine)
   ├── Block split into shreds
   ├── Erasure coded
   └── Propagated via tree structure

7. VALIDATORS VERIFY (TVU)
   ├── Reconstruct block
   ├── Verify PoH
   ├── Re-execute transactions
   └── Vote if valid

8. FINALITY
   ├── 2/3+ stake votes = "confirmed"
   ├── 31+ blocks built = "finalized"
   └── Transaction is permanent

Account Model Deep Dive

Solana uses a unique account model:

Text
Every piece of data is an Account:
┌─────────────────────────────────────────────────────────┐
│                        Account                          │
├─────────────────────────────────────────────────────────┤
│ pubkey: PublicKey        // Unique 32-byte identifier   │
│ lamports: u64            // Balance in lamports         │
│ data: Vec<u8>            // Arbitrary data              │
│ owner: PublicKey         // Program that owns this      │
│ executable: bool         // Is this a program?          │
│ rent_epoch: u64          // When rent was last paid     │
└─────────────────────────────────────────────────────────┘

Account Types

Text
1. SYSTEM ACCOUNTS (Native)
   └── Owned by System Program
   └── Hold SOL balances
   └── Can be assigned to programs

2. PROGRAM ACCOUNTS
   └── executable = true
   └── Contain BPF bytecode
   └── Immutable after deployment (usually)

3. DATA ACCOUNTS
   └── Owned by programs
   └── Store arbitrary data
   └── Programs read/write via instructions

4. PROGRAM DERIVED ADDRESSES (PDAs)
   └── Deterministically generated
   └── No private key
   └── Programs can sign for them

Account Relationships

Text
┌─────────────────┐         ┌─────────────────┐
│  Token Program  │◄────────│  Mint Account   │
│   (executable)  │ owns    │  (data: supply) │
└─────────────────┘         └─────────────────┘
         │
         │ owns
         ▼
┌─────────────────┐         ┌─────────────────┐
│  Token Account  │◄────────│   User Wallet   │
│  (data: balance)│ authority│   (system acc) │
└─────────────────┘         └─────────────────┘

Rent and Storage

Solana charges rent for account storage:

TypeScript
// Rent calculation
const LAMPORTS_PER_BYTE_YEAR = 3480;
const EXEMPTION_THRESHOLD_YEARS = 2;

function calculateRentExemption(dataLength: number): number {
  const accountSize = 128 + dataLength; // 128 byte header
  return accountSize * LAMPORTS_PER_BYTE_YEAR * EXEMPTION_THRESHOLD_YEARS;
}

// Examples:
// Empty account: ~890,880 lamports (~0.00089 SOL)
// 1KB data: ~7,908,480 lamports (~0.0079 SOL)
// 10KB data: ~78,308,480 lamports (~0.078 SOL)

Rent-Exempt Accounts

If an account holds >= 2 years of rent, it's rent-exempt:

Text
Account balance >= rent_exemption_minimum
        ↓
Account is never charged rent
        ↓
Account persists forever (or until closed)

Most accounts should be rent-exempt. Non-exempt accounts are gradually collected.

Programs (Smart Contracts)

Solana programs are compiled to BPF bytecode:

Text
Development:
┌──────────┐    ┌──────────┐    ┌──────────┐
│  Rust    │───►│ Compiler │───►│   BPF    │
│  Source  │    │  (LLVM)  │    │ Bytecode │
└──────────┘    └──────────┘    └──────────┘

Deployment:
┌──────────┐    ┌──────────┐    ┌──────────┐
│   BPF    │───►│  Deploy  │───►│ Program  │
│ Bytecode │    │   Tx     │    │ Account  │
└──────────┘    └──────────┘    └──────────┘

Program Execution

Rust
// Every Solana program has this entry point
pub fn process_instruction(
    program_id: &Pubkey,        // This program's ID
    accounts: &[AccountInfo],   // Accounts passed to instruction
    instruction_data: &[u8],    // Custom data for this call
) -> ProgramResult {
    // Your logic here
    Ok(())
}

// Programs are STATELESS
// All state is in accounts passed by the caller
// Programs can only modify accounts they OWN

Cross-Program Invocation (CPI)

Programs can call other programs:

Text
User Transaction:
┌────────────────────────────────────────┐
│ Instruction: Call Program A            │
│ Accounts: [Acc1, Acc2, Acc3, TokenProg]│
└────────────────────────────────────────┘
                   │
                   ▼
            ┌──────────────┐
            │  Program A   │
            └──────┬───────┘
                   │
                   │ CPI
                   ▼
            ┌──────────────┐
            │ Token Program│
            │  (transfer)  │
            └──────────────┘

CPI Code Example

Rust
use solana_program::{
    account_info::AccountInfo,
    entrypoint::ProgramResult,
    program::invoke,
    pubkey::Pubkey,
};

pub fn process_with_cpi(
    accounts: &[AccountInfo],
) -> ProgramResult {
    let token_program = &accounts[0];
    let source = &accounts[1];
    let destination = &accounts[2];
    let authority = &accounts[3];

    // Create transfer instruction
    let transfer_ix = spl_token::instruction::transfer(
        token_program.key,
        source.key,
        destination.key,
        authority.key,
        &[],
        1000,
    )?;

    // Execute CPI
    invoke(
        &transfer_ix,
        &[source.clone(), destination.clone(), authority.clone()],
    )?;

    Ok(())
}

Network Clusters

Solana has multiple networks:

ClusterPurposeURL
Mainnet BetaProductionhttps://api.mainnet-beta.solana.com
DevnetDevelopmenthttps://api.devnet.solana.com
TestnetValidator testinghttps://api.testnet.solana.com
LocalnetLocal developmenthttp://localhost:8899

Connecting to Clusters

TypeScript
import { Connection, clusterApiUrl } from "@solana/web3.js";

// Connect to devnet
const devnet = new Connection(clusterApiUrl("devnet"));

// Connect to mainnet
const mainnet = new Connection(clusterApiUrl("mainnet-beta"));

// Connect to local validator
const local = new Connection("http://localhost:8899");

// Custom RPC (recommended for production)
const custom = new Connection("https://your-rpc-provider.com");

Key Takeaways

  1. Solana optimizes for throughput through parallel execution and PoH
  2. Everything is an account: programs, data, tokens, NFTs
  3. Programs are stateless: all state lives in accounts
  4. Upfront account declaration enables parallelism
  5. Fast finality (~400ms confirmed) enables responsive apps

What's Next

The following chapters dive deep into each component:


Next: Validators vs RPC Nodes