Skip to content

Commit

Permalink
qip-0011: Paying for Account State Usage
Browse files Browse the repository at this point in the history
  • Loading branch information
wizeguyy committed Apr 11, 2024
1 parent 78cd805 commit 5c47106
Show file tree
Hide file tree
Showing 2 changed files with 148 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@ Those proposing changes should consider that ultimately consent may rest with th
| [8](qip-0008.md) | Consensus (hard fork) | Dynamic Tree Expansion | wizeguyy | Standard | Draft |
| [9](qip-0009.md) | Consensus (hard fork) | Interlinks | gameofpointers | standard | Draft |
| [10](qip-0010.md) | Consensus (hard fork) | Network Object Identifiers | wizeguyy | standard | Draft |
| [11](qip-0011.md) | Consensus (hard fork) | Paying for Account State Usage | wizeguyy | standard | Draft |

<!-- IMPORTANT! See the instructions at the top of this page, do NOT JUST add QIPs here! -->
147 changes: 147 additions & 0 deletions qip-0011.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
```
QIP: 11
Layer: Consensus (hard fork)
Title: Paying for Account State Usage
Author: wizeguyy <[email protected]>
Comments-Summary: No comments yet.
Comments-URI: https://github.com/quainetwork/qips/wiki/Comments:QIP-0011
Status: Draft
Type: Standards Track
Created: 2024-04-01
License: BSD-2-Clause
```

## Abstract
This QIP proposes a mechanism for paying for the state used by an account in
the state tree. State pricing is dominated by the disk IOPS necessary to
load/store trie nodes to perform state root updates. Therefore, we price
account slots logarithmically according to the size of the account trie, and
let the market drive the price through its ability to buy/sell account space.

## Motivation
As the popularity of a blockchain grows, the data necessary to maintain the
state of each account grows. This state trie growth degrades performance, as
the cost of recomputing state root updates becomes the dominant processing cost
associated with processing a transaction.

Given the material costs associated with account slots, the protocol needs to
impose that cost on users to prevent unsustainable state usage. Because these
costs are born by the entire network, and not simply the transactor, it is not
sufficient to impose this cost in the form of transaction fees. A long-term
cost must exist, proportional to each account's impact on the state tree and
the duration of that impact (i.e. not just at the time the transaction is
processed).

## Rationale
The complexity to update the state root is proportional to the number of
accounts in the state tree. Since we use Patricia Merkle trie (PMT) with its
extension node optimization, the tree complexity is rarely worst-case, but for
the reader's intuition, the worst case update cost is bounded by its radix-16
tree update cost: $O(log_{16}(N))$ for $N$ accounts. In the case of a PMT, the
physical limitation is often the number of disk IOPS necessary to update each
database record for each trie node.

### Letting Markets Decide the Price
Since node operators may be running any number of hardware configurations, with
different CPU, memory, storage, or network constraints, it is impossible to
pick a concrete price for any of these resources that makes any sense. In fact,
even if we could, the concrete number selected today may be very different as
node operators upgrade hardware or experience failures over time. The solution
to this, is to expose these limited resources to the market so that market
participants can decide the price of these resources based on each's own
subjective preference.

To accomplish this, we build the protocol to enforce account prices
according to the current size of the account trie. Then we make it possible to
buy and sell account slots back at whatever the current price
is.
Every account must
pay for its index in the PMT, but it may sell its account space back if it
no longer requires it. This accomplishes two things:

1) The market determines efficient price for account slots

2) Users are incentivized to clean up the state trie by destroying their
accounts when they no longer need them.

An important thing to consider, is that Quai's design has the ability to scale
and add more capacity if these limits end up being too small. If, for example,
speculators buy up too many account slots to resell them to future buyers, they
run the risk of increasing block processing latency, which through
[QIP-0008](qip-0008.md) will ultimately lead to the addition of more chains
with more resources. If this happens, speculators will have to compete with
these newly available resources, which would harm their speculative investment.
So there is some negative feedback here, which incentivizes speculators to
participate and help determine market pricing, without fully consuming
resources that would trigger a trie expansion. In fact, when the network gets
close to that point, there is a strong incentive for account holders to sell
back any account space they no longer need, which helps balance resource usage
as the network scales.

## Specification
### Account Pricing
Every new account added to the tree must pay for its address space. The cost of
this address space must increase as the number of addresses increases. This
will create negative feedback: speculators will occupy address space with new
accounts when its cheap, and destroy their accounts when if it becomes
expensive. This balance of speculator preference with user demand, is how the
market determines the appropriate address space price.

To achieve this, we use the radix-16 computational bound described above, to
set the account slot price. The price function is:

$$ P_a = K_a* \lfloor log_{16}(N) \rfloor $$

where $P_a$ is the price to create or sell an account slot in Quai per account,
$N$ is the total number of accounts in the trie, and $K_a$ is a constant
scaling factor chosen to adjust price responsiveness to trie size.

#### Choosing $K_a$
We choose $K_a$ to set a Schelling point about a reasonable acceptable trie
size, while understanding that the actual size will again depend on the
subjective demand for account space. We choose 1 billion (2^30) accounts per
chain as a reasonable upper bound, and we choose 0.1 Quai per account to be a
high cost which will lead to reduced demand in the account space market.

We choose:

$$ K_a = 0.1*\frac{Quai}{account^2} $$

$$ \approx 9.31*10^{-11} \frac{Quai}{account^2} $$

### Protocols for Buying and Selling Account Slots
For a new account to be created, enough Quai must be sent to cover the account
creation price $P_a$. The new account will be credited with the balance of the
transaction minus the creation price, $P_a$. Any transaction to a new account,
which does not satisfy the creation price, will fail.

Conversely, to sell account space back, we provide a precompiled contract with
a destruction method. The destruction method will allow the user to provide a
"beneficiary transaction", which may transfer the balance including the sale
price of the account (along with optional TX data) to any other address in the
trie. Upon successful execution of the transaction, the account will be deleted
from the state trie.

Contract address and ABI TBD.

### Dynamic Load/Store Gas
The demand curve defined above only works if the load/store costs for accounts
and account data are appropriately priced. Specifically, there cannot be a
fixed price to load an account, load code/data stored within an account, or to
store it back. Since all of these operations depend on merkelization of the
data, the gas used in each operation is dependent on the size of the trie.
Accordingly, these operations cannot have a fixed gas cost as implemented in
the vanilla EVM.

#### Account Access Gas
The gas required for processing a transaction will be updated to dynamically
compute the account load/store cost according to merkle trie depth. Every trie
node which is loaded will cost $\lfloor log_{16}(N) \rfloor$ times the vanilla
EVM gas cost.

#### Account Data Access Gas
The gas required for accessing code and storage data will similarly be multiplied
by $\lfloor log_{16}(N) \rfloor$ times the vanilla EVM gas cost for each such opcode.

## Copyright
This QIP licensed under the BSD 2-clause license.

0 comments on commit 5c47106

Please sign in to comment.