Skip to content

Overview — The Account Model

The book asks one question over and over: how do you build a single global state machine that runs at hardware speed without falling apart? Proof of History gave us a clock — an ordering of events that validators can agree on without talking to each other. But ordering events is only useful if the events themselves can run fast, and ideally in parallel. That is where this part begins.

To run transactions in parallel you need one thing above all: you must know, before a transaction runs, exactly which pieces of state it will read and write. Two transactions that touch disjoint state can run at the same time on different cores; two that touch the same state cannot. So the whole performance story rests on a data-layout question — how do you arrange global state so a transaction’s footprint is knowable up front? This part answers it. The answer is the account model, and it starts with a single decision: separate code from state.

Here is the core claim of this entire part, in one line:

State and code are separable. Accounts hold state; programs hold only code.

That sounds almost too simple to matter. It is the opposite. Nearly everything Solana does differently — parallel execution, cheap state, predictable fees, program-derived addresses — falls out of this one split. Get it now and the rest of the book stops looking like a bag of tricks and starts looking like consequences.

The account model in one picture
─────────────────────────────────
PROGRAMS (code only, stateless) ACCOUNTS (state only)
┌─────────────────────────┐ ┌──────────────────────────┐
│ System Program │ owns ───► │ Alice's wallet │
│ Token Program │ │ lamports, no data │
│ your Counter program │──── owns ──► │ a Counter's state buffer │
└─────────────────────────┘ └──────────────────────────┘
▲ ▲
│ pure functions over accounts │ named by a 32-byte Pubkey
└──────────────────────────────────────────┘
one flat global map: Pubkey → Account

Global state is not a tree of contracts each hiding its own storage. It is one flat key→value map: a 32-byte public key (Pubkey) points at an Account. Every wallet, every token balance, every piece of program state, and even the programs themselves live as entries in that single map. There is exactly one namespace for all state on the chain.

What an account is (previewed, not yet taught)

Section titled “What an account is (previewed, not yet taught)”

An account is deliberately dumb. In real Solana it is five fields:

Account
├── lamports u64 native balance (1 SOL = 1_000_000_000 lamports)
├── owner Pubkey the program allowed to change data / debit lamports
├── data [u8] an opaque byte buffer the owner interprets
├── executable bool is this account itself a program (code)?
└── rent_epoch u64 rent accounting (largely vestigial after rent-exemption)

The whole part unpacks these fields, but notice the shape already:

  • lamports is the only value the runtime itself understands. Everything else is opaque.
  • data is just bytes. The runtime never looks inside it. Only the owner program knows what type lives there — a token balance, a counter, a governance proposal.
  • owner is the access-control rule of the entire system: only the owner program may write an account’s data or debit its lamports.
  • executable is how “code is an account too” is expressed — a program is an account whose data is its compiled bytecode and whose executable flag is set.

The running model for this part strips the last two fields, because our miniature runtime does not load bytecode or charge rent. In solmini, the book’s companion crate, an account is exactly this:

#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct Account {
pub lamports: u64, // native balance (Solana's smallest unit)
pub data: Vec<u8>, // opaque buffer a program interprets however it likes
pub owner: Pubkey, // the program id allowed to mutate this account's data
}

That three-field struct is the entire data model you will map onto real Anchor by the end of the part. Every page below builds on it.

The Ethereum contrast (it recurs through the whole part)

Section titled “The Ethereum contrast (it recurs through the whole part)”

If you have any Ethereum background, the account model will feel inverted, so name the contrast now — it comes back on nearly every page.

Ethereum Solana
──────── ──────
contract account program account (code only, STATELESS)
= code + its OWN storage owns ▼
data accounts (typed buffers + lamports)
state hidden INSIDE the contract state in NAMED, EXTERNAL accounts
→ footprint unknown until you run → footprint declared up front

On Ethereum a contract is its code and it holds its own storage inside itself. That is intuitive, but it has a hidden cost: you cannot know which storage slots a contract call will touch until you actually execute it, because that storage is the contract’s private business. So the runtime must execute calls one at a time — it cannot tell in advance whether two calls collide.

Solana pulls code and state apart. A program is pure code that owns no state. All mutable state lives in separate, externally named accounts that the program owns. Because state now lives in named, external accounts, a transaction can list the accounts it will touch before it runs — and that list is precisely the information a scheduler needs to know which transactions are independent. The account model is not just a different data layout. It is the precondition for parallel execution. That single sentence is the thread this part exists to prove.

What does the account model force you to understand? That state and code are separable, and that separating them is what makes a transaction’s footprint knowable in advance. Knowability is the whole game: it is the one fact the parallel scheduler (later in the book) depends on. Ethereum hides state inside contracts and pays for it with serial execution; Solana exposes state as named accounts and buys the right to run transactions side by side. Everything in this part is a detail of how that exposure works — and every later part is a payoff that only exists because the footprint was knowable up front.

Read these in order. Each one adds a single idea to the flat Pubkey → Account map above.

#PageWhat it addsThe one idea
2Everything Is an Accountthe flat global map and the five account fields, taught in fullwallets, state, and code are all entries in one Pubkey → Account map
3Stateless Programs Act on Accountsprograms as pure functions over a passed-in account listcode holds no state; it mutates the accounts a transaction hands it
4Program Derived Addresses (PDAs)deterministic, keyless addresses a program ownshow a program gets accounts it controls without a private key
4Contrast: Contract-Owned Storage vs External Accountsthe Ethereum comparison in depthwhy external named state is what unlocks parallelism
900Revision — The Account Modela recap of the whole partthe part compressed to what you must retain

By the end you will be able to point at a real Anchor #[account] struct, a #[derive(Accounts)] context, and a declare_id!, and say exactly which piece of this flat map each one names — and why that naming is what lets Solana run at hardware speed.

The first job is to make the flat map concrete and teach all five fields properly: Everything Is an Account.

  1. State the core thesis of this part in one sentence, and name the single property it is designed to give a transaction.
  2. Solana’s global state is described as a “flat map.” What are the keys, what are the values, and what kinds of things live in it that might surprise someone from Ethereum?
  3. Of the five account fields, only one is understood by the runtime itself; the rest are opaque to it. Which one, and who gives meaning to the data field?
  4. Ethereum stores a contract’s state inside the contract; Solana stores a program’s state in external accounts. Why does that one difference determine whether transactions can run in parallel?
  5. The owner field is called “the access-control rule of the entire system.” What exactly does an account’s owner get to do that nothing else can?
Show answers
  1. State and code are separable: accounts hold state, programs hold only code. It is designed to make a transaction’s footprint knowable before it runs — the precondition for running independent transactions in parallel.
  2. The keys are 32-byte public keys (Pubkey); the values are Accounts (lamports + owner + data, plus executable/rent_epoch in real Solana). Everything lives in this one map: wallets, token balances, program state — and the programs themselves, since code is stored in an account with its executable flag set. There is a single global namespace for all state.
  3. Only lamports (the native balance) is understood directly by the runtime. The data buffer is just opaque bytes; only the account’s owner program knows what type those bytes represent and how to interpret them.
  4. If state is hidden inside a contract, the runtime cannot know which state a call touches until it executes it, so it must run calls serially (any two might collide). If state lives in named external accounts, a transaction can declare its accounts up front, so the runtime can see which transactions are independent before executing and run those simultaneously.
  5. Only an account’s owner program may change its data buffer and debit its lamports. That single rule is how the flat, shared map stays safe: anyone can name any account, but only the owner can mutate it.