-
Notifications
You must be signed in to change notification settings - Fork 632
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
doc: meta transactions #8257
doc: meta transactions #8257
Conversation
@mm-near I completed the documentation to the best of my knowledge, now including also all the other bits, not just the gas accounting. Hopefully it helps with your review of #7497. @fadeevab and @e-uleyskiy I created this nearcore documentation regarding meta transactions to help other nearcore developers understand how it works. If you have a moment to read through it, I'd appreciate your feedback. I also stole your diagram, I hope that's okay. |
possible `SEND` costs is chosen. The `EXEC` cost is not burned, yet. But it | ||
is implicitly part of the transaction cost. The third and last part of the | ||
transaction cost is the gas attached to function calls. The attached gas is | ||
also called prepaid gas. (Not to be confused with `total_prepaid_exec_fees` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so there are basically 3 fields?
- burned_gas
- total_prepaid_exec_fees (these will be "burned" immediately on the receiver shard)
- prepaid_gas (gas that is remaining)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, yes, you can think of them as these 3 logical fields in this context. But you don't find them stored exactly like that. And throughout the code, there are more fields and their names are somewhat inconsistent...
If you look at ActionResult
, the actual gas fields stored are:
pub gas_burnt: Gas,
pub gas_burnt_for_function_call: Gas,
pub gas_used: Gas,
Here the gas_used
is = burned_gas + total_prepaid_exec_fees + prepaid_gas(outgoing)
.
The values for total_prepaid_exec_fees
and prepaid_gas
are never stored explicitly on the receipt level. It's always implicitly defined by the list of actions.
prepaid_gas
is only relevant for function calls and 0 everywhere else. Adding up the prepaid gas inn all function calls of the receipt will give you the total prepaid_gas
.
Likewise, the total_prepaid_exec_fees
is the sum of all execution fees for all actions. We don't have to store it explicitly, because we can recompute it if we know the list of actions, which is why I wrote it is "implicitly" part of the total cost.
gas_burnt_for_function_call
is not relevant for this discussion, it is only tracked separately for the 30% smart contract reward that only applies to the fraction of the cost that was burned for the actual function call.
In ExecutionOutcome
you only have one gas field:
pub gas_burnt: Gas,
Everything else is implicitly defined by looking at the outgoing receipts.
delegate action wrapping them. | ||
2. The cost of sending the inner actions and the delegate action from the | ||
relayer to Alice's shard will be burned immediately. The condition `relayer | ||
== Alice` determines which action `SEND` cost is taken (`sir` or `not_sir`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
out of curiosity - would it ever happen that Relayer == Alice ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I cannot think of a real scenario where it makes sense. Maybe testing your own relayer? Other than that it seems rather pointless. (Btw, we have many costs around SIR / NOT_SIR that practically don't make sense^^)
|
||
Each of these steps should make sense and not be too surprising. But the | ||
consequence is that the implicit costs paid at the relayer's shard are | ||
`SEND(1)` + `SEND(2)` + `EXEC` for all inner actions plus `SEND(1)` + `EXEC` for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is Send(1) and Send(2) ?
Does it mean that we pay Send(1) twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is Send(1) and Send(2) ?
It's the send costs where sender and receiver are defined by either Relayer/Alice or Alice/Bob. I've just added some text above that properly defines SEND(1)
and SEND(2)
.
Does it mean that we pay Send(1) twice?
No. SEND(1) + SEND(2)
is paid for the inner actions. Send fees are paid twice for inner actions but with different SIR condition. This should be the surprising bit, that send fees are charged twice for inner actions. This makes action sinside meta transactions more expensive than in normal transactions.
Only SEND(1)
is charged for the one outer delegate action, without the inner actions. This is the obvious way to do it, exactly like every other action is charge today.
EXEC
costs are paid for all actions involved, at block height h+1
for the outer action and h+2
for the inner actions. Note that when I write "cost of the outer action", this is exclusive the cost for inner actions.
4. On Bob's shard, we execute all inner actions and burn their `EXEC` cost. | ||
|
||
Each of these steps should make sense and not be too surprising. But the | ||
consequence is that the implicit costs paid at the relayer's shard are |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So all of these are paid on relayer shard ? (as in point 3 above you say that some of them happen on the Alice's shard)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The relayer pays everything upfront when purchasing the required amount of gas. The required amount of gas is implicitly defined by all actions in the receipt and potentially inner actions if we have a delegate action inside.
The burning happens in multiple steps. Burning is not the same as paying. I think I worded it correctly already, please let me know i I mixed it up somewhere.
the delegate action. This might be surprising but hopefully with this | ||
explanation it makes sense now! | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW - you might also want to mention the gas refunds -- that they should go back to the relayer, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good point. I've added a paragraph for this. (Yes they are all sent to the relayer)
|
||
## Balance refunds in meta transactions | ||
|
||
Unlike gas refunds, the protocol sends balance refunds to the predecessor |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Balance refunds happen only when receipt fails (or runs out of gas), right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes
Hey @mm-near I've tried to answer your in-code questions. I know this topic (gas in general) is way more complicated than it appears and meta transactions add a weird twist to it. I struggle to make it consumable for a general nearcore developer audience without prior knowledge on meta transactions and only basic understanding of how we charge gas for actions. Please let me know whether my explanations here make sense to you now, or which sections need improvment. (If you don't understand it, then who will?) I can rephrase some sections that currently are hard to grasp, or add more context where necessary. |
Uleyskiy._ | ||
|
||
|
||
The graphic shows an example use case for meta transactions. Alice owns an |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This overview section is great - thanks !
* doc: meta transactions gas and balance flow * document everything else about meta txs * address review comments * expand slightly more on complicated gas flow
No description provided.