Bitget App
Trade smarter
Buy cryptoMarketsTradeFuturesCopyBotsEarn

Vitalik's New Quick Read: Multi-Dimensional Gas Pricing

View original
ChaincatcherChaincatcher2024/05/09 12:19
By:作者:Vitalik Buterin

Vitalik talks about the multi-dimensional Gas pricing of Ethereum, how should one balance and choose?

Author: Vitalik Buterin

Translation: Karen, Foresight News

 

In Ethereum, resources were limited until recently and were priced using a single resource called "Gas." Gas is a unit of measurement for the "computational effort" required to process specific transactions or blocks. Gas combines various types of "computational effort," with the most important ones being:

1. Raw computation (e.g., ADD, MULTIPLY);

2. Reading and writing to Ethereum storage (e.g., SSTORE, SLOAD, ETH transfers);

3. Data bandwidth;

4. Cost of generating ZK-SNARK proofs for blocks.

For example, the transaction I sent consumed a total of 47,085 Gas. This includes: (i) a base cost of 21,000 Gas, (ii) calldata bytes included as part of the transaction consumed 1556 Gas, (iii) reading and writing to storage consumed 16,500 Gas, (iv) generating logs consumed 2149 Gas, with the rest used for EVM execution. The transaction fee that users must pay is directly proportional to the Gas consumed. A block can contain a maximum of 30 million Gas, and the Gas price is continuously adjusted through the EIP-1559 targeting mechanism to ensure an average of 15 million Gas per block.

This approach has a major advantage: because all content is merged into a virtual resource, market design is very simple. Optimizing transactions to minimize costs is easy, optimizing blocks to collect as high fees as possible is relatively easy (excluding MEV), and there are no strange incentive mechanisms encouraging some transactions to be bundled with others to save costs.

However, this approach also has inefficiencies: it treats different resources as interchangeable when the actual underlying constraints are different. To understand this issue, you can first look at the following chart:

Gas limits impose a constraint:

The actual underlying security constraints are usually closer to:

This difference causes Gas limits to either unjustly exclude blocks that are actually secure, accept blocks that are not actually secure, or a combination of both.

If there are n resources with different security constraints, one-dimensional Gas could potentially reduce throughput by up to n times. Therefore, people have long been interested in the concept of multi-dimensional Gas, and through EIP-4844, we have actually implemented multi-dimensional Gas on Ethereum. This article explores the advantages of this approach and the prospects for further enhancements.

Blob: Multi-dimensional Gas in Dencun

At the beginning of this year, the average block size was 150 kB. A large part of this was Rollup data: Layer2 protocols storing data on-chain. This data is very expensive: although transactions on Rollup cost only 5-10 times those on Ethereum L1, even such costs are too high for many use cases.

So why not reduce the Gas cost of calldata (currently 16 Gas for non-zero bytes, 4 Gas for zero bytes) to make Rollup cheaper? We have done this before, and we can do it again now. But the answer here is: the maximum block size is 30,000,000/16 = 1,875,000 non-zero bytes, and the network can barely or almost not handle blocks of this size. Lowering the cost by 4 times would increase the maximum to 7.5 MB, which would pose a huge risk to security.

This problem is ultimately solved by introducing a separate, Rollup-friendly data space (called blob) in each block.

These two resources have different prices and limits: after the Dencun hard fork, an Ethereum block can contain (i) 30 million Gas and (ii) 6 blobs, each capable of holding about 125 kB of calldata. These two resources have separate prices and are adjusted through a pricing mechanism similar to EIP-1559, with the goal of averaging 15 million Gas and 3 blobs per block.

As a result, the cost of Rollup has been reduced by 100 times, the transaction volume on Rollup has increased by over 3 times, and the theoretical maximum block size has only slightly increased: from about 1.9 MB to about 2.6 MB.

Note: Rollup transaction fees provided by Growthepie.xyz. The Dencun fork occurred on March 13, 2024, introducing multi-dimensional pricing for blobs.

Multi-dimensional Gas and Stateless Clients

In the near future, storage proofs for stateless clients will also face similar issues. Stateless clients are a new type of client that will be able to verify the chain without needing to store a large amount or any data locally. Stateless clients achieve this by accepting proofs of specific parts of Ethereum state that transactions in that block need to access.

