Satoshi Nakamoto has used many technologies to build Bitcoin. One of them was an accounting model using Unspent Transaction Output (UTxO). Vitalik Buterin and his team decided to use a different accounting model based on accounts, as it seemed to be a better solution for executing smart contracts. In the article, we will call it the account-based model.
Nowadays, many projects like Solana, Polkadot, and Algorand use the same accounting model as Ethereum. There are advantages and disadvantages to both approaches, and developers face different challenges when building on top of the base layers. The IOG team building Cardano decided to go a different route and extended Bitcoin’s original model, UTXO. The new model was named Extended-UTXO.
Accounting is the foundation of today’s financial world. Every financial entity needs to keep track of individual account balances and cash flows. The ledger is also the foundation of blockchain networks because at its core it is a global balance sheet that gives us the answer to who owns what assets at what time.
Blockchain records the entire history of transactions. It is very easy to audit records in the blockchain. Blockchain comes with one big advantage. It allows us to own assets without unnecessary middlemen and ensure that no one in the system can cheat.
A blockchain network essentially has two basic tasks. To maintain the ledger and to enable the transfer of value from account to account through transactions. The first generation of blockchain networks only allowed transactions to be sent unconditionally (pushed from Alice’s account to Bob’s account). The second generation added programmability, i.e. the ability to send a transaction conditionally. There are tools available for the third-party developers that allow them to write and deploy programs (smart contracts/scripts) that the network can execute in a decentralized way. The first generation blockchain network can be viewed as PayPal. The second generation will enable the building of a comprehensive banking system.
In the traditional world of finance, people rely on accountants and sophisticated centralized systems. To ensure that accountants do not cheat, it is necessary to monitor financial flows, actively implement fraud prevention measures, and audit ledgers.
Blockchain networks rely on rules that are written into the source code. Assuming the source code is correctly implemented and behaves as most people expect, there is no need for precautions and all data is available to everyone. Everyone can have a global ledger on their computer and directly interact with the network. It allows Peer-to-Peer interaction between users where a decentralized network is a trusted middleman.
How to understand blockchain from a block perspective
Blockchain is essentially a specific database that is able to ensure the immutability of historical records. The records relate to the transfers of value between users that take place through transactions. The blockchain always knows the exact answer to the question of which user X owned token Y at time Z. Because the blockchain is pseudo-anonymous, blockchain addresses are used instead of specific users. The blockchain keeps a history of all transactions made from the very beginning to the present. In addition, it ensures that history cannot be overwritten.
A blockchain is technically a state machine because it remembers previous events, which are called system states. These events are interactions between users. The state can be changed under predefined conditions. Each protocol has implemented a logic that allows the state to transit from S-0 to S+1. At regular intervals, the network creates new blocks within which a so-called state transition occurs.
The difference between the UTXO and the accounting-based model lies in the way the bookkeeping is handled. It has nothing to do with state transition from the point of view of adding new blocks. A new block is created by one node and must be broadcast to the network. Each new block contains a set of transactions and if it is accepted by the majority of participants in the network (technically by full nodes that actively participate in the network consensus), a state transition occurs. If a block is accepted, all contained transactions are accepted as well. The new block will be permanently stored in the blockchain and with its addition, the asset owners will change exactly as dictated by the accepted transactions.
Essentially, the role of the blockchain network is to validate transactions, insert valid transactions into new blocks, validate blocks and add them to the history of the blockchain. Let’s add that this process happens in a decentralized way, so new transactions and blocks need to be broadcast to the entire network, which handles the validation.
Asset ownership (coins and tokens) is represented by the possession of a private cryptographic key to a given address, which is derived from the public cryptographic key. Usually, the address is hashed. You can think of a transaction as a specific message to the network in which the sender instructs the transfer of a selected number of assets from the sender’s address to the recipient’s address. A valid transaction must contain proof that the sender is the true owner of the tokens. To do this, a private cryptographic key is used to sign the transaction. The network, or rather each node, is able to verify the signature and evaluate whether the transaction is valid. For simple transactions, validation is based on a private and public key pair.
If the transaction is accepted and is contained in a block that has been added to the blockchain, the assets will be owned by the owner of the recipient’s address. Only the new owner can spend them, again through a signature made with a private key. The user can of course send assets to himself.
This concept is the same for both the UTXO and the accounting-based model as it is based on public-key cryptography (asymmetric cryptography).
It is important to remember that what users perceive as coins or tokens are actually just digital numbers associated with blockchain addresses. The purpose of the transaction is to transfer a number from a sender address and assign the same value to a single address, or split it across multiple recipient addresses. Since fees are required, the value will usually be split across multiple addresses. The value at the input and output of the transaction must always be the same. A value cannot be created or lost during a common transaction. Networks usually define the rules for creating a new value.
Whenever people talk about coins or tokens, including in this article, they are really talking about numbers. Tokens are just an abstraction of numbers that is easy for users to understand.
Users treat their assets as a balance in their accounts. Wallets generate all private and private key pairs, so they know all of the user’s public addresses. All created addresses can contain assets. The wallet sums all the tokens at the addresses (sums all the digital numbers) and shows this to the user as a balance. A wallet could have only one single address and everything would work exactly the same.
Difference between UTXO and account-based model
The difference between the UTXO and the account-based model lies in how assets are stored at addresses and how they are handled in transactions. In other words, how the two different models handle balances and how the state of the system is recorded. In a broader context, it is important what rules and conditions are defined (and implemented in the source code of nodes) when a new block is created. Validation by the network is an integral part of the value transfer.
An unspent transaction output (UTXO) is the technical term for the number of digital assets that remain after a processed transaction. UTXO is a digital number that you can think of as a number of assets. In the UTXO model, you can use the terms UTXO and asset (coin or token) interchangeably.
Cardano uses an extended UTXO model, called Extended-UTXO (EUTXO). In the EUTXO model, the transfer of assets is recorded as a directed acyclic graph (DAG) between addresses. As scary as it sounds, there is no need to be afraid. In fact, it’s easy to understand.
As we have said, each UTXO is represented by a digital number and is an abstraction of a coin or token. You can think of UTXOs as physical banknotes or coins, but with the difference that there are no defined denominations that UTXOs need to have. For example, 10 ADA’s can be one UTXO. 12 ADA’s can also be one UTXO. Even, 116.85 can also be one UTXO.
Now imagine Alice has all three UTXOs in her wallet. It doesn’t matter if she has all 3 UTXOs at the same address, or if each UTXO is at its own address. If she wants to know her balance, she has to sum all the UTXOs. Her wallet will do it for her. Her balance is 10 + 12 + 116.85 = 138.85 ADA.
Let’s see what happens when Alice decides to send 15 ADAs to Bob. Bob has 21 ADA in his wallet at one address. He decides to create a new address to receive 15 ADAs from Alice. Alice’s wallet must use 2 UTXOs. The wallet chooses UTXOs with 10 and 12 ADA. The UTXO with 10 ADA is spent in full. Only 5 ADA + 0.2 ADA (transaction fee) is taken from the UTXO with 12 ADA.
After the transaction is accepted, Alice will have only 2 UTXOs with 6.8 and 116.85 ADA. In total, Alice will have 123.65 ADA. Bob will have 2 UTXOs with 21 and 15 UTXOs. In total, Bob will have 36 ADA. 0.2 ADA will be added to the fee address.
A transition between two states (blocks) has been executed through a transaction. The composition of the transaction is important. A transaction has inputs and outputs. Notice how the values on the input are transformed into values on the output according to the needs of the transaction, exactly as the sender (wallet) constructed it. Every UTXO in a transaction must be spent as a whole because the records in previous blocks cannot be edited. The input is a set of UTXOs to be spent, i.e. the total value will be used to create outputs by the transaction. The transaction output is also a set of UTXOs to be assigned to a new address. Alternatively, some or all UTXOs can be assigned to the same address with different values. A user can have 3 UTXOs at one address and wishes to have only 1 UTXO at the same address. The total value remains the same.
In our example, we had two inputs and three outputs. The input was 2 UTXOs belonging to Alice. The output was 3 UTXOs. Specifically, a UTXO with 15 ADA for Bob, a UTXO with 0.2 ADA as a transaction fee, and a UTXO with 6.8 ADA, which is the amount returned to Alice. For a transaction to be valid, the number of coins on the input must match the number of coins on the output. In our example, this is 22 ADA coins.
People may find it strange that it is necessary to give 6.8 ADA back to Alice. It’s similar to what the cashier at the store will give you back if you pay with a higher bill than the total price of your purchase. Again, each UTXO must be spent in full, so it is necessary to make sure the remainder is returned (if there is some remainder) to Alice as part of the transaction.
Note that the UTXO model operates with individual UTXOs during the creation of transactions. When spending a certain number of tokens, the necessary number of suitable UTXOs must be selected. If the sum of tokens in the selected UTXOs is greater than the number of tokens to be spent, the remainder must be returned as new UTXOs to the sender’s address.
UTXO is treated just like real money. If you have to pay $85 at a store, you can pay with a $100 banknote and the cashier will give you $15 back ($10 and $5 banknotes). You can’t somehow cut $85 off a $100 banknote and pay by it. You could find 17 $5 banknotes in your wallet and pay with them. You might as well have 17 UTXOs with 5 ADA in your Cardano wallet.
Each UTXO can only be spent once and never again in the future. Once it is spent, one or more new UTXOs are created and can subsequently be spent. This cycle is constantly repeated. The UTXO model is a way of organizing a blockchain such that no assets are spent twice. The blockchain transits to a new state at regular intervals. Users can spend the unspent UTXOs in any future state. For example, Bob may receive UTXO in state N and decide to spend it in 14 days, which may be state N+60,480. Spending UTXO basically means transferring the value to another address.
There are several transactions in each block, so many UTXOs are spent. All transactions together form a collection (a block) that represents the transition between states. In the UTXO model, the entire graph of transaction outputs, spent and unspent, represents the global state. It is possible to distinguish between the current state and all earlier states, which is essentially the entire history of transactions since the first Genesis block.
If you were interested in the number of all tokens that can be spent in the current state, you would have to count all unspent outputs (UTXOs). Finding them basically means going through all the transactions from the Genesis block to the present. Full nodes verify all transactions during synchronization with the network so they are aware of the current set of UTXOs.
Let’s now look at the account-based model. This is similar to a bank account. As with the UTXO model, assets are digital numbers that are associated with blockchain addresses. In the account-based model, only the current balance is maintained at the address for a given type of asset. The transaction adjusts the balance on the addresses in such a way that it subtracts a value from one address and adds it to another address.
Let’s illustrate this with an example. Alice has 138.85 ETH and decides to send Bob 15 ETH. Bob has 21 ETH in his balance.
The transaction subtracts 15 ETH from Alice’s balance and adds it to Bob’s balance. Next, a transaction fee of 0.15 ETH is deducted from Alice’s balance (GAS).
In the account-based model, the global state can be understood as a database of all accounts and their current balances of the different assets on the network. With each addition of a new block, the state of the system is updated according to all transactions that are contained in the block. The number of accounts remains constant and independent of the number of transactions conducted, as long as the number of users remains constant.
Note the differences between the two concepts. The UTXO model at the protocol level does not work with the idea of wallet or balance. The model is based only on transaction history. The user’s balance must be determined locally based on the UTXO’s transfer history.
Back to blocks
Now let’s go back to the blocks and explain their importance in the transition between states. Each transaction is basically a request to change the global state. In the case of a blockchain network, the required majority of nodes in the network should agree and accept the new state. Synchronizing the entire network with every single transaction would be very resource inefficient. Global synchronization of nodes is a time-consuming process as the information must be broadcast to the whole world. As the number of transactions increases, the network would not be able to synchronize in time. The solution is a block that contains multiple transactions. Multiple user requests are handled within the synchronization through blocks.
Blocks are the heartbeat of blockchain networks. Bitcoin transitions from its current state to a new state on average every 10 minutes. Cardano approximately every 20 seconds.
Since every individual transaction is a request for a state change, a block, with all the transactions it contains, becomes a state change request and is the means of synchronizing the network. If the global state is to change, the required majority of nodes in the network must accept the entire block. This means that all transactions in the block must be valid individually and mutually. For example, when verifying a new block, every node must ensure that the same asset is not spent twice. The entire block will be rejected by the network if it does not match the validation rules.
A blockchain is basically a sequence of blocks that are interlinked in such a way that the order cannot be changed. In most current networks, a randomly selected node will produce a new block. This block is then broadcast to all other nodes in the network. It is important that the new block is propagated throughout the network before another randomly selected node creates another new block so that the new block can be linked to the previous block. If the propagation of new blocks is too slow, forks would be created, which is an unwanted state. When another block is added to the previous one, it would be necessary to choose one of two blocks, which means that one of the blocks would remain in the blockchain forever and the other would be orphaned (with all transactions).
UTXO and the account-based models do not differ in the concept of transition to a new state based on blocks. The fundamental difference is in the global state update. In the UTXO model, the global state is only extended by the creation of new UTXOs, while in the account-based model, the global state is updated at the level of balance changes.
The two models also differ in how they handle transactions. The UTXO model is a verification model. Transactions specify the desired outcome of a state transition. The result is defined as a new UTXO that is created based on the inputs to the transaction. The node verifies whether the inputs are unspent and whether the digital signature of the transaction or other spending conditions is valid. The account-based model is a computational model. Transactions are instructing on what state transition should look like. Nodes compute the new state based on the instructions. In both cases, a change of state may require the execution of a smart contract. Smart contracts can be seen as an extension of state transition instructions.
The differences in the UTXO and account-based models have implications when it comes to the validation of blocks, smart contract execution, and scalability.
Understanding the basics
Before going into Extended UTXO, it is necessary to briefly explain some basic concepts that are well known to developers but not to the general public.
Let’s start with the terms concurrency and parallelism.
Concurrency means multiple computations are happening “nearly” at the same time. The user can perceive that tasks are being done concurrently, but there is only one actor in the background that switches between tasks very quickly. This happens if you have a single processor computer. Concurrency allows the text editor and the music player to run at the same time. The process devotes a short time to each process so that from the user’s point of view they appear to be running simultaneously. This is because the processor is much faster than human perception. If the computer has multiple processors, it can delegate individual tasks to a dedicated processor. Thus, tasks can run in parallel.
To achieve concurrency within a single big task or a bunch of tasks (which may or may not be related), it must be possible to divide the work into smaller parts in such a way that it is possible to work independently on subtasks.
When a single actor is to process a bunch of tasks, it can finish one task before starting the next one. In this case, the actor would process the tasks sequentially. Alternatively, the single actor can switch between tasks in turn at a suitable moment. A single agent can complete all tasks at approximately the same time. The question is whether switching is more effective for given tasks. In this case, tasks are processed concurrently, but not in parallel.
It can be more efficient when multiple agents are available that are able to process a bunch of tasks. In this case, multiple agents must be able to progress on tasks at the same time without interfering with each other. The tasks would be processed concurrently and also in parallel, so they would be completed faster.
Sometimes it can be difficult to split the work into multiple tasks that could be processed separately. It depends on whether the inputs can be split into separate units, or if multiple agents need to use a unique resource at the same time. In this case, agents can experience a contention. It means that more agents want to use the unique resources at the same time but only one of them can actually succeed. The winner can consume the resource permanently or release it for others when it does not need it any longer. Contention can be solved by some form of synchronization of agents. Agents might be limited in processing their subtasks.
In general, it is advantageous to try to achieve the maximum level of parallelization when we are concerned with the speed of processing a task or a bunch of smaller tasks. From a scalability point of view, it is always more advantageous for blockchain networks if it is possible to achieve higher parallelization, i.e. to allow more transactions to be processed simultaneously. However, it might be necessary to deal with contention and many other aspects.
It cannot be said unequivocally that parallelism is always the best possible solution. Concurrency can have its advantages in some specific cases. Especially if some form of synchronization is needed to avoid contention problems. There is no such thing as the best universal design. Rather, we can talk about a more appropriate solution for a particular problem.
Let’s explain the term determinism. A deterministic algorithm is an algorithm that, given a particular input, will always produce the same output, with the underlying machine always passing through the same sequence of states.
From the users’ point of view, this means that they can estimate or even know in advance what result they can expect after inserting specific inputs. For example, if you enter a 5+5 operation into the calculator, you expect in advance that the result is 10. Any other result would be an error. Developers try to build systems to be as deterministic as possible, as this guarantees a high level of reliability and therefore high user experience.
In the context of blockchain, users want to be able to predict in advance the outcome of the transaction’s submission. Determinism means that when a user creates a transaction, he wants the transaction with the set fee to get to the block as soon as possible and has the expected result. Users have the same expectations for script validation and the execution of smart contracts. When a transaction is submitted, it should not fail, and the user should not pay for a transaction that fails.
During the design of the accounting model, along with the way smart contracts are intended to be processed, it is important to anticipate the conditions under which indeterminism may occur. It is important to understand the reasons that lead to indeterminism and try to design a system in which it can be avoided or will occur minimally. Developers of decentralized applications should be provided with tools that help them create programs that behave predictably and are secure.
One risk for applications is access to mutable ledger data, i.e. data that can change constantly. If the outcome of a transaction or smart contract depends on the state of mutable data, indeterminism may occur during execution. It is always advantageous when the processing of operations is as isolated as possible from its environment (avoid using external mutable data) and depends only on local data.
Every operation is always dependent to some extent on its environment. The question is to what extent the environment can influence the outcome of a transaction and how the environment can be influenced. If an attacker is able to change mutable ledger data, he can influence the outcome of transactions and the execution of smart contracts to gain personal profit. The design of the system should minimize the possibility of attacks.
A brief history of the accounting models evolution
Let’s start first with Bitcoin, which first came up with the UTXO model. The advantage of UTXO is that the calculation during transaction verification is performed off-chain. Transactions are both results of the calculation (local verification) and proofs. It is enough to store transactions in the blockchain and there is no need to deal further with the states and their eventual storage.
The transaction inputs are always existing unspent UTXOs and it is easy for the node to verify it. This means that the same transaction, or the same inputs, cannot be used twice. Verification is easy because it takes place within a block, which is a space with a defined boundary. An attempt to spend the same input a second time is easily detected and will not be accepted. Transactions can be processed in parallel because they do not depend on any external state.
The UTXO model in Bitcoin is very weak in programmability. It is almost impossible to create a complex computation. Attempting to create a stateful contract over the UTXO model often results in high storage demand and low state utilization. Each input requires a single witness script and each output requires a single locking script. So as the number of UTXOs grows, the number of associated witness scripts grows as well. The computational power needed for verification of scripts along with the need to store scripts and witness data increases the resource requirements, hence the cost.
Ethereum was the first to come up with an account-based model. Ethereum made it possible to write a small program with complex logic called a smart contract. Transactions are interpreted as events that change the global state. Ethereum Virtual Machine (EVM) computes the state transition result of these events based on the prior blockchain state.
This is an important point since the previous state becomes an integral part of the current calculation of the new global state. In other words, the correctness of the current calculation is dependent on the past. Transactions (input data for the calculation) that affect the blockchain state are syntactically separated from the result of transactions (output data).
The global state is stored locally on nodes and is not transmitted in blocks. Nodes reach a majority consensus on the new global state by performing their own global state computation locally based on transactions (events) and then comparing their result with the received result (State-Root). In other words, all honest nodes should get the same State-Root as the proposed one after the local calculation. This is the only way to transit to the new global state within the whole network.
In the account-based model, all accounts are stateful. This means that at the computation time of the transition to a new state (smart contract processing), the global state is locked, i.e. immutable. Developers have a certain abstraction that makes it easier to develop smart contracts. They can work with and interact with all balances. Based on the computed result, a new global state will be created, which will be locked again before the next computation, which will result in another new state. There is a sequence of transitions between states.
The advantage is that developers can work with any account (balance) when the global state is locked. This means that it is possible to work with a specific account multiple times within a block. This is possible because of the sequential processing of transactions and contracts. In other words, Ethereum is good at concurrency.
This design is developer-friendly as it is easy to work with. On the other hand, developers cannot control the sequence in which transactions and contracts are processed, as this is in the hands of the block producers and users who set the fees. Thus, developers have to take into account many possible outcomes and attack attempts. It might be a challenge.
Adherence to the sequence is important as it is part of the defense against a double-spend attack. Each account has a ‘nonce’ value that is contained in each transaction. With each new transaction from a given account, the nonce is incremented. This mechanism prevents the parallel processing of transactions. If the first of several transactions by a particular account fail and are not included in a block, subsequent transactions will fail as well.
It is important to understand that transactions (events) depend on each other and their order in the block matters. When a node receives a new block, it accepts it only if it computes the same State-Root that is proposed in the block. This will only happen if the order of the events being processed, i.e. the same transition sequence, is followed.
A simple transaction in the account-based model can be seen as a request to change the balances of two users. A transaction is an event that changes the global state, not a specific input and output. Therefore, a transaction must be evaluated for correctness in the context of the previous state. This also applies to all other applications and protocols that are built on top of EVM.
Users react to a certain state, such as the price of an asset, when they submit new transactions. What users cannot influence much is the expected placement of a transaction within the transition sequence in the block. This can be a problem for more complex transactions that operate with predefined conditions, as it cannot be guaranteed in advance that the proposed state transition will still be valid when the inclusion is attempted. The user is never sure and cannot verify locally in advance that his transaction will be added to the block. As a result, the transaction may fail despite the transaction fee paid. The outcome of transactions has higher uncertainty and it is not deterministic.
Failed transactions are the result of the global state (mutable shared data). Multiple parties might want to submit transactions that will change the global state in a specific way. However, the modified global state can prevent the processing of other submitted transactions. In other words, only the first submitted transaction at a given time or under specific conditions could be processed. The rest of the transactions could fail. This complicates the building of smart contracts and can be considered a surface area for attacks.
Let’s take a concrete example. User Bob can construct a transaction based on the state of specific balances he sees at a given moment. However, these balances may have been changed by Alice’s transaction, which was unexpectedly placed before Bob’s transaction (Alice could use a higher fee or the miner decided to place Alice’s transaction before Bob’s one since fees were the same). At the moment when Bob’s transaction is inserted, the global state is different than the one Bob took into account. This change in the global state may cause the transaction to fail, or in the worse case may result in an unpredictable state.
Let’s summarize. Account-based model as it is implemented by Ethereum has the advantage for application developers of not having to worry about concurrency. Developers can freely work with user accounts and change the balance. It is ensured that balances are accessed individually as the events dictate, so there is less risk of two agents accessing the same balance at the same time. Thus, it is relatively easy to design an application. The account-based model allows users to access a single account multiple times within a block. This means that Alice can send ETH from her account to Bob in one transaction and also send ETH to Carol in another transaction. Both transactions can be in the same block.
The disadvantages are the aforementioned complexity of parallelization, frequently failed transactions, and having to pay a fee even for transactions that fail. Moreover, due to the ordering of transactions, there is an issue known as Miner Extractable Value (MEV).
Advantages of E-UTXO
Cardano uses the Extended UTXO model, abbreviated EUTXO. The purpose of the EUTXO model is to support higher expressiveness of programmability while maintaining all the benefits of Bitcoin’s UTXO model. The extended UTXO model is important to Cardano because it wants to be more than just a transactional network. Cardano is a platform, so it is important to allow developers to build more complex functionality. This is achieved through smart contracts. In the case of Cardano, it is more accurate to talk about validator scripts. In the text, we may use these terms interchangeably, but they are the same.
EUTXO offers some advantages over the account-based model. In particular, greater security when executing smart contracts, fee predictability, local verification ensuring that transactions will be accepted after the submission, and an inherently fragmented blockchain state. This allows parallelization in transaction processing, which has a positive effect on on-chain scalability. Parallelization is also important for the execution of smart contracts. Like transactions, smart contracts can also be executed independently, i.e., in parallel.
When processing smart contracts, the order in the block does not matter, there is no need to consider the execution results of other contracts in the block, so the execution itself can be considered more secure. In other words, since the individual smart contract execution results are independent of each other and there is no shared mutable (global) state, there is less surface for attacks.
It is important to note that the scalability of decentralized applications is based on the capabilities of the accounting model. In general, smart contracts and their execution can be seen as a layer that depends on the capabilities of the blockchain.
The parallelization options are based on the original UTXO design, where each existing unspent UTXO is made up of a sequence of previous transactions. Each EUTXO can be handled independently. There is no such thing as the global state that needs to be taken into account during the handling and validation of EUTXO. Only the local state is important. It means that the outcome of the transaction depends only on the use of UTXOs which are immutable, single-use objects that act as the input of transactions that will produce outputs.
Each transaction can consume one or more EUTXOs, which will create new EUTXOs that will have the same total value. The only way a transaction can influence the effect of another transaction applied to the ledger is by spending the same EUTXO as the later transaction attempts to spend, thus causing the node to reject it.
If a transaction passes local validation, the user can be almost certain that the transaction will make it to a new block. Transactions in the EUTXO model are independent of each other and are deterministic, meaning that the transaction will very likely not fail. It is also true for the validation of Plutus scripts. Users can check locally that a Plutus script can be submitted and run on-chain. It ensures that fees are never lost. One rule must be followed, however, namely that each EUTXO can only be spent only once and as a whole within a block.
The spending of UTXO must be accepted by the entire network as part of the addition of a new block. This means that the UTXO recipient can only spend it in the next block. Not in the same block in which the UTXO was received. The addition of a new block can be considered a state transition of Cardano’s blockchain. However, in the blocks themselves, the individual transactions and EUTXOs are independent of each other.
The EUTXO model is more deterministic than the account-based model, but a transaction can still be rejected. Rejection means that despite the transaction being correctly constructed, it cannot be applied to the blockchain. If this happens, the transaction has no effect on the state of the blockchain, so no fees are paid. A transaction rejection occurs in the event of contention. This means that the state of the blockchain changed at approximately the same time that the user constructed a transaction locally. The local validation has passed, but the blockchain state is already different at the moment of submission. Determinism ensures that, whenever a transaction is accepted, it will only have predictable effects on the ledger state. In other words, it will have the same effect on the ledger state as it has during construction and local validation.
It can be more difficult for a developer to create a validator script since they have to deal with concurrency themselves. Transactions can run into contention if they depend on the same EUTXO at the same time. For example, if a few EUTXOs were locked by a smart contract then only a single agent can interact with them inside one block. Notice that this limitation applies only to EUTXO. Different agents can interact with other smart contracts without any concurrency failure. A smart contract can handle a number of different UTXOs that make up its current state and off-chain metadata that allows interpreting those UTXOs.
Parallelization, or the ability to perform multiple independent operations simultaneously, is an important feature in terms of overall network performance and scalability. The global state of the account-based model limits the scalability options, as it is extremely difficult to achieve parallelization in transaction processing and also smart contract execution. With the EUTXO model, a higher level of concurrency can be achieved, which opens the door for increased scalability.
Let’s take a look at what’s new about the EUTXO model compared to the UTXO model, which uses Bitcoin. Processing a transaction in the Cardano network involves validating the requested action. The node verifies that it is able to perform the requested action and that the author of the transaction has provided relevant data/inputs.
The common action is for ordinary transactions that intend to spend EUTXOs that are locked with a public key. Node validates that the author of the transaction has provided a digital signature with the corresponding private key. The action, i.e. consuming the EUTXO, will be performed if the validation is successful. There is nothing new here yet compared to Bitcoin.
The next action is to validate transactions that intend to spend EUTXOs that are locked by a script address.
A script is a program (a piece of code) that decides whether or not the transaction that spends the EUTXO is authorized to do so. A script contains pure functions whose result is either True or False. To validate a transaction, the node invokes the script interpreter, which is a program that can translate and execute Plutus script code. The interpreter executes the script whose hash has been formed by the address where UTXOs are locked. In other words, when a EUTXO is locked by a Plutus script, that EUTXO’s script code is associated with its address.
Let’s take a look at what’s really innovative about EUTXO compared to Bitcoin besides the higher expressiveness of programmability enabled by Plutus.
Extended UTXO allows users to optionally add arbitrary user data in JSON-like format to UTXO. This data is called Datum. The Datum will allow developers to give scripts state-like functionality. User data can be considered as a local script state. This state has only local validity as it is associated with a specific UTXO. Using the full potential of Datum is up to the developers.
Transactions can carry user-specific arguments, called a Redeemer. Redeemer can be viewed as the intention of the author of the transaction on how to spend the UTXO. Redeemer can be used by developers of decentralized applications for various purposes.
There usually is a binding between Datum and Redeemer that depends on the specific functionality of a particular application. When a transaction is being validated, a validation script operates with Datum, Redeemer, and context that includes transaction data. The script contains conditions that allow consuming UTXO when they are met. The Datum, Redeemer, and transaction context are data that are input to the script.
In order to spend EUTXOs that are locked by a script, it is first necessary to get the script into the blockchain. Unlocking the UTXO will depend on the script, so the transaction will contain the script and also the UTXOs to be locked.
Developers (or their applications) write Plutus on-chain code and package it in a special format. Then, a transaction must be created into which the Plutus script will be embedded. Once the transaction has been stored in the blockchain, another transaction can be sent to initiate the execution of the script. The transaction can be seen as a message to the script.
Developers divide applications into on-chain and off-chain code. Off-chain code can be part of the wallet, or it can be a decentralized application (DEX). The off-chain part of the application can create a transaction that contains the on-chain script and EUTXOs that are to be locked. For every EUTXO the hash of Datum needs to be specified. The user has to sign the transaction. After the transaction is submitted and accepted by the network, EUTXOs will be locked by the script.
Validating a script is much more resource-demanding than validating a regular transaction. One source of indeterminism can be the size of the smart contract/script execution fees. In the case of Cardano, the budget for executing the script is part of the transaction and it is possible to calculate the exact fee locally in advance. The script interpreter tracks resource consumption during script execution in the context of the budget. If the execution budget is exhausted, the script evaluation stops and the result is False. A false value means that the EUTXO will not be consumed.
Note that the Plutus script only works with the state that is associated with the EUTXO and further with the data it receives in the transaction. The script execution does not depend on anything else. The only thing that will change from a ledger perspective on a global level is moving EUTXOs from addresses to other addresses with every newly added block.
The same contract can be used to lock Alice and Bob’s coins. Executing the script for Alice’s coins has no effect on executing the script for Bob’s coins, as they are two independent executions for separate EUTXOs. The result of the two individual execution depends on the local states.
A spending transaction (message transaction) is constructed in order to interact with a script. The input of the transaction can be the EUTXO that is locked by the script. Spending transaction invokes script interpreter in order to validate the script and unlock EUTXO if the conditions are met. Thus, unlocked EUTXO is transferred to a new address.
Some applications may need to work with a global state across multiple EUTXOs and can use Datum to do so. A kind of global state is achievable within a particular protocol design. Designers of protocols must be aware that if EUTXOs are locked by a script only a single agent can interact with it inside one block. It might require some kind of synchronization between agents.
Let’s illustrate this with an example. The liquidity pools that AMM DEX uses are shared resources because users want to use them at the same time (within the same block). Every liquidity pool contains a set of EUTXOs. Available EUTXOs are therefore also shared resources since unless an agent reserves a particular EUTXO for itself in some agreed way, they are available to everyone else.
The application algorithm must ensure that when transactions are constructed, individual agents do not contend for the EUTXOs in the pool. The transactions that want to consume a particular EUTXO are independent of each other from a validation perspective. However, the dependency exists since multiple agents might want to consume the same resource (the same EUTXO) at the same time to construct a transaction. In other words, agents want to work concurrently. One solution that is currently used is bulk transactions. Agents search for suitable request UTXOs that want to interact with a particular liquidity pool in order to fulfill the requested swap. Agents do that with all other available swap requests in mind and insert selected swaps into one big batch transaction. When creating a batch transaction, agents know what EUTXOs has already been used. They can ensure that a particular EUTXO is not used twice within a batch transaction.
The best thing about Cardano is that the team is constantly upgrading it, which will gradually increase its capabilities. At the time of writing this article, the Vasil hard-fork is upon us, which will bring many scripting improvements to Cardano. Specifically, these are Reference Inputs (CIP-31), Inline Datums (CIP-32), Reference Scripts (CIP-33), and Collateral Outputs (CIP-40). All these improvements will give developers more options when designing their applications.
I have made a few minor simplifications in the article to make it easier for readers to understand. In addition, Vasil hard-fork makes some things substantially better. Definitely see what will be different once Vasil is deployed.