Due to the decentralized design of blockchain, it sacrifices efficiency, making improving execution speed one of the urgent issues that need to be addressed. The 'execution layer' of blockchain is the key part that processes each transaction and adds it to the chain. Therefore, enhancing processing capability at the execution layer has become a core strategy, with parallel execution being a significant breakthrough in this regard.
Traditional blockchains typically process transactions one by one in a serial manner, severely limiting transaction speed, especially in transaction-intensive networks which can lead to congestion. However, with parallel execution, multiple transactions can be processed simultaneously, significantly improving execution efficiency and reducing on-chain pressure.
To better understand what parallelism is, we will first introduce execution, using Ethereum under the PBS model after Merge as an example to explain what execution is, while also demonstrating the position of execution within the entire transaction lifecycle.
Specific links of transaction execution
The transaction enters the memory pool and is filtered and sorted: This is the preprocessing phase after the transaction is submitted, including the interaction between Mempool, Searcher, and Builder, completing the filtering and sorting of the transaction.
Builder constructs the block (but does not execute): The Builder arranges profitable transactions into a block to complete the packaging and sorting of the transactions.
Proposer verifies and submits the block: After the block construction is complete, the Builder sends the proposal of the block to the Proposer. The Proposer verifies the structure and transaction content of the block, then formally submits the block to the network to start execution.
Execute the transaction: After the block is submitted, nodes execute the transactions within the block one by one. This is a critical stage for state updates, where each transaction triggers smart contract calls, account balance changes, or state changes.
Witnessing: Validators witness the execution results and state root of the block and confirm it as final. This ensures the authenticity and validity of the block at the execution layer and prevents inconsistencies.
State synchronization: Each node synchronizes the execution results of the block (such as account balances, contract state updates, etc.) to its local state, calculating and storing a new state root after executing each transaction to be used as the initial state in the next block.
Of course, this is just the state synchronization of transactions at the block level. To maintain the most up-to-date on-chain state, nodes typically synchronize data block by block and continuously verify blocks and states. However, to achieve finality under the POS mechanism, aggregators need to aggregate the witness signatures of each Slot into a complete signature and pass it to the proposer of the next Slot. Validators also need to confirm the state of all blocks within that Epoch based on the number of votes after one Epoch, forming a temporary consensus state checkpoint. Only after two consecutive Epochs gain majority support from validators do blocks and transactions achieve finality.
From the perspective of the entire transaction lifecycle, execution occurs after the Proposer verifies the structure and transaction content of the block sent by the Builder. The actual execution process requires processing transactions one by one and updating the corresponding account or contract state. After all transactions are executed, the Proposer calculates a new state root (Merkle root), summarizing the execution results of all transactions in the current block and the final global state. In simple terms, the complete block execution process includes a series of calculations required to transition Ethereum from the previous state to the next state, from the execution of each transaction to the calculation of the Merkle root.
Sequential execution
In contrast to parallelism is sequential execution, which is currently a more common execution method in blockchains. Typically, transactions are executed step by step in order. Once a transaction completes execution, Ethereum updates the account state and related information (such as balances and contract storage data) into the account state tree, generating a new account state hash. After all account state trees are updated, a root node hash known as the state Merkle root is formed. Following the completion of the state Merkle root, transaction Merkle root, and receipt Merkle root, the block header undergoes hash computation to generate the block hash for that block.
In this process, the order of transaction execution is crucial. Since the Merkle tree is a binary tree of hash values, the Merkle root value formed under different orders will vary.
Parallel execution
In a parallel execution environment, nodes attempt to process transactions in the block in parallel. Instead of executing transactions one by one in order, transactions are assigned to different 'execution paths' so that they can execute simultaneously. By executing in parallel, the system can handle transactions in the block more efficiently and improve throughput.
Once all transactions have been executed, nodes will aggregate the execution results (i.e., the state updates affected by transactions) to form a new block state. This state will be added to the blockchain, representing the latest global state on-chain.
State conflict
Since parallelism processes transactions simultaneously on different paths, one major difficulty of parallelism is state conflicts. That is, there may be multiple transactions reading or writing to the same piece of data (state) on the blockchain within the same time frame. If this situation is not handled properly, it may lead to uncertain execution results. Because the update order of states differs, the final computational results may also differ. For example,
Assume there are two transactions, Transaction A and Transaction B, both attempting to update the balance of the same account:
Transaction A: Increase account balance by 10.
Transaction B: Increase account balance by 20.
The initial balance of the account is 100.
If we execute serially, the result of the execution order is deterministic:
1. Execute Transaction A first, then Transaction B:
The account balance first increases by 10, becoming 110.
Increase by 20, ultimately becoming 130.
2. Execute Transaction B first, then Transaction A:
The account balance first increases by 20, becoming 120.
Then increases by 10, ultimately becoming 130.
In both orders, the final balance is 130, as the system ensures the sequential consistency of transaction execution.
However, in a parallel execution environment, Transaction A and Transaction B may read the initial balance of 100 simultaneously and perform their calculations:
Transaction A reads a balance of 100 and updates it to 110 after calculation.
Transaction B also reads a balance of 100 and updates it to 120 after calculation.
In this case, due to the simultaneous execution of transactions, the final balance is only updated to 120 instead of 130, because the operations of Transaction A and Transaction B 'overlapped' with each other's results, resulting in a state conflict.
Such state conflict issues are often referred to as 'data overwrites', meaning that when transactions attempt to modify the same data simultaneously, they may overwrite each other's computational results, leading to incorrect final states. Another issue that can arise from state conflicts is the inability to guarantee execution order. Since multiple transactions complete operations over different time periods, different execution orders can lead to different computational results, making the results uncertain.
To avoid this uncertainty, blockchain parallel execution systems typically introduce some conflict detection and rollback mechanisms, or conduct dependency analysis on transactions in advance, ensuring they can execute in parallel without affecting the final state consistency.
Optimistic parallelism vs. deterministic parallelism
There are two approaches to addressing potential state conflict issues: deterministic parallelism and optimistic parallelism. These two modes each have trade-offs in efficiency and design complexity.
Deterministic parallelism requires pre-declaring state access, and validators or sequencers will check the declared state access during transaction sorting. If multiple transactions attempt to write to the same state, those transactions will be marked as conflicts to avoid simultaneous execution. Different chains implement various forms of pre-declaring state access, but they generally include the following methods:
By contract specification constraints: Developers directly specify the scope of state access in smart contracts. For example, ERC-20 token transfers require access to the balance fields of the sender and receiver.
By declaring structured data in transactions: Adding specific fields in transactions to indicate state access.
By compiler analysis: High-level language compilers can statically analyze contract code and automatically generate a set of state accesses.
By framework enforcing declarations: Some frameworks require developers to explicitly specify the state that needs to be accessed when calling functions
Optimistic parallelism will optimistically process transactions first, and when a conflict occurs, it will re-execute the affected transactions in order. To minimize the occurrence of conflicts, the core design of optimistic parallelism is to quickly predict and hypothesize about the state through historical data, static analysis, etc. That is, the system assumes that certain operations or state updates are valid without complete verification, thereby avoiding waiting for all verification processes and improving performance and throughput.
Although optimistic parallelism can try to avoid conflicts as much as possible through rapid predictions and hypotheses about the state, there are still some unavoidable challenges, especially regarding contract execution or cross-chain transactions. If conflicts occur frequently, re-execution may significantly slow down system performance and increase computational resource consumption.
Deterministic parallelism avoids the potential conflict situations that may arise from optimistic parallelism by performing state dependency checks before executing transactions. However, since it requires accurately declaring state dependencies before submitting transactions, it places higher demands on developers, thereby increasing implementation complexity.
EVM parallelism dilemma
Addressing state conflicts involves not only deterministic and optimistic approaches, but also considerations from the perspective of blockchain database architecture during the specific implementation of parallelism. The issue of state conflicts in parallelism is particularly challenging in EVM under the Merkle tree architecture. The Merkle tree is a hierarchical hash structure, and each time a transaction modifies a piece of state data, the root hash of the Merkle tree also needs to be updated. This update process is recursive, computing from the leaf nodes up to the root node. Since the hashing is irreversible, the upper layers can only be computed after the lower layer's data changes are completed, making it very difficult to update in parallel.
If two transactions execute in parallel and access the same state (such as account balance), it will cause conflicts in the Merkle tree nodes. Resolving such conflicts usually requires additional transaction management mechanisms to ensure a consistent root hash value across multiple branches. This is not easy to implement for EVM, as it requires trade-offs between parallelization and state consistency.
Non-EVM parallel solutions
Solana
Unlike Ethereum's global state tree, Solana uses an account model. Each account is an independent storage space, stored in the ledger, thus avoiding path conflict issues.
Solana is deterministically parallel. In Solana, each transaction must explicitly declare the accounts it will access and the required access permissions (read-only or read-write) upon submission. This design allows blockchain nodes to analyze the resources each transaction needs to access before executing. Since all account dependencies are explicitly stated before execution begins, nodes can determine which transactions will access the same accounts and which transactions can be safely executed in parallel, thus enabling intelligent scheduling to avoid conflicts and lay the foundation for parallel scheduling.
Since each transaction has declared the accounts and permissions it needs to access before execution, Solana can check for account dependencies between transactions (Sealevel model). If there are no shared read/write accounts among transactions, the system can assign them to different processors for parallel execution.
Aptos
Aptos's parallel execution design differs significantly from Ethereum, as it makes some key innovations in architecture and mechanisms, particularly in account models and state storage.
Ethereum requires frequent updates to the global state tree (MPT) when executing transactions. All accounts and contract states are stored in a shared state tree, and any transaction needs to access and update a part of this state tree. In contrast, Aptos divides accounts into independent state units, where each object is an independent key-value pair, allowing objects to exist independently without mutual influence; they only relate when there is an explicit reference relationship. There is no shared tree path between objects, preventing lock contention and enabling complete parallelism.
Aptos's underlying data structure is the Jellyfish Merkle Tree. The state of each object is ultimately stored in the JMT as independent key-value pairs. Unlike Ethereum's MPT, Jellyfish Merkle Tree takes the form of a complete binary tree structure, which simplifies the storage and query paths of nodes, significantly reducing verification time. Additionally, the position of each account in the tree is fixed, and the nodes in the tree are stored independently, allowing for parallel updates and lookups of multiple accounts.
Aptos is optimistically parallel; it does not require prior declaration of all account dependencies. To this end, Aptos uses Block-STM, which estimates dependencies based on a preset transaction order, thereby reducing the number of rollbacks.
Parallel EVM
Compared to non-EVM parallelism, parallel EVM faces greater technical difficulties in handling issues such as state dependency, conflict detection, gas management, and rollback mechanisms. To better understand this, we can refer to how some parallel EVM projects (such as Sui, Monad, Canto) address these issues.
Sui
Like Aptos, Sui also uses an object model to handle state, using each object (e.g., account, smart contract state) as an independent resource, which are distinguished by unique object identifiers. When transactions involve different objects, these transactions can be processed in parallel because they operate on different states and do not cause direct conflicts.
Although Sui uses an object model to manage state, in order to be compatible with EVM, Sui's architecture bridges the object model and EVM's account model through an additional adaptation layer or abstraction mechanism.
In Sui, the scheduling of transactions uses an optimistic parallel strategy, assuming that there are no conflicts between transactions. If a conflict occurs, the system will use a rollback mechanism to restore the state.
Sui uses an object model and state isolation technology to effectively avoid state dependency issues. Each object acts as an independent resource, allowing different transactions to be executed in parallel, thereby improving throughput and efficiency. However, the trade-off of this approach is the complexity of the object model and the overhead of the rollback mechanism. If conflicts occur between transactions, part of the state needs to be rolled back, which increases the burden on the system and may affect the efficiency of parallel processing. Compared to non-EVM parallel systems (such as Solana), Sui requires more computational and storage resources to maintain efficient parallelism.
Monad
Like Sui, Monad also adopts optimistic parallelism. However, Monad's optimistic parallelism will predict some dependent transactions before actual execution, primarily through Monad's static code analyzer. This prediction requires access to the state, and the way Ethereum's database stores state makes accessing the state very difficult. To make the state reading process more efficient in parallel, Monad has also restructured the database.
The Monad state tree is partitioned, with each partition maintaining its own state subtree. During updates, only the relevant shards need to be modified without rebuilding the entire state tree. A state index table quickly locates states within the partition, reducing interactions between partitions.
Summary
The core of parallelism is to improve execution efficiency at the execution layer through multi-path execution. To achieve this, the chain needs to implement a series of mechanisms such as conflict detection and rollback to ensure that they can execute in parallel without affecting the final state consistency, along with certain improvements to the database.
Of course, improving execution layer efficiency is not limited to parallelism; optimization of the execution process can also be achieved by reducing the read and write operations required by a single transaction on the database. The scope of speed improvement for the entire chain is even broader, including enhancements to consensus layer efficiency.
Every technology has its specific limitations. Parallelism is just one way to enhance efficiency, and whether to adopt this technology ultimately depends on considerations such as whether it is developer-friendly, and whether it can be completed without sacrificing decentralization, etc. The stacking of technologies is not always beneficial; at least for Ethereum, parallelism does not seem particularly attractive. If we only consider the aspect of efficiency enhancement, incorporating parallelism may not be the optimal solution for Ethereum, whether considering simplicity or Ethereum's current Rollup-centric roadmap.