⛓️The gcEVM chain states
Here you will find a detailed examination of the gcEVM chain states and state transition mechanisms, describing the processes nodes undergo to achieve consensus and maintain state integrity with
Section 1: The gcEVM chain states
Let's begin our discussion with a brief overview of the possible states in which a gcEVM chain can exist. To transition between these states, all nodes in the blockchain must perform a process known as "state transition." This mechanism ensures that every correctly functioning node maintains an identical state at each operational interval, commonly referred to as the block height. To provide context, we'll first review the state transition process in Ethereum's standard execution layer.
State Transition
In order to replicate the state of the leader node (“Block Proposer” in the Beacon chain, or “Miner” in the execution chain), each node that receives its block must execute every single transaction in the block’s transactions field in the same order. After each transaction, it must update the state tree (more on that elsewhere) with the resulting state. Once the node has executed all the transactions from a block, it can validate its new state tree root (alongside other roots such as the transaction root, storage root, etc.) against the roots recorded in that block’s header. If those roots match, the block is considered valid and can be inserted into the chain.
To evaluate the state of each transaction, the EVM (Ethereum Virtual Machine) must first break it down into opcodes (operation codes), which tell the virtual machine how to perform the calculations described by the transaction. Understanding opcodes is fairly low level and outside the scope of this discussion. Suffice it to say that the Ethereum Virtual Machine acts like a stack based computer, fetching data from memory, pushing it onto the stack, popping it, and performing basic computations with the values. For example: “Take the 32-byte word at memory offset X1 and push it onto the stack, then take the word at offset X5 and push that too. Now run the ADD opcode, which pops those two words, sums them, and pushes the result back onto the stack. Finally, pop the sum and write it back into memory at offset X12.”
In this regard, understanding state transition is straightforward. We take the block signed by the miner, break every transaction into a sequence of opcodes, execute them in order, and verify that the resulting state roots match the ones in the header.
The problem arises when the resulting state cannot be validated, in other words, when the outcome of certain opcodes is unknown at the time of building the block.
Private Op-Codes
Let’s take a step back and consider the case of privacy in blockchain. The gc in gcEVM stands for “garbled circuits,” which is a form of MPC (Multi-Party Computation). In a nutshell, this means we can run calculations such as “decrypt x, decrypt balance, add x to balance, encrypt balance, store balance” using multiple participants, without any one of them knowing any of the unencrypted values involved. When we apply this concept to blockchain technology, we immediately face two problems:
How do you coordinate between multiple leader nodes to ensure they work on the same input for the same block height?
How can a single node perform state transition without the ability to run private computations?
Lets tackle the first problem - Normally, the input for a new block comes from the transaction pool. The pool is itself a distributed data structure, but unlike blocks, the transaction pool is not strictly required to contain the same state across all nodes. It is common for some nodes to have a different view of the pool than others. With a single leader (miner), this does not pose a problem. As long as the transactions included in the blocks are valid and verifiable, they can come from anywhere, even private transaction pools.
When there is more than one block leader, this process does not work. If two leaders are required to work together on a state they cannot decipher, and they attempt to pick transactions from a transaction pool, discrepancies are bound to occur frequently.
This problem has two obvious solutions:
Use a service to assign the transaction input to the MPC nodes for coordination. However, this gives too much power to the service. MPC nodes would also find it very difficult to validate their input, effectively reducing them to an “oblivious” oracle that performs secure calculations without context. This approach would also expose the chain to a malicious service that could feed the MPC nodes with fake opcodes, causing them to reveal/decrypt information they should not disclose.
Use a distributed system, possibly even a blockchain, to track and verify the inputs as blocks. These blocks would relate to the MPC nodes in the same way Beacon blocks relate to execution blocks. While this would increase the visibility and trustlessness of the input, it would also increase the complexity and cost of managing two parallel chains.
We chose a hybrid approach that incorporates elements of both solutions. We still use a decentralized entity to determine the input (transactions), but instead of using another chain, we allow our chain to partially exist in a temporary “pseudo” state. We achieve this by generating a valid block with non-private state, attaching it as the chain head, and broadcasting it to the MPC nodes.
A pseudo block resembles an ordinary EVM block and follows the same rules for state evaluation, with one exception. When it encounters a transaction containing private opcodes, it does not evaluate them. Instead, it treats the result as a 256-bit blob with no meaning. This allows MPC evaluation nodes to agree on which transactions to process and in what order. The pseudo state block is currently sealed by a single node, the Sequencer, but it could be decentralized by delegating leader election to any known consensus mechanism such as PoW, PoS, or PoA.
We selected this approach over service-based opcode bundling because by packing signed and validated transactions as an input sequence, we ensure the sequencer cannot cheat by requesting the MPC nodes to decrypt a secret they are not supposed to access. This could have been mitigated by using a separate blockchain, but that would have added complexity and removed the ability to include an important validation: ensuring that transactions in the bundle are consistent with the latest state of the “real” blockchain.
For the chain to exist in two different states, the pseudo block must follow two rules:
There can be at most one pseudo block.
The pseudo block can only be the chain head.
When a new pseudo block is added as the chain head, no other pseudo blocks can be added until the MPC nodes finish creating a new canonical block. The canonical block replaces the pseudo block as the chain head, sharing the same block number but having a different hash. The canonical block contains the hash of the pseudo block’s header so it remains preserved in the chain. Once the canonical block replaces the pseudo block, there are no pseudo blocks, and the MPC nodes cannot create another canonical block until a new pseudo block is added as the chain head.
Now let's tackle the second problem - First, let’s go over how the gcEVM generates its private state. As part of its architecture, the gcEVM delegates private operations to an oracle-like network composed of multiple nodes that perform Multi-Party Computation to produce the result. No single node can ever know the result because it is encrypted, and the decryption key is a ‘secret shared’ among them. More precisely, the results of these private operations are always 256-bit ciphertexts (bytes).
To achieve replication in a way that can be validated, we associate a ‘transcript’ with the list of transactions, the transcript is a list of results for the private opcodes that cannot be computed at the time of replication. The transcript is formatted as a queue, ordered to match the order of the private opcodes that the transactions included in the block would produce. When an operation requires private computation, we pop the next result from the transcript queue and use it.
The transcript is an essential part of the gcEVM block. The Transcript is signed by all MPC nodes participating in the execution, and the signatures can be validated by any node.
To sum up
In the gcEVM, there are two types of blocks:
A block that bundles transactions in sequence for the MPC nodes. This is called a pseudo block.
A block that contains the real state of the chain after execution. This is called the canonical block.
Although the pseudo block is a valid block, it can only exist as the head of the chain and is quickly replaced by the canonical block. Its sole purpose is to convey transactions to the MPC nodes in a verifiable way.
The canonical block contains a Transcript that enables state transition without requiring the ability to run MPC computations.
Last updated