The above image shows a stateless client receiving a block and proof of the current values of specific parts of the state touched by the block's execution (e.g., account balances, code, storage), enabling nodes to verify a block without any storage.

A storage read costs 2100-2600 Gas, depending on the read type, while storage write costs are higher. On average, a block performs about 1000 storage read/write operations (including ETH balance checks, SSTORE and SLOAD calls, contract code reads, and other operations). However, the theoretical maximum is 30,000,000/2,100 = 14,285 reads. The bandwidth load of stateless clients is proportional to this number.

The current plan is to support stateless clients by transitioning Ethereum's State tree design from Merkle Patricia trees to Verkle trees. However, Verkle trees do not have post-quantum security and are not the optimal choice for newer STARK proof systems. Therefore, many are interested in supporting stateless clients through binary Merkle trees and STARKs, either completely skipping Verkle or upgrading to it after a few years of transition, once STARKs become more mature.

STARK proofs based on binary hash tree branches have many advantages, but their key weakness is the long time it takes to generate proofs: Verkle trees can prove over 100,000 values per second, while hash-based STARKs typically prove only a few thousand hashes per second, and proving each value requires including many hash branches.

Considering today's predictions from highly optimized proof systems like Binius and Plonky3, as well as dedicated hashes like Vision-Mark-32, it seems that proving 1000 values per second is feasible for a while, but proving 14,285 values is not. Average blocks would be fine, but potential worst-case blocks (issued by attackers) would disrupt the network.

The default approach we take to handle such situations is repricing: increasing the cost of storage reads to reduce the maximum per block to a safer level. However, we have done this many times already, and doing it again would make too many applications too expensive. A better approach is multi-dimensional Gas: limiting and charging for storage access separately to keep the average usage at 1000 storage accesses per block, but setting an upper limit per block, for example, 2000 accesses.

Universality of Multi-dimensional Gas

Another resource worth considering is the growth of state size: operations that increase the Ethereum state size, which subsequently require full nodes to store. The uniqueness of state size growth is that the reasons for limiting it come entirely from long-term sustained usage, rather than peak values.

Therefore, adding a separate Gas dimension for increasing state size operations (e.g., zero-to-non-zero SSTORE, contract creation) may be valuable, but with a different goal: we can set a floating price targeting a specific average usage but not set a limit for each block.

This demonstrates a powerful property of multi-dimensional Gas: it allows us to separately inquire for each resource (i) what is the ideal average usage? (ii) what is the safe maximum usage per block? By setting Gas prices based on the maximum value per block and allowing the average usage to vary, we have 2n degrees of freedom to set 2n parameters, adjusting each parameter based on considerations for network security.

In more complex scenarios, such as when security considerations for two resources partially overlap, handling this can be done by having an opcode or resource consume multiple types of Gas in certain quantities (e.g., a zero-to-non-zero SSTORE might consume 5000 stateless client proof Gas and 20000 storage expansion Gas).

Max per transaction (choose the one with higher data or computation cost)

Let 𝑥1 be the Gas cost for data, 𝑥2 be the Gas cost for computation, so in a one-dimensional Gas system, we can write the Gas cost of a transaction as:

In this scheme, we define the Gas cost of a transaction as:

Meaning, transactions are charged based on which of the two resources they consume more of, rather than a sum of data and computation. This can easily be extended to cover more dimensions (e.g., 𝑚𝑎𝑥(...,𝑥3∗𝑠𝑡𝑜𝑟𝑎𝑔𝑒_𝑎𝑐𝑐𝑒𝑠𝑠)).

It should be easy to see how this enhances throughput while ensuring security. Theoretically, the maximum data volume in a block is still Gas LIMIT /𝑥1, the same as in a one-dimensional Gas scheme. Similarly, the theoretical maximum computation is Gas LIMIT /𝑥2, also the same as in a one-dimensional Gas scheme. However, the Gas cost for any transaction consuming data and computation will decrease.

