The Accounting Battle - UTXO vs Account Model
Have you ever wondered how a blockchain remembers who owns what?
At its heart, every blockchain is just a database. But how that database tracks who owns what determines how fast, private, and “smart” the network can be.
As the title mentions, there are 2 main ways of handling accounts in the blockchain, one is how Bitcoin does it and second how Ethereum does it.
1. The UTXO Model (Bitcoin Style)
Used by Bitcoin, Litecoin, Dogecoin and other coins. The Unspent Transaction Output (UTXO) model doesn't store "balances". Instead, it stores "receipts" of unspent money.
The Logic: You don't have a "balance" on the blockchain. Instead, you have a collection of "unspent" chunks of crypto (UTXOs).
How it works: Imagine you have three $5 bills in your physical wallet. You don't have a "balance" of $15; you have three separate objects. If you want to buy a $12 sandwich, you hand over all three bills, and the cashier gives you $3 back.
The Transaction:
Inputs: Your three $5 "bills" (UTXOs).
Outputs: $12 to the shop + $3 back to you (a new UTXO).
Think of this exactly like having only cash, you know the total amount you have, but it's not one piece instead it's many UTXOs.
And every UTXO you spend is marked as spent so you can no longer use it (TXO: spent Transaction Output).
Note: The User UTXOs are stored in multiple blocks not only one.
But wait how do we know what UTXOs user has, and how do we look for them?
To find user's money, a Node would need to scan the entire history of the blockchain. It looks for every transaction output that matches your Public Key (your address).
- It gathers all those outputs.
- It checks if any of them were spent in later blocks.
- Whatever is left over and unspent is your UTXO Set.
But isn't this too slow, each time someone sends a transaction we scan the whole blockchain?
Thankfully, no. That would make the network crawl. To solve this, nodes maintain a separate database called the UTXO Set (in Bitcoin Core, this is stored in a database called chainstate).
- This database only contains Unspent outputs.
- As soon as a UTXO is spent, it is deleted from this "fast" database.
- As soon as a new one is created, it is added.
So, when you send a transaction, you provide a Pointer (the Transaction ID of where you got the money).
- The node takes that ID and looks it up in the
chainstate. - If it finds it: "Great, this money exists and is unspent."
- The node then deletes that entry from
chainstate(since it's now spent) and adds the new outputs you just created.
Now that we covered some aspects of UTXOs, let's move to the other way of handling accounting.
2. The Account Model (Ethereum Style)
Used by Ethereum and Solana, the Account Model is much closer to how modern banking apps work.
How it works: The blockchain maintains a global state — a massive table of addresses. Each address has a "balance" field.
The Transaction: When Alice sends 5 ETH to Bob, the EVM (Ethereum Virtual Machine) checks if Alice.balance >= 5. If yes, it performs: Alice.balance -= 5 and Bob.balance += 5.
But wait… what stops someone from sending the same transaction twice?
If the Account Model is just a "massive table of addresses," we run into a serious security flaw called a Replay Attack.
Imagine Alice sends a transaction: "Subtract 5 ETH from Alice and add 5 ETH to Bob." Since this is just a digital message signed by Alice, what stops Bob from "replaying" that same message over and over? Without a safeguard, Bob could broadcast that same transaction ten times, and the network would keep subtracting 5 ETH from Alice until her account is empty!
Unlike UTXOs that we mark as spent each time we use them, the account balance is just a number that we can add or subtract from.
The solution is what we call Nonce (Number used Once)
To prevent this, Ethereum adds a tiny but powerful piece of data to every account: the Nonce.
How it works: The Nonce is a counter that starts at 0. Every time you send a transaction, your Nonce must increase by exactly 1.
The Rule: The Ethereum network will only accept a transaction if its Nonce is the exact next number in the sequence for that specific account.
How does the network keep track of all these Nonces and Balances?
In the UTXO model, we saw that we can just look at the chainstate. But in Ethereum, we have millions of accounts, each with a balance, a nonce, and potentially smart contract code.
Searching a "massive table" every time a transaction happens would be incredibly slow as the network grows. To make this "Account Model" actually work at scale, we need a special data structure…
The Merkle trees and The Merkle Patricia Tries: next article topic.
References
-
Bitcoin Whitepaper - Satoshi Nakamoto
- https://bitcoin.org/bitcoin.pdf
- Original introduction to the UTXO model and blockchain technology
-
Ethereum Documentation - State and Accounts
- https://ethereum.org/en/developers/docs/accounts/
- Official documentation on Ethereum's account model
-
Bitcoin Core Repository - UTXO Set
- https://github.com/bitcoin/bitcoin
- Source code reference for chainstate database implementation
-
Ethereum Yellow Paper - Gavin Wood
- https://ethereum.org/en/developers/docs/apis/json-rpc/
- Technical specification of Ethereum's protocol and state management
-
Replay Attack Prevention - Ethereum Improvement Proposals (EIP-155)
- https://eips.ethereum.org/EIPS/eip-155
- Details on transaction replay protection using chain IDs and nonces