The significance of the selected blockchain accounting model is often underestimated, despite its substantial influence on user experience and potential for scalability. In this article, we will delve into the intricacies of the UTxO model, employed by Cardano and Bitcoin, and the account-based model, utilized by Ethereum and numerous other EVM-compatible blockchains. The article is replete with illustrative images. Upon perusal, you will comprehend why the validation of transactions in Ethereum is non-deterministic and often prone to failure, while Cardano validates transactions deterministically. We will also elucidate the distinction between the global states of Ethereum and Cardano.
Accounting In The Blockchain
Accounting serves as the bedrock of the modern financial landscape. Every financial institution is required to maintain a record of individual account balances and cash flows. This process must be completely reliable, secure, auditable, and most importantly, trustworthy.
Each ledger should be able to precisely indicate the ownership of assets at any given moment. In other words, user X had ownership of a certain quantity of Y assets at time Z. As financial interactions among individuals are a constant occurrence, the entries in the ledger are perpetually in flux. The system, be it centralized or decentralized, must accurately validate each transaction and duly record it in the ledger.
Historically, paper ledgers were the norm. However, with the emergence of computers, accounting underwent a digital transformation. The advent of blockchain technology has enabled the possibility of distributed accounting.
Blockchain networks can be perceived as a financial system. They can be viewed as a distributed ledger, that is, an accounting system that is not under the control of any central authority. Users can engage in financial transactions with each other in a Peer-to-Peer fashion. However, the intermediary, or the entity verifying the transaction, is not a central authority but a distributed network made up of volunteers. A set of volunteers are responsible for adding new financial entries to the ledger.
Satoshi Nakamoto implemented the UTxO model in Bitcoin. Vitalik Buterin opted for an account-based model for Ethereum. The IOG team chose to use the extended UTxO model for Cardano. Each of these variants has its own set of pros and cons, which we will delve into in the subsequent analysis.
State As A Prerequisite For Validating Transactions
A blockchain is technically a state machine. It remembers previous events, which is called a system state or a global state. These events, mostly represented by transactions, are interactions between users. The state can be changed under predefined conditions. Each protocol has implemented a set of rules and logic that allows the transition from state S-0 to state S-1. At regular intervals, the blockchain network appends new blocks within which the state transition occurs.
A block serves as the fundamental unit of transition from the existing state to a new state. It is made up of transactions. The block producer is tasked with crafting a new block following the protocol’s rules, meaning all conditions for block acceptance must be fulfilled. For a block to be deemed valid, it must only contain valid transactions.
The validation of a transaction—which is a transfer of value between two or more parties—necessitates some context or state for verification. The system must verify, among other things like valid signatures, that the sender’s account possesses adequate funds. It also has to prevent users from spending the same funds more than once, thereby tackling the infamous double-spend problem. It is not feasible to validate the transaction in isolation. The validator validates the transaction based on the ledger’s current state.
Both a node tasked with constructing a new block and a node that validates a newly created block, require knowledge of the context, that is, the current state of the ledger, for validation. The context for validation is the most recent valid block in the blockchain.
The block-producing node, which constructs a new block in a specific round, uses the last block representing the current state as input for validation. Subsequently, it takes all the transactions that are to be inserted into the new block and validates them. It then appends other required data to the block and diffuses it to the network.
In the picture, the node is trying to build a new block that would allow the transition from state S+3 to the next state S+4.
Both the node that produces a new block and all validating nodes must share the same validation context to transition to the new state. If various nodes were to use different contexts, the newly proposed block could be accepted only by a part of the nodes in the network. A valid block would only pass validation on those nodes that used the same context as the producer of the block.
The global state is constantly changing, with each newly added block or even with each additional validated transaction. There can be a considerable time lapse between the dispatch of a transaction and its processing by the network (i.e., the inclusion of the transaction in the block), during which the global state could change. The context that the user had at the time of dispatching the transaction may or may not alter when the block producer node incorporates the transaction into a new block candidate.
As depicted in the image, the user dispatched the TX 10 transaction shortly after the addition of block N+2. Following this, block N+3 was added, resulting in a change in the global state. The block producer node is in the process of constructing block N+4 and intends to incorporate transaction TX 10 into it. The addition of block N+3 altered the global state, which could potentially also modify the context directly associated with the validation of transaction TX 10.
The user had a context that was valid after adding block N+2. However, the block producer has a context that is valid after adding block N+3. So the context is different.
A key distinction between the UTxO and the account-based model is rooted in the context required by the validator for transaction validation, and the method by which transactions within a block are validated.
UTxO Basics
UTxO, an acronym for Unspent Transaction Output, refers to the output of a prior transaction that can be utilized in a future transaction.
The UTxO model does not recognize concepts such as account and balance. UTxOs function more like banknotes, capable of holding any nominal value. For instance, a UTxO could be 6.9 ADA, 47 ADA, or 459.7 ADA.
Cardano wallets assist users in managing UTxOs as if they were account balances. The three aforementioned UTxOs would appear as 513.6 ADA in Alice’s wallet.
So, what occurs when Alice wishes to send Bob 50 ADA?
Alice initiates a transaction in the Cardano wallet. The wallet must incorporate a set of UTxOs into the transaction, which will be adequate to cover a total of 50 ADA plus a 0.17 ADA fee.
The wallet could use a single input UTxO with a value of 459.7 ADA or two input UTxOs with values of 6.9 ADA and 47 ADA for the transaction. The wallet opts for the latter, using a total of 53.9 ADA as input for the transaction.
Typically, two UTxOs are created as an output of the transaction: 1) UTxO sent to the recipient, 2) UTxO returned to sender.
Notice that the transaction input is a larger amount of ADA than Alice intends to send to Bob (including the fee). It is the case in the majority of transactions and it aligns with the workings of the UTxO model.
Through the transaction, Alice spends 50.17 ADA, and through the newly created UTxO, 3.73 ADA is returned to her account. It happens only rarely that a UTxO is available with exactly the value that the sender wants to spend.
The transaction will result in 2 output UTxOs: 50 ADA for Bob and 3.73 ADA for Alice.
In the image below, you can observe the transaction as described. Both input UTxOs will be entirely spent and new output UTxOs will be generated from them. The value of the output UTxOs will be reduced by the transaction fee. Bob receives exactly 50 ADA. After sending the transaction, Alice will have 2 UTxOs in her wallet.
Cardano UTxO Model
Now you know how UTxO works from a user perspective. But what does this mean for transaction validation and the global state (context)?
UTxOs are independent and immutable objects, and exclusive access can be ensured. Once a UTxO is created as an output of a transaction, it remains unchanged until it is spent in a new transaction. When it is spent, it is consumed entirely and a new UTxO is created as an output of the new transaction.
The context a validator needs for validating a transaction is the set of all existing UTxOs at the time of validation. This set of UTxOs represents the active ledger state of the blockchain (global state).
When a transaction is submitted, it refers to one or more UTxOs as inputs, which are intended to be spent. The validator’s job is to check that:
- All input UTxOs are indeed part of the current global state, i.e., they are unspent and exist in the ledger.
- The total value of input UTxOs is greater than or equal to the total value of output UTxOs, ensuring the conservation of value (any difference becomes transaction fees).
- The transaction is correctly signed by the owners of the input UTxOs, ensuring only the rightful owners can spend the UTxOs.
The current state of the blockchain can be represented by the set of all unspent UTxOs, and the history of the blockchain can be seen as the graph of all UTxOs, both spent and unspent. This graph provides a complete, auditable history of all transactions that have ever occurred on the blockchain.
In the image below you can see how UTxOs are consumed by transactions. Output UTxOs (green) become input UTxOs (red). All UTxOs that have not been spent represent the current global state, or active UTxO set (blue). All blue UTxOs can become transaction input, i.e. be spent. Green UTxOs have already been spent, so they cannot be spent again.
To validate new transactions, it is not necessary to know the entire history of the blockchain, but only the active set of unspent UTxOs (blue UTxOs). However, getting an active set of UTxOs usually requires processing the entire blockchain history.
Note that the active set of UTxOs also includes those UTxOs created in the past.
In each state N in the figure, one block was produced. In the new state N+5, a context containing UTxOs from states N+2, N+3, and N+4 will be used for transaction validation. In the new block in state N+5, there will be transaction 14 trying to spend UTxO from transaction 10, and transaction 15 trying to spend UTxO from transaction 11.
In state N+5, a new block is created. Thus also new UTxOs are created and they will be inserted into the active set of UTxOs.
Each UTxO can be processed independently and in parallel, thus transaction validations are independent of each other. Now we come to the explanation of why transactions in Cardano are validated deterministically.
In the UTxO model, the validation of a transaction is predicated on its inputs and outputs, thereby obviating the need for a shared global state. This might seem somewhat contradictory to the previous text, where I stated that the active set of UTxOs constitutes a global state.
The entire UTxO set isn’t necessary for transaction validation, but only a small subset of it, specifically the input UTxOs. The remaining UTxOs in the UTxO set are irrelevant.
The validity of a transaction hinges solely on whether the consumed UTxOs are valid and unspent, and if the aggregate value of the inputs aligns with the aggregate value of the outputs.
Transaction inputs are independent immutable entities, hence validation is deterministic. It is feasible to predict with a high degree of certainty the outcome of the validation, including the output UTxOs.
It is possible to validate the transaction at the time of its submission, as it is certain that the inputs and outputs will remain unchanged at the time when the same transaction will be validated by the network, i.e., when the block producer incorporates the transaction into a new candidate block. The validation result will likely be identical in both instances. Thus, if the transaction passes local validation, it will also pass network validation.
The image depicts a validator that builds a new block, N+4, containing transactions TX 9 and TX 10. Inputs for validation are transactions that a node takes from its mem-pool and an active set of UTxOs that each node maintains.
The new transactions, TX 9 and TX 10 consume the old unspent output UTxOs (depicted by blue boxes) to form the input UTxOs (represented by red boxes). The sequence of transactions within the block is inconsequential, as the transactions are autonomous and do not impact each other.
Transaction TX 10, dispatched shortly after the generation of block N+2, can utilize the UTxO from the transaction within that block. The creation of the new N+4 block leads to the creation of new UTxOs from the input UTxOs. With the addition of the N+4 block to the blockchain, the network transitions to a new global state.
As illustrated in the image, a new block N+4 has been appended to the blockchain, resulting in a change in the global state. From the active set of UTxOs, UTxOs that were utilized in transactions contained in block N+4 will be eliminated (green). Newly created UTxOs (purple) were added to the set. The block is disseminated across the network, so the active set of UTxOs will be updated on all nodes in the network that accept the new block.
Deterministic Transaction Validation
Let’s revisit the example where Alice has 3 UTxOs in her wallet, each valued at 6.9 ADA, 47 ADA, and 459.7 ADA respectively.
Alice intends to send 5 ADAs each to three individuals - Bob, Carol, and Dave, initiating a new transaction each time. While Alice could dispatch a single transaction with three recipients, we deliberately opt for three separate transactions in this example to illustrate the concept of determinism. All transactions were dispatched in quick succession and can all be processed in the subsequent block.
As depicted in the image, each transaction utilizes one UTxO from Alice’s wallet (represented by red boxes), thereby ensuring that each transaction has an independent input. Each transaction yields two output UTxOs, represented by blue boxes. One UTxO, valued at 5 ADA, is allocated to the recipient, and a second UTxO, containing the remaining ADA, is returned to Alice’s wallet. The output UTxOs are determined at the time of transaction submission. For the sake of simplicity, transaction fees have been omitted in this example.
Upon successful local validation, transactions are disseminated across the network. All transactions are processed in the next block. In the subsequent image, you can observe the UTxOs in the wallets of Alice and all the recipients.
Take note that the input UTxOs have been consumed (depicted by the green boxes). Six new UTxOs were generated. Three UTxOs are returned to Alice. Each of the three recipients received one UTxO.
Observe that a value is conserved in each transaction. The sum of input UTxOs equals the sum of all output UTxOs. This holds for all transactions.
The sequence in which transactions are validated is inconsequential. The validation outcome would remain unchanged even if only one transaction made it to the next block and the remaining two were included in subsequent blocks (for any given reason). The global state can undergo any changes (across multiple blocks) between the validation of the transaction for Bob and the transactions for Carol and Dave, without impacting the validation of the transactions.
The validation of transactions is independent of each other due to the independence of the input UTxOs from each other. Hence, transaction validation is deterministic. Although the global state can change between the submission of a transaction and its processing by the network, it does not affect the outcome. The outcome (valid or invalid) can be determined solely based on the transaction itself and its input UTxOs.
Cardano’s global state is a compilation of independent and immutable UTxOs. Given the independence of these UTxOs, it is feasible to work with them in parallel. This implies that multiple transactions can be validated concurrently, which can significantly enhance the network’s throughput and efficiency.
In the picture, you can see how each transaction exclusively consumes UTxOs from the set of UTxOs. If all wallets and DApps are well designed, it cannot happen that two transactions consume the same UTxO. Consumed UTxOs are removed from the active set and new UTxOs are inserted.
Consuming UTxOs and adding new UTxOs to the set is not shown in the picture. The figure only illustrates how transactions reference input UTxOs.
An additional advantage is that the principles applicable to standard transactions also extend to the execution of validator scripts. It’s feasible to build a transaction that passes local validation, inclusive of script execution. Such a transaction is highly likely to pass network validation as well, given that all validation inputs, encompassing Datum and Redeemer, will remain consistent. In other words, even the script validator execution is not dependent on the external global state, but only on the transaction inputs. The only difference is that in the case of a script transaction, there are more inputs.
Determinism is conditioned by the exclusivity of access to UTxOs.
For standard transactions, the owner of the UTxO is the one who initiates the transactions. The wallet, acting as an agent, ensures that each UTxO is included in the transaction only once.
In our example, Alice owned all the UTxOs she wanted to spend. No one else was able to build a transaction with a valid signature.
If the wallet allowed two transactions to be submitted with the same UTxO as input, only one of the transactions would have a chance to succeed. However, a well-designed wallet will not allow the user to make such a mistake.
In the case of decentralized applications (DApps), the agent could be an entity other than the wallet (for example a batcher). This entity is responsible for providing exclusive access to UTxOs when constructing transactions. This ensures that each UTxO is used exactly once, preserving the determinism and security of the system.
In the image below you can see the liquidity pool with tokens X and Y. Batchers, which in this case are off-chain parts of DEX, are trying to do 2 swaps. Specifically, batcher 1 and batcher 3. Batchers must communicate with each other off-chain to ensure exclusive access to UTxOs in the liquidity pool (in the figure, off-chain communication is represented in blue).
If batchers were not communicating off-chain, they could try to use the same UTxO as transaction input. You can see this situation in the picture. Two batchers, who would not know each other’s intentions, could each submit a transaction whose input would be the same UTxO from the liquidity pool. Both transactions would pass local validation, but only one of those transactions would have a chance to pass network validation.
A Cardano transaction can fail if one agent, or several agents independently of each other, submit valid transactions with the same input UTxO. This situation is caused by a poorly designed wallet or Dapp.
In conclusion, we can state that Cardano transactions can be considered stateless.
Ethereum Account-Based Model
The Ethereum account-based model is easy to describe, as the behavior is similar to that of a regular bank account. Each account in Ethereum has a state associated with it, which includes its current balance of Ether (ETH). This balance is directly stored in the account’s state and can be updated by transactions.
In the figure below you can see the transition between the states. Note changes to user account balances. For simplicity, there is only one balance representing ETH.
Ethereum’s global state can be viewed as a database of all accounts and their current balances of different assets on the network. Each time a new block is added, the state of the system is updated according to all the transactions contained in that block.
This global state is stored locally on each node in the Ethereum network.
When a transaction is created, it specifies the sender account, the recipient account, the amount of Ether to be transferred, and optionally some data and a GAS. If the recipient is a contract account, the transaction triggers the execution of the contract’s code.
In the picture, you see a transaction that changes the global state N to state N+1. The transaction changes the balances in Alice and Bob’s accounts.
When a transaction is processed, the Ethereum network checks that the sender’s account has enough balance to cover the transfer and the gas cost. If the check passes, the network deducts the appropriate amount from the sender’s balance and adds it to the recipient’s balance (or to the contract’s balance, if the recipient is a contract account).
The global state of Ethereum is updated with each processed transaction, and this updated state is stored in each new block added to the Ethereum blockchain.
When a transaction is processed, the EVM computes the new state based on the current state and the transaction. This new state then becomes the current state for the next transaction. In this way, the state of the Ethereum blockchain is constantly evolving with each transaction.
As depicted in the image, the most recently added block is N+3, making the global state N+3. The network attempts to transition to a new state, N+4, and thus a new N+4 block is constructed. It’s important to note that the validation of transaction TX 1 in block N+4 (indicated by the green box) is dependent on the global state. TX 1 is the first transaction that the block producer node tries to include in a new block N+4.
The global state is represented by the current state of all accounts and smart contracts.
Once the transaction TX 1 is incorporated into block N+4, the subsequent transaction can be validated, which will be dependent on both the global state and the preceding transaction.
The picture shows that the validation of transaction TX 2 depends not only on the global state that was valid in block N+3 but also on transaction TX 1.
Ethereum block producer node processes transactions sequentially. Each additional transaction added to the newly built block changes the current global state of the node. When the block is diffused to the network, the validator nodes have to proceed the same, i.e. validate the transactions sequentially in exactly the order in which they were inserted into the block by the block producer node.
One of the reasons Ethereum transactions can fail is due to the unpredictability of the global state at the time of transaction validation. When a transaction is being constructed, it’s impossible to predict its outcome. The global state during transaction validation may differ from the state during transaction construction. In the interim between transaction submission and validation, the account balances of the transaction participants may have changed. These changes in account balances could prevent the transaction from being executed as originally intended by the submitter.
The figure illustrates the period between the submission of transaction TX 10, which occurred around block N+2 (state +2), and the subsequent validation of the transaction following the validation of transaction TX 9. During this period, numerous changes in the global state occurred. The validation of transaction TX 10 is dependent on both the global state and the changes introduced by transaction TX 9. Transaction TX 9, or any preceding change, could potentially cause transaction TX 10 to fail.
Transaction inputs are account balances and this is a shared resource. This means that at the time when the user submits the transaction, the account balance may be different than at the time when the transaction is validated. The transaction input is not deterministic as in the case of the UTxO model. It makes no sense to perform a local validation that would reveal if the transaction later passes network validation.
The best way to explain the differences is to go back to the example with Alice who wants to send 5 ETH to 3 recipients. In the case of Ethereum, all 3 submitted transactions have the same input, namely the balance of Alice’s account.
Validation of transactions takes place sequentially and each time 5 ETH is deducted from Alice’s balance and credited to the account of one of the recipients.
After adding a new block containing all transactions, user accounts will look like described in the picture.
This picture is not accurate. Later we will show how exactly the transition between states takes place.
Ethereum does validate transactions deterministically in the sense that given the same inputs (transaction data) and the same state (the current global state of the Ethereum blockchain), the EVM will always produce the same output. However, the result of transaction validation is non-deterministic. The validation outcome may differ from the user’s expectations.
During transaction submission, the user cannot predict what the global state will be at the time of transaction validation. Therefore, it’s impossible to estimate the validation result with a high degree of certainty. It can only be assumed.
If multiple users can access the same balance, it can easily happen that multiple transactions will be sent that deduct a certain amount from the same balance. Let’s say the amount is 1200 ETH. Three users independently submitted a transaction that is to deduct 500 ETH from the amount.
At the time of submitting transactions, the context may be such that it is possible to deduct the given amount from the balance. Not one of the transactions has yet been added to the global state (accepted by the network). However, once 2 transactions are validated, the third one fails. The two transactions subtracted a total of 1000 ETH. The balance will be only 200 ETH. So it is not possible to withdraw 500 ETH again. 2 transactions succeeded, and 1 failed.
In the picture, you can see that only 2 transactions of Bob and Carol who wanted to get (deduct) 500 ETH from the application account succeeded. Dave was unlucky and his transaction failed.
Even this picture is not completely accurate because it does not capture the gradual changes of balances during state transitions. The next picture will clarify it.
Now let’s explain the importance of order when inserting transactions into a block. Even if Dave had submitted the transaction first, before Bob and Carol, he might have been unlucky. It depends on the order in which the block producer node inserts transactions into the new block.
Analogously, if Dave and Carol’s transactions were inserted into the block first and second, Bob’s transaction would fail.
At the time when Bob, Carol, and Dave submit the transaction, they cannot ensure its successful validation by the network, because it is not possible to have access to the part of the balance exclusively for their transaction. This is different from the UTxO model, as it allows the transaction to have exclusive access to the input UTxO.
In the picture, you can see 4 states representing state changes within the block preparation. White transactions are in the mem-pool. The 2 green transactions are those that subtracted 500 ETH from the DApp balance in states N+1 and N+2. In red is the transaction that failed in state N+3. You can see how the DApp balance (from which the value was gradually subtracted) changes in each new state. At the beginning the value was 1200, then 700 and finally only 200.
Note that in state N+2 all transactions reference the same DApp balance, but it has a different value than in state N+1 and N.
The Ethereum global state can be considered the state of all accounts and contract accounts. The state of an account includes its balance of Ether and, for contract accounts, the current state of the smart contract, including any variables defined in the contract.
Ethereum’s account-based model requires transactions to be processed sequentially. This is because each transaction can potentially affect the state of any account on the network, and the outcome of a transaction could depend on the order in which it is processed. Therefore, to ensure consistency and prevent double-spending, the global state must be ‘locked’ for each validation, meaning only one transaction can be processed at a time.
The locking of the global state is needed to ensure the integrity of the system. Without this locking mechanism, it would be possible for two transactions to simultaneously attempt to spend the same funds, leading to inconsistencies in the global state and potentially allowing double-spending. By processing transactions sequentially and updating the global state after each transaction, Ethereum ensures that each transaction is processed in a consistent state and that the order of transactions does not affect the final state of the system.
The image illustrates the global state of Ethereum. Each transaction modifies two balances. The red arrow indicates the deduction of value from a balance, while the green arrow signifies the addition of value to a balance. It’s noteworthy that some transactions processed in sequence adjust identical balances. For instance, both TX 1 and TX 2 deduct value from the same balance, while TX 3 and TX 4 add value to the same balance.
Ethereum transactions can be characterized as stateful.
Conclusion
Without the context or the global state, it would only be feasible to validate certain properties of a transaction, such as the cryptographic signature from the owner of the private key. The capability to spend resources necessitates context. All nodes in the network must uphold a consistent global state that is utilized when a node constructs a new block and also during its subsequent validation by other nodes in the network.
It is occasionally stated that Cardano lacks a shared global state. This is a fairly apt analogy in the context of the significance of the global state in the case of Ethereum. However, the context for validating transactions is also crucial for Cardano. In the case of Cardano, the global state comprises a set of unique and independent objects that can only be consumed once in a single transaction. The consumption of the input UTxO results in the generation of new UTxOs. In the case of Ethereum, balances are enduring entities that can be modified repeatedly by transactions at any given time. Two Ethereum transactions cannot modify the same balance simultaneously. Therefore, sequential processing of transactions is necessary. In the case of Cardano, parallelism is feasible because transactions are independent of each other.
Determinism is advantageous for ZK cryptography. For instance, in the Cardano ecosystem, it will be possible to create a ZK Rollup that does not necessitate a sequencer.