Spawned by a discussion with @isheff and others in the state architecture ART review call, I propose that we specify a mechanism for gas payment (or, more specifically, payment for transaction function execution) as part of the resource machine specs, which would work as follows:
- We introduce a new datatype
TransactionFunctionWithPayment
, which consists of three elements:
a. A transaction function (as currently in the RM specs).
b. A transaction object (the “payment transaction”), which includes in a special application data field the hash of the transaction function and the gas limit.
c. A gas limit (natural number). - When executing a
TransactionFunctionWithPayment
, the executor takes the following steps:
a. Checks that the payment transaction is “simple”. What exactly this means can be executor-specific, but roughly “simple” means “inexpensive to verify”. A basic (very restrictive) check could be that the payment transaction has exactly one consumed resource and nothing else.
b. Decide whether this gas payment is sufficient. This decision can be controller-specific (maybe there are certain assets and certain prices accepted for gas).
c. Alter the payment transaction, adding new resources assigned to the executor (or whoever is supposed to receive the gas payments) as necessary to make the payment transaction balanced.
d. Check that the payment transaction is fully valid and balanced (normal transaction rules), including in a special application data field the hash of the transaction function and the gas limit.
e. Execute the payment transaction (apply the state changes).
f. Compute the transaction function, limited by the specified gas limit.
g. If the transaction function computation finishes within the gas limit (returning a transaction object), check that the transaction object is valid and balanced, and if so apply it to state (as previously in the RM).
I like this approach for a few reasons:
- It does the basic thing we want (a simple transaction pays for the potentially costly execution of the transaction function).
- It’s pretty simple and uses mostly data structures and logic which we already have.
- It’s quite general, doesn’t fix a particular token which must be used to pay for gas, and even allows for solving as part of the gas payment (e.g. controller accepts token X, user wants to pay for gas in token Y, a solver can match this with another X → Y intent and produce a valid payment transaction).
I’m looking for quick feedback from @isheff @vveiln and @degregat. If this looks good, we can add it to the specs next week (in full detail). Otherwise, raise any questions or concerns here.