State explosion and Nervos has the answer
8 min read
You probably wouldn’t know how much VISA or Mastercard charge you for buying food at your favourite restaurant, but you should know how much ‘fx transaction fee’ your bank charges you when you travel abroad. The point is, we are sensitive to transaction fees and would compare different providers to bank without needing to understand how the whole payment system works. The same logic applies when we interact on-chain.
Now most newcomers to web3 understands what gas is and how Ethereum network is expensive to use especially during congested periods, it is the fee required to pay for miners to include your transaction in the next block on the blockchain. However, there are more resources being consumed after the transaction in conducted which is a one-time event.
To understand the costs we first need to understand how full nodes operate to power the network. Full nodes download new transactions and blocks for verification and then broadcast only valid transactions and blocks to other nodes. To verify the blocks and transactions, the full node must have the complete current state of the network. The validation task is undertaken by full nodes themselves, so there is no need for them to trust a third party. It is easy to confuse full nodes and miners as miners are usually also full nodes in many blockchains, but they are also responsible for packaging transactions and generating blocks.
Compared with other kinds of nodes, block-producing nodes require more resources, including CPU (for PoW hashing or voting), disk space and network bandwidth. This demand for resources makes it more difficult to run block-producing nodes, which tends to centralize their distribution. CPU and bandwidth are resources that refresh with each new block, so it makes sense for users to pay a one-time gas when using the network to compensate these costs. However, nodes need disk space to store information to process new incoming blocks and transactions. This information could include account balances, contract code, contract storage, consensus-related data. Now let’s formalise the concept.
Sate refers to the essential information stored in local storage alongside with history when running full nodes. It is required so that the full node can process new blocks and transactions.
History: Information about past events, path from Genesis to the current state, not essential to continue processing the chain.
State (present): The final result of the node after processing all the blocks and transactions from Genesis to the current height. The state changes with the growth of the block, and the transaction is the cause of the change.
The consensus protocol ensures that each node sees the same current state and to achieve this, the system must ensure each node sees the same history.
Now it is easy to see storage of the present state takes up long-term disk space when you want to operate a node. But the cost for that storage is not accounted in the one-time gas fee. Users essentially free-ride the permanent right to use this storage system operated by full nodes. This becomes a detrimental issue when the size of state grows without bound as more users join.
Take Ethereum for an example, its state include:
- Account balances and nonces
- Contract code
- Contract storage
- Consensus related data
Among the 4 only the last item has been designed to be limited in size while other 3 would grow unboundedly. This has many undesirable outcomes as junk states are also left lying around forever.
The EOS sale is a good example of this problem, although the sale has concluded and EOS tokens are transacting on the EOS chain, the disk space used by the sale has become a permanent part of Ethereum full node. Those part of the disk space are effectively wasted on junk state.
As a result of state information accumulating over time, it will require bigger disk space to run a full node, thus making full node operation more expensive for participants. This would likely result in less full nodes compromising the decentralisation of the blockchain.
The idea here is that nodes verifying blocks no longer need to store state. Instead, blocks come with proofs proving the values of the state that get accessed. The main issue with this approach is the data availability of the blockchain. If the whole state is replicated to N clients, the availability of any data in state is N; if the state is only kept by a few or single client, then its availability is 1. Data availability is at the core of a layer 1 blockchain because the availability of layer 1 assets relies on it, smart contracts rely on it and layer 2 protocols rely on it.
State must be continually accessed to remain “active”; state that is untouched for a long time becomes “inactive” (or “expired”). There are many choices for the exact mechanic for how state can be renewed (e.g. pre-paying a “rent” fee, or simply touching the account), but the general principle is that unless a state object is renewed explicitly, it is inactivated in some way. Hence, any action that creates new state objects (or refreshes existing ones) only burdens other nodes for a limited period, and not as is currently the case forever.
There are a few ways to determine when states are expired:
- Direct rent: Per-block rent fee is charged directly from the balance of each account or other state object; an object is expired when its balance reaches zero.
- Rent via time-to-live: Each state object stores a “time-to-live” value, and this can be extended by paying a fee
- Refreshing by touching: Each state object stores a “time-to-live” value, and this is extended by reading or writing to the account, which costs one-time gas fee
- Everything expires at regular intervals
However, paying ‘subscription fees’ is against consumer habits and having data expiry is very intrusive to user experience. Moreover, what happens when states expire? The state expiry must be coupled with mechanisms such as resurrection, which would increase the complexity of the design, sharply reduce the immutability of the smart contract, and negatively impact user experience. Ethereum’s state model is also a shared model but not First-Class State. Take the ERC20 token as an example: the assets of all users are recorded in the storage of a single ERC20 contract. In this case, who pays the state rent? If it’s the contracts then they would have to add fairly complex logic to pass on the cost of storage to their users, which is not ideal.
Nervos and Storage-slot-level Expiry
Solving the State Explosion problem is one of the goals of Nervos CKB. For this reason, CKB is taking a completely different approach to the design of a blockchain network, with many innovations. Nervos is using a multi-layer architecture designed to store only high-value Assets on Layer 1, with transactions taking place on Layer 2.
Nervos Layer 1 makes the storage space of the blockchain like land, it’s limited and to use it (store data) you have to own $CKB (1 CKB = 1 byte). This “state-focused” economy encourages developers and users to make efficient use of the blockchain’s storage, one of its limited resources. This also enforces a hard cap which released through an inflationary schedule because the base issuance is capped at 33.6billion CKBytes with secondary issuance at fixed annual amount of 1.344 billion CKBytes. It is easy to see this issuance schedule of CKBytes gives a bounded growth of state size. And although you could say the supply of CKBytes is unlimited, you could easily see how the state growth is nicely controlled by the fixed secondary issuance each year and no user gets a free lunch. Now that we get state explosion out of the way, why don’t we need to worry about the inflation caused by unlimited supply? Think about cities in the real-world, as cities grow into metropolis they expand in size. The land in the city is used for many purposes, and once a school or office is built, the land itself is locked and cannot be used for other purposes. As more and more dApps and assets are formed on Nervos more CKBytes would be occupied. In other words, there will be less CKBytes in circulation as Nervos network prospers.
As mentioned above, secondary issuance of CKBytes if fixed at 1.344 billion each year, and the secondary issuance is distributed proportionally to following parties depending on cells used:
- miners maintaining the network acting as state rent collected from users
- Users of NervosDAO
- The Nervos treasury for continued development
For instance, if 60% of total supplied CKBytes is being occupied on chain and 20% being locked in NervosDAO, miners would collect \( 1.344 billion \times 0.6 = 8.064 billion \) secondary issuance as state rent. For long-term holders looking for a store of value who lock their CKByte holdings in NervosDAO, they are shielded from the targeted inflation by receiving \( 1.344 billion \times 0.2 = 2.688 billion \) CKBytes. Currently the portion allocated to the Nervos treasury is being destroyed as governance mechanism is not finalised.
While state explosion is a post-scalability problem blockchains face and there are different solutions that don’t involve changing the base layer chain, I’m fascinated with the solution Nervos proposes and its vision beyond scalability. It is a problem everyone will face and only talked about in theory in other public chain communities, solved by intelligent design of Nervos cell model from the start.