This is likely the approach adopted in the proposed EIP-7623 to reduce the maximum block size while further increasing blob count. The precise mechanism in EIP-7623 is slightly more complex: it keeps the current calldata price at 16 Gas per byte but introduces a floor price of 48 Gas per byte; transactions pay the higher of (16 * bytes + execution _ Gas) and (48 * bytes). Thus, EIP-7623 reduces the theoretical maximum transaction call data in a block from about 1.9 MB to about 0.6 MB while keeping costs for most applications unchanged. The benefit of this approach is that it changes very little compared to the current one-dimensional Gas scheme, making it very easy to implement.

However, this approach has two drawbacks:

1. Even if all other transactions in a block use very little of that resource, transactions that heavily consume one resource will still be unnecessarily charged a large fee;

2. It incentivizes bundling data-intensive and computation-intensive transactions together to save costs.

I believe that rules like those in EIP-7623, whether for transaction calldata or other resources, can bring significant benefits, even with these drawbacks.

However, if we are willing to invest (significantly higher) development effort, a more ideal approach will emerge.

Multi-dimensional EIP-1559: A More Challenging but Ideal Strategy

Let's first review how the standard EIP-1559 works. We will focus on the version introduced for blobs in EIP-4844, as it is more mathematically elegant.

We track a parameter excess _ blobs. During each block period, we set:

excess _ blobs <-- max (excess _ blobs + len(block.blobs) - TARGET, 0)

where TARGET = 3. This means that if a block has more blobs than the target, excess _ blobs increases, and if a block has fewer blobs than the target, excess _ blobs decreases. Then we set blob _ basefee = exp(excess _ blobs / 25.47), where exp is the exponential function 𝑒𝑥𝑝(𝑥)=2.71828^𝑥's approximation.

This means that whenever excess _ blobs increase by about 25, the base fee for blobs increases by about 2.7 times. If blobs become too expensive, average usage decreases, and excess _ blobs start to decrease, automatically lowering the price again. The price of blobs continuously adjusts to ensure that, on average, blocks are half full, meaning each block contains an average of 3 blobs.

If there is a short-term peak in usage, there is a limit: each block can contain a maximum of 6 blobs, in which case transactions can compete by increasing the priority fee. However, under normal circumstances, each blob only needs to pay the blob _ basefee plus a small additional priority fee to be included as an incentive.

This type of Gas pricing has been in Ethereum for years: as early as 2020, EIP-1559 introduced a very similar mechanism. Through EIP-4844, we set two independent floating prices for Gas and Blobs.

Note: Gas base fee in gwei for one hour on May 8, 2024. Source: ultrasound.money

In principle, we can add more independently floating fees for storage reads and other types of operations, but I will detail an issue to be mindful of in the next section.

For users, this experience is very similar to today: you no longer pay a base fee (basefee), but two base fees, which your wallet can abstract from you, showing only the expected fee and maximum fee you can expect to pay.

For block builders, the optimal strategy is mostly the same as today: include any valid content. Most blocks are not full—whether in Gas or Blobs. A challenging situation arises when there is enough Gas or enough Blobs to exceed the block limit, requiring builders to potentially solve a multi-dimensional knapsack problem to maximize their profit. However, even with fairly good approximation algorithms, the gains from optimizing profit through proprietary algorithms in this scenario are much smaller than those from using MEV for the same operations.

For developers, the main challenge is the need to redesign the EVM and its related infrastructure's functionality, which is currently designed based on a single price and limit and now needs to be refactored to accommodate multiple prices and limits.

One issue application developers face is that optimization becomes slightly more challenging: in some cases, you can no longer explicitly say A is more efficient than B because if A uses more calldata and B uses more execution, A may be cheaper when calldata is cheap and more expensive when calldata is expensive.

However, developers can still achieve fairly good results by optimizing based on long-term historical average prices.

Multi-dimensional Pricing, EVM, and Sub-calls

One issue that does not arise in blobs, and would not arise in EIP-7623 or even in a complete multi-dimensional pricing implementation for calldata, but would arise if we attempt to individually price state access or any other resource, is the Gas limit in sub-calls.

