Skip to content
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

Introduce fixed gas for transfers #939

Closed
herr-seppia opened this issue Jun 28, 2023 · 1 comment · Fixed by #940
Closed

Introduce fixed gas for transfers #939

herr-seppia opened this issue Jun 28, 2023 · 1 comment · Fixed by #940
Labels
module:rusk Issues related to rusk module

Comments

@herr-seppia
Copy link
Member

Summary

Currently, when rusk is performing transactions, it calls the method execute of the transfer contract
execute methods does the following:

  • Verify the tx is spendable
  • Spend the inputs+fee and create the outputs
  • Call the interContract method (if any)
  • Refund the fee change (gas_left*gas_price)

Current implementation lead to some issues, due to the atomic logic of piecrust (a sort of "all or nothing).

  • If a tx runs OOG while executing a contract call everything is reverted (no fee spent)
  • If a tx runs OOG while refunding the change, the ICC is reverted
  • If a tx runs OOG while spending, tx should be discarded completely (and we have no way to determine it, because now it looks like a OOG while executing)

Possible solution design or implementation

Introduce a fixed artificial gas limit for transfers (aka TX_GAS)

Split the execute into three different host calls:

  1. spend: ensure that tx.gas_limit >= TX_GAS and set session to use GasLimit::MAX
  2. call (if any): set session's gas limit to tx.gas_limit-TX_GAS
  3. refund: pop crossover (if any) and refund tx.gas_limit - call.gas_spent - TX_GAS)

With this 3 host functions, rusk can handle all the actual use cases:

  • If panics while spend then tx should be discarded
  • If panic while call then tx return Err(_), otherwise it's considered successful
  • refund should never fail

Additional context

N.B:

  • refunding become free
  • we still have to decide if we have to revert a panicked IIC, maybe it's up to the contract developer
@herr-seppia herr-seppia added module:transfer-contract module:rusk Issues related to rusk module labels Jun 28, 2023
@herr-seppia
Copy link
Member Author

To keep it simpler, we can wrap those 3 fn in a new execute that return Result<TransactionResult, InvalidTx> where

enum TransactionResult {
  SUCCESS,
  FAIL(Piecrust::Error)
}

enum InvalidTx {
  UNSPENDABLE,
  OTHER
}

ureeves added a commit that referenced this issue Jun 29, 2023
To allow for splitting execution of a transaction, we split the
`execute` function into two different functions - `spend` and `refund`.

The `spend` function checks that a transaction can spend its inputs and
produce its outputs, and execute the transfer, while the `refund`
function refunds a specific amount to the previously performed
transaction.

This allows the host to execute code in between the two calls, such as
executing a contract call, and decide exactly what a transaction should
be charged based on the results.

See also: #939
ureeves added a commit that referenced this issue Jun 29, 2023
ureeves added a commit that referenced this issue Jun 29, 2023
Transactions are now executed in three steps:

1. Call to "spend" to spend inputs and generate outputs
2. Execute possible contract call
3. Call to "refund" to refund the transaction some amount

This allows the host to specify *exactly* the amount of gas it wants to
charge a transaction. In this case we choose to charge `0.001 Dusk` per
input of a transaction, at a gas price of 1.

Resolves: #939
ureeves added a commit that referenced this issue Jun 29, 2023
Transactions are now executed in three steps:

1. Call to "spend" to spend inputs and generate outputs
2. Execute possible contract call
3. Call to "refund" to refund the transaction some amount

This allows the host to specify *exactly* the amount of gas it wants to
charge a transaction. In this case we choose to charge `0.001 Dusk` per
input of a transaction, at a gas price of 1.

Resolves: #939
ureeves added a commit that referenced this issue Jun 29, 2023
Transactions are now executed in three steps:

1. Call to "spend" to spend inputs and generate outputs
2. Execute possible contract call
3. Call to "refund" to refund the transaction some amount

This allows the host to specify *exactly* the amount of gas it wants to
charge a transaction. In this case we choose to charge `0.001 Dusk` per
input of a transaction, at a gas price of 1.

Resolves: #939
ureeves added a commit that referenced this issue Jun 29, 2023
Transactions are now executed in three steps:

1. Call to "spend" to spend inputs and generate outputs
2. Execute possible contract call
3. Call to "refund" to refund the transaction some amount

This allows the host to specify *exactly* the amount of gas it wants to
charge a transaction. In this case we choose to charge `0.001 Dusk` per
input of a transaction, at a gas price of 1.

Resolves: #939
ureeves added a commit that referenced this issue Jun 29, 2023
Transactions are now executed in three steps:

1. Call to "spend" to spend inputs and generate outputs
2. Execute possible contract call
3. Call to "refund" to refund the transaction some amount

This allows the host to specify *exactly* the amount of gas it wants to
charge a transaction. In this case we choose to charge `1_000_000` per
input of a transaction.

Resolves: #939
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
module:rusk Issues related to rusk module
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant