Full nodes verify blocks by downloading all transactions and re-executing them to check their validity. Unsurprisingly, larger blocks place a greater burden on full nodes – more hardware required to process and verify each block. Technologies like fraud and validity proofs enable nodes to check validity without re-executing every transaction. Data availability sampling enables nodes to verify data availability while only downloading a small subset of each block.
One of the final burdens that is left is the state. To verify blocks, full nodes must also store a copy of the entire state. As the state grows, storage requirements for full nodes increase. Luckily, state growth is also solvable to a degree.
Statelessness is a property where full nodes nodes can verify blocks without storing the state (stateless). There are two primary kinds of statelessness:
- Strong statelessness: No node is required to store the state.
- Weak statelessness: Only block producers are required to store the state.
Strong statelessness introduces an order of magnitude more complexity and tradeoffs, so we’re just going to focus on weak statelessness for now.
A (weakly) stateless rollup is one in which at minimum, the sequencers are required to store the state, but full nodes are stateless. An optimistic rollup may additionally require watchers to store the state to generate fraud proofs – dependent on whether fraud proof generation is allowed for non-sequencer nodes.
To verify a block’s validity, full nodes start with a pre-state root, which is the root of the state tree after appending the previous block to the chain. The transactions are then re-executed, generating a new state root known as the post state root. The computed post state root is then verified against the post state root in the proposed block header. If they match, then the block is valid, if not then it is invalid and rejected. However, a stateless node doesn’t have a pre-state root to begin with because they don’t store the state.
In a stateless rollup, the sequencers would distribute a pre-state and post-state root with each block for full nodes to verify the block. There’s a bunch of other nuances but that is the basic idea around stateless verification.
If a stateless rollup has a p2p network, the sequencers only need to send the block and corresponding state roots to an initial group of peers, which can then propagate them throughout the network. However, if a stateless rollup were to have no p2p network, which is currently the case for many rollups, then the single sequencer would need to individually distribute the block and state roots to every node in the network. Implementing statelessness in a rollup without a p2p network would place an impractically large burden on the sequencer. So, a p2p network is a prerequisite.
In addition to verifying blocks, full nodes also serve state requests (e.g. send me the account balance for address 0x…). Stateless nodes fully verify state transitions like full nodes but depend on them for access to the state. As such, there is still a minimum number of full nodes needed to provide state requests to the rest of the network.
In practice, users may likely gravitate to stateless nodes due to lower hardware requirements, therefore fueling a growing dependence on a dwindling percentage of full nodes. If there aren’t enough full nodes to serve the state requests, the stateless rollup will become bottlenecked because the state can’t propagate fast enough throughout the network to meet demand.
Full nodes verify incoming transactions before forwarding them to the mempool to prevent the mempool and block producers from getting spammed with invalid transactions. However, transaction verification requires access to the state for data such as the sender’s account balance and nonce, which a stateless node can’t perform without making a state request to a full node. This process opens stateless nodes to a DoS vector, they can get spammed but can’t reject the transactions until they make the required state requests to check the transactions are eligible for forwarding to the mempool Additionally, transaction propagation slows because of the additional steps that stateless nodes must take before forwarding transactions.
Benefits of a stateless rollup
Removing the requirement for full nodes to store the state produces lower hardware requirements – lowering the barrier for more users to run full nodes. Mitigating the negative affects of state growth are as important for rollups as any other chain because they too are vulnerable. Since weak statelessness doesn’t remove the responsibility for sequencers to store the state, the most used rollups may see state growth could potentially become a hinderance. Further measure can be implemented to reduce state growth for sequencers, such as state expiry where state that hasn’t been accessed during a given period of time gets removed from the state.
As an aside, statelessness also removes the DoS vector for Disk IO because stateless nodes are no longer required to perform accesses of the state – this is particularly beneficial if the rollup has a large state.
Statelessness and fraud proofs are two sides of the same coin – implement one and get the other for free. Nodes require pre and post state roots to verify fraud proofs, which is a similar requirement for stateless block verification. Admittedly, there are additional considerations around fraud proofs, such as single round vs multi-round, bonding, and general censorship resistance specifics.
If the fraud proof implementation allows them to get distributed among the rollup’s p2p network, light clients become trust-minimized in the process – they can now verify an invalid block as opposed to naïve light clients.