Gas limits in the EVM exist in two places. First, each transaction sets a Gas limit, restricting the total amount of Gas that can be used in that transaction. Second, when a contract calls another contract, that call can set its own Gas limit. This allows contracts to call other contracts they do not trust and still ensure they have a limit after the call is made.

There is remaining Gas to execute other computations.

Note: The trace of abstract transactions involves one account calling another account and providing a limited amount of Gas to the callee to ensure that even if the callee consumes all the Gas allocated to it, the external call can continue to run.

The challenge lies in achieving multidimensional Gas between different types of executions, which seems to require multiple restrictions for each type of Gas for subcalls, necessitating very deep changes to the EVM and being incompatible with existing applications.

This is one of the reasons why multidimensional Gas proposals typically remain in two dimensions: data and execution. Data (whether transaction calldata or blob) is allocated externally to the EVM, so no changes are needed internally to the EVM to price calldata or blob separately.

We can come up with a "solution in the style of EIP-7623" to address this issue. Here is a simple implementation: charge 4 times the fee for storage operations during execution; for simplification of analysis, assume each storage operation costs 10000 gas. At the end of the transaction, refund min(7500 * storage_operations, execution_Gas). As a result, after deducting the refund, the user needs to pay the following fees:

execution_Gas + 10000 * storage_operations - min(7500 * storage_operations, execution_Gas)

This equals:

max(execution_Gas + 2500 * storage_operations, 10000 * storage_operations)

This reflects the structure of EIP-7623. Another approach is to track storage_operations and execution_Gas in real-time and charge 2500 or 10000 based on how much max(execution_Gas + 2500 * storage_operations, 10000 * storage_operations) has increased at the time the opcode is called. This avoids the need for transactions to over-allocate Gas, which is mainly recovered through refunds.

We did not obtain fine-grained permission for subcalls: subcalls may consume all the allowance of a transaction for cheap storage operations.

But we did get something quite good, that is, the contract performing the subcall can set a limit and ensure that once the subcall is completed, the main call still has enough Gas for the required post-processing.

The simplest "complete multidimensional pricing solution" I can think of is: we consider the Gas limit for subcalls to be proportional. That is, assuming there are 𝑘 different types of executions, and each transaction sets multidimensional limits 𝐿1...𝐿𝑘. Assume at the current execution point, the remaining Gas is 𝑔1...𝑔𝑘. Assume a CALL opcode is invoked, using a subcall Gas limit 𝑆. Let 𝑠1=𝑆, then 𝑠2=𝑠1/𝑔1*𝑔2, 𝑠3=𝑠1/𝑔1*𝑔3, and so on.

In other words, we treat the Gas for the first type (actually VM execution) as a special "account unit," and then allocate Gas for other types so that subcalls receive the same percentage of available Gas in each type. This approach may look a bit ugly, but it maximizes backward compatibility.

If we want to make this solution more "neutral" between different types of Gas without sacrificing backward compatibility, we can simply represent the Gas limit parameter for subcalls as a part of the remaining Gas in the current context (e.g., [1...63]/64).

However, regardless of the case, it is worth emphasizing that once we start introducing multidimensional execution Gas, inherent complexity will increase, which seems hard to avoid.

Therefore, our task is to make a complex trade-off: do we accept some degree of increased complexity (ugliness) at the EVM level to safely unlock significant L1 scalability gains, and if so, which specific proposal is most effective for protocol economics and application developers? It is very likely that neither of the two solutions I mentioned above is the best, but there is still room to propose more elegant and better solutions.

Special thanks to Ansgar Dietrichs, Barnabe Monnot, and Davide Crapis for their feedback and review.

Associated Labels
Multidimensional Gas Pricing, EVM, Rollup, EIP-1559, Blobs
ChainCatcher reminds readers to rationally view blockchain, enhance risk awareness, be vigilant against various virtual token issuances and speculation. All content on the site is market information or opinions of relevant parties and does not constitute any form of investment advice. If sensitive information is found in the content on the site, you can click "Report," and we will handle it promptly.
0

Disclaimer: The content of this article solely reflects the author's opinion and does not represent the platform in any capacity. This article is not intended to serve as a reference for making investment decisions.

PoolX: Stake to earn
APR up to 10%. Always on, always earning.
Stake now!