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

[FVM] Fail fast when payer cannot pay #3473

Merged
merged 1 commit into from
Dec 7, 2022
Merged

Conversation

janezpodhostnik
Copy link
Contributor

@janezpodhostnik janezpodhostnik commented Oct 28, 2022

This is the first part of #2767

Payer must have sufficient balance for the transaction execution to happen.
The required balance is defined by the smart contract.

related to: onflow/flow-emulator#231 and onflow/flow-core-contracts#318

@janezpodhostnik janezpodhostnik added the Execution Cadence Execution Team label Oct 28, 2022
@janezpodhostnik janezpodhostnik self-assigned this Oct 28, 2022
@codecov-commenter
Copy link

codecov-commenter commented Oct 28, 2022

Codecov Report

Merging #3473 (c488364) into master (0459d16) will increase coverage by 4.51%.
The diff coverage is n/a.

@@            Coverage Diff             @@
##           master    #3473      +/-   ##
==========================================
+ Coverage   55.32%   59.83%   +4.51%     
==========================================
  Files         768      152     -616     
  Lines       69922    17223   -52699     
==========================================
- Hits        38683    10306   -28377     
+ Misses      28055     6065   -21990     
+ Partials     3184      852    -2332     
Flag Coverage Δ
unittests 59.83% <ø> (+4.51%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Impacted Files Coverage Δ
engine/consensus/compliance/core.go 73.98% <0.00%> (ø)
fvm/bootstrap.go
fvm/environment/env.go
fvm/environment/system_contracts.go
fvm/errors/codes.go
fvm/errors/execution.go
fvm/systemcontracts/system_contracts.go
fvm/transactionInvoker.go
fvm/transactionStorageLimiter.go
utils/unittest/execution_state.go
... and 607 more

Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.

@github-actions
Copy link
Contributor

github-actions bot commented Oct 28, 2022

FVM Benchstat comparison

This branch with compared with the base branch onflow:master commit 0459d16

The command (for i in {1..7}; do go test ./fvm ./engine/execution/computation --bench . --tags relic -shuffle=on --benchmem --run ^$; done) was used.

Collapsed results for better readability

old.txtnew.txt
time/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeNFTBatchTransfer-2142ms ± 5%139ms ± 0%~(p=0.750 n=7+1)
RuntimeTransaction/reference_tx-236.9ms ± 2%37.6ms ± 0%~(p=0.571 n=6+1)
RuntimeTransaction/convert_int_to_string-237.6ms ± 4%38.5ms ± 0%~(p=0.571 n=6+1)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-240.4ms ± 4%43.3ms ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/get_signer_address-237.6ms ± 5%38.2ms ± 0%~(p=0.750 n=7+1)
RuntimeTransaction/get_public_account-241.1ms ± 4%41.3ms ± 0%~(p=0.857 n=6+1)
RuntimeTransaction/get_account_and_get_available_balance-2319ms ± 7%325ms ± 0%~(p=0.750 n=7+1)
RuntimeTransaction/get_account_and_get_storage_used-242.7ms ± 4%44.6ms ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_account_and_get_storage_capacity-2280ms ± 1%278ms ± 0%~(p=1.000 n=6+1)
RuntimeTransaction/get_signer_vault-245.8ms ± 7%49.0ms ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/get_signer_receiver-258.9ms ± 9%59.6ms ± 0%~(p=0.750 n=7+1)
RuntimeTransaction/transfer_tokens-2245ms ± 5%236ms ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-245.2ms ± 6%47.5ms ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/load_and_save_long_string_on_signers_address-293.2ms ± 2%99.5ms ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/create_new_account-2995ms ± 1%974ms ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/call_empty_contract_function-240.4ms ± 3%43.8ms ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/emit_event-256.7ms ± 3%62.7ms ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/borrow_array_from_storage-2162ms ± 6%169ms ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/copy_array_from_storage-2165ms ± 2%168ms ± 0%~(p=0.500 n=7+1)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-25.30s ± 4%5.96s ± 0%~(p=0.250 n=7+1)
 
alloc/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeNFTBatchTransfer-253.4MB ± 5%52.3MB ± 0%~(p=0.750 n=7+1)
RuntimeTransaction/reference_tx-234.1MB ± 3%34.9MB ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/convert_int_to_string-233.7MB ± 2%34.2MB ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-234.4MB ± 3%35.4MB ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_signer_address-233.9MB ± 3%34.1MB ± 0%~(p=1.000 n=7+1)
RuntimeTransaction/get_public_account-235.8MB ± 2%34.2MB ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/get_account_and_get_available_balance-2104MB ± 1%106MB ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/get_account_and_get_storage_used-235.7MB ± 4%35.7MB ± 0%~(p=1.000 n=7+1)
RuntimeTransaction/get_account_and_get_storage_capacity-298.6MB ± 3%98.0MB ± 0%~(p=1.000 n=7+1)
RuntimeTransaction/get_signer_vault-236.2MB ± 2%40.2MB ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_signer_receiver-240.9MB ± 3%40.0MB ± 0%~(p=0.750 n=7+1)
RuntimeTransaction/transfer_tokens-282.9MB ± 3%85.6MB ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-235.1MB ± 3%35.6MB ± 0%~(p=1.000 n=7+1)
RuntimeTransaction/load_and_save_long_string_on_signers_address-252.0MB ± 6%53.0MB ± 0%~(p=1.000 n=7+1)
RuntimeTransaction/create_new_account-2183MB ± 3%184MB ± 0%~(p=1.000 n=7+1)
RuntimeTransaction/call_empty_contract_function-234.8MB ± 3%35.5MB ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/emit_event-240.5MB ± 4%41.9MB ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/borrow_array_from_storage-268.1MB ± 7%70.7MB ± 0%~(p=0.500 n=7+1)
RuntimeTransaction/copy_array_from_storage-279.6MB ± 4%81.4MB ± 0%~(p=0.500 n=7+1)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-21.10GB ± 0%1.21GB ± 0%~(p=0.333 n=5+1)
 
allocs/opdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeNFTBatchTransfer-2259k ± 0%272k ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/reference_tx-274.4k ± 0%84.3k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/convert_int_to_string-286.6k ± 0%96.5k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-297.8k ± 0%107.7k ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/get_signer_address-278.6k ± 0%88.5k ± 0%~(p=0.333 n=5+1)
RuntimeTransaction/get_public_account-2100k ± 0%110k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_account_and_get_available_balance-21.19M ± 0%1.20M ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_account_and_get_storage_used-2110k ± 0%120k ± 0%~(p=0.333 n=5+1)
RuntimeTransaction/get_account_and_get_storage_capacity-21.07M ± 0%1.08M ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/get_signer_vault-2117k ± 0%127k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_signer_receiver-2188k ± 0%198k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/transfer_tokens-2840k ± 0%841k ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-2117k ± 0%127k ± 0%~(p=0.286 n=6+1)
RuntimeTransaction/load_and_save_long_string_on_signers_address-2192k ± 0%202k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/create_new_account-22.27M ± 0%2.27M ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/call_empty_contract_function-288.8k ± 0%98.7k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/emit_event-2127k ± 0%137k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/borrow_array_from_storage-2330k ± 0%340k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/copy_array_from_storage-2286k ± 0%296k ± 0%~(p=0.250 n=7+1)
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-215.8M ± 0%17.7M ± 0%~(p=0.250 n=7+1)
 
computationdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/reference_tx-2202 ± 0%202 ± 0%~(all equal)
RuntimeTransaction/convert_int_to_string-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-2502 ± 0%502 ± 0%~(all equal)
RuntimeTransaction/get_signer_address-2302 ± 0%302 ± 0%~(all equal)
RuntimeTransaction/get_public_account-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_available_balance-22.60k ± 0%2.60k ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_storage_used-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/get_account_and_get_storage_capacity-21.30k ± 0%1.30k ± 0%~(all equal)
RuntimeTransaction/get_signer_vault-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/get_signer_receiver-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/transfer_tokens-23.50k ± 0%3.50k ± 0%~(all equal)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/load_and_save_long_string_on_signers_address-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/create_new_account-2202 ± 0%202 ± 0%~(all equal)
RuntimeTransaction/call_empty_contract_function-2402 ± 0%402 ± 0%~(all equal)
RuntimeTransaction/emit_event-2602 ± 0%602 ± 0%~(all equal)
RuntimeTransaction/borrow_array_from_storage-22.60k ± 0%2.60k ± 0%~(all equal)
RuntimeTransaction/copy_array_from_storage-22.60k ± 0%2.60k ± 0%~(all equal)
 
interactionsdelta
pkg:github.com/onflow/flow-go/fvm goos:linux goarch:amd64
RuntimeTransaction/reference_tx-244.3k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/convert_int_to_string-244.3k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/convert_int_to_string_and_concatenate_it-244.3k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_signer_address-244.3k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_public_account-244.3k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_account_and_get_available_balance-25.13M ± 0%5.25M ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_account_and_get_storage_used-244.3k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_account_and_get_storage_capacity-25.13M ± 0%5.25M ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_signer_vault-244.5k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/get_signer_receiver-244.9k ± 0%157.4k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/transfer_tokens-245.2k ± 0%157.5k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/load_and_save_empty_string_on_signers_address-244.4k ± 0%157.1k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/load_and_save_long_string_on_signers_address-247.2k ± 0%159.8k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/create_new_account-28.39M ± 0%11.71M ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/call_empty_contract_function-244.5k ± 0%157.3k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/emit_event-244.5k ± 0%157.3k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/borrow_array_from_storage-249.7k ± 0%162.3k ± 0%~(p=0.250 n=7+1)
RuntimeTransaction/copy_array_from_storage-249.7k ± 0%162.3k ± 0%~(p=0.250 n=7+1)
 
us/txdelta
pkg:github.com/onflow/flow-go/engine/execution/computation goos:linux goarch:amd64
ComputeBlock/16/cols/128/txes-22.59k ± 4%2.91k ± 0%~(p=0.250 n=7+1)
 

@bluesign
Copy link
Contributor

I am late to the party, but why do we need MaxTxFees here? Why not MAB is not enough alone?

Considering when I have <MAB, any transaction will fail, and I will end up with <MAB; isn't it enough check to filter transactions and reject? Why do we need to cast the net wider here?

@janezpodhostnik
Copy link
Contributor Author

@bluesign I went into more detail in the issue itself #2767, but generally the Idea is that if the payer is at MAB and the transaction is run and the payers vault doesn't get a deposit during the transaction, the transaction will fail anyway because payers balance will be below MAB.

@bluesign
Copy link
Contributor

bluesign commented Nov 1, 2022

thanks @janezpodhostnik, but I fail to see the benefit here; probably I am missing something:

Now; in the case of MAB, limit is constant. But when we introduce limit as a function of gas_limit ( MAB + cost(msx_gas_limit) ) we only cover very limited cases ( which are not important ) but generate extra complication.

Considering my account has MAB + delta ( where delta is a small amount ) of balance, It is in a state of unknown, isn't it easier to cache without this delta and calculation? If we have an account that has < MAB, we can cache the result, and even skip the MAB check ( until balance > MAB ), but when we have MAB + delta calculation, we are losing that possibility.

@janezpodhostnik
Copy link
Contributor Author

That is a good argument! I will bring that up with the team.

This change would go into the smart contract anyway, so it doesn't affect this PR in particular, but the feature in general.

@janezpodhostnik janezpodhostnik force-pushed the janez/fail-fast-payer-cannot-pay branch 2 times, most recently from 58d3e8e to fc1eb83 Compare November 1, 2022 15:19
inclusionEffort uint64,
maxExecutionEffort uint64,
) (cadence.Value, error) {
return sys.Invoke(
Copy link
Contributor

@Tonix517 Tonix517 Nov 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you have profiling info about how much this extra overhead will be? wondering if it can be less than deductFees & checkStorage cadence calls.

@Tonix517
Copy link
Contributor

Tonix517 commented Nov 1, 2022

i'm thinking out loud: would it be helpful if Cadence can provide FVM more info like, if there's any withdraw in the contract, and pass it to FVM as a flag, so that FVM will have more info to make decisions like this.

@bluesign
Copy link
Contributor

bluesign commented Nov 4, 2022

i'm thinking out loud: would it be helpful if Cadence can provide FVM more info like, if there's any withdraw in the contract, and pass it to FVM as a flag, so that FVM will have more info to make decisions like this.

It is very good idea, but this being a good idea makes implementing it a bad idea ( in a way ) If this is a need ( and I agree it is ) solution is not for cadence to provide FVM information but instead FVM should take responsibility for storage (atree and friends ) ( as we are resource-aware blockchain ) and it should provide storage functions to Cadence. ( I know it is easier said than done, e.g. It is not so easy with metering etc )

@janezpodhostnik janezpodhostnik force-pushed the janez/fail-fast-payer-cannot-pay branch 4 times, most recently from 383a5f7 to 55d69c8 Compare November 29, 2022 16:56
@janezpodhostnik janezpodhostnik marked this pull request as ready for review November 29, 2022 18:21
fvm/errors/execution.go Outdated Show resolved Hide resolved
uint64(txnState.TotalComputationLimit()),
)
if err != nil {
return 0, errors.NewPayerBalanceCheckError(proc.Transaction.Payer, err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NewPayerBalanceCheckError should be a failure instead of error?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure This should be a failure, but I don't have a good argument against it.

Let me create a separate PR for making this a failure, so I can move this one forward.

fvm/transactionPayerBalanceChecker.go Outdated Show resolved Hide resolved
fvm/transactionInvoker.go Outdated Show resolved Hide resolved
fvm/fvm_blockcontext_test.go Outdated Show resolved Hide resolved
@@ -275,6 +276,21 @@ func (executor *transactionExecutor) normalExecution() (
modifiedSets programsCache.ModifiedSetsInvalidator,
err error,
) {
executor.txnState.RunWithAllLimitsDisabled(func() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, should this check be done in ExecuteTransactionBody, before getBodyMeterParameters?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

o ... nevermind. i need to move getBodyMeterParameters into preprocessing, which would defeat this point.

fvm/environment/system_contracts.go Show resolved Hide resolved
fvm/transactionPayerBalanceChecker.go Show resolved Hide resolved
@janezpodhostnik
Copy link
Contributor Author

bors merge

@bors bors bot merged commit 69e3570 into master Dec 7, 2022
@bors bors bot deleted the janez/fail-fast-payer-cannot-pay branch December 7, 2022 16:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Execution Cadence Execution Team
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants