Solana Blockchain Overview

The Solana blockchain is a proof of stake blockchain with extra sauce:

  • Proof of history
  • Validators use something like bittorrent to fetch blocks and don't wait for all pieces to assume correctness
  • Offload data to something like filecoin so validators can run lite nodes (soon tm)

Proof of history uses a mechanism called nLocktime that postdates transactions using block height instead of the usual timestamp.

There is no mempool, instead there is deterministic leader selection and nodes forward transactions to future leaders.

Clients declare memory locations it needs beforehand.

Multiple transactions on the same program happen in parallel with SIMD instructions. Signatures are verified on GPU's

Solana uses

  1. ed25519 for encryption
  2. sha256 for hashing (same hashing as bitcoin).

Much more complicated to develop on than Ethereum based chains.

Even normal SOL transfers on Solana are handled by a smart contract.

Programs written in Rust are pretty limited. Public types should be basic in general forget about custom crates, you can't even use most of std::collections.

For example you cannot use HashMap without modifications because by default it actually uses some sneaky thread-local static state for caching keys. Static mutable state is forbidden in Solana so it won't work.

The anchor CLI also doesn't know how to turn HashMap into IDL. For now your easiest bet is to just use a sequence of key-value pairs unfortunately.

Solana Virtual Machine

The actual virtual machine responsible for executing programs is usually rBPF. Not all validators use the same one, but that is the canonical.

The specific format is a custom version of eBPF called Solana Bytecode Format (sBPF).

eBPF was originally created to filter packets in the kernel but has applications in profiling because of its efficiency.

This bytecode is processed by a virtual machine called rBPF. This virtual machine only has a set of 11 registers.

name feature set kind Solana ABI
r0 all GPR Return value
r1 all GPR Argument 0
r2 all GPR Argument 1
r3 all GPR Argument 2
r4 all GPR Argument 3
r5 all GPR Argument 4 or stack spill ptr
r6 all GPR Call-preserved
r7 all GPR Call-preserved
r8 all GPR Call-preserved
r9 all GPR Call-preserved
r10 all Frame pointer System register
r11 from v2 Stack pointer System register
pc all Program counter Hidden register

You first have your General-Purpose Registers (GPRs):

  • r0 holds the function's return data
  • r1 - r5 store function arguments, r5 holds "spillover" data which is represented by a pointer to some stack data.
  • r6 - r9 are values preserved across function calls.

After that we have:

  • r10 the frame pointer that references the current stack frame in memory
  • r11 the stack pointer that keeps track of where the top of the stack is
  • pc the program counter that holds the address of the current instruction being executed

The virtual machine can execute eBPF programs in two ways:

  1. An interpreter
  2. Just-in-Time (JIT) compilation to x86_64 machine code

Interpreters walk each instruction one-by-one. This adds a slight runtime overhead in exchange for a big reduction in load time.

JIT is favored as it makes the runtime execution faster at the cost of a longer load time due to the increased initial compilation.

Development Cycle

The development cycle on Solana looks like this:

  1. Code your program in rust
  2. Build your program which should generate an Interface Description Language (IDL) JSON file.
  3. Generate a client from this IDL file
  4. Test the programs behavior acting as a client of the chain

These are our system specs. They test behavior from the perspective of the user with all the bells and whistles of the blockchain.

The solana-test-validator can be used to set up a local chain to try these transactions out on and fetch the data to see if it is what we expect.