Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure #9824

Merged
merged 3 commits into from
Nov 14, 2018

Conversation

niklasad1
Copy link
Collaborator

@niklasad1 niklasad1 commented Oct 29, 2018

Attempt to close #6155 & close #9031

What does this PR:

  1. Differentiate between out-of-gas/manual throw
  2. Changes the start_gas from 50_000 to 60_000
  3. If too little gas is submitted in a transaction then we use to the required start_gas replied to us to set the next start_gas if it doesn't exceed the block's gas limit (however this could be changed to set the start_gas regardless of block_limit and continue until we get BlockGasLimitReached error instead, will probably require at least one extra network request)

Example execution with 50_000 as start_gas:

2018-10-29 15:45:05  jsonrpc-eventloop-1 TRACE light_fetch  Placing execution request for 50000 gas in on_demand
2018-10-29 15:45:05  jsonrpc-eventloop-1 TRACE light_fetch  Not enough start gas provided required: 53000, got: 50000
2018-10-29 15:45:05  jsonrpc-eventloop-1 TRACE light_fetch  Placing execution request for 53000 gas in on_demand

@niklasad1 niklasad1 added A0-pleasereview 🤓 Pull request needs code review. M4-core ⛓ Core client code / Rust. labels Oct 29, 2018
@ordian ordian added B1-patch-beta 🕷🕷 B0-patch-stable 🕷 Pull request should also be back-ported to the stable branch. labels Oct 29, 2018
@ordian ordian added this to the 2.3 milestone Oct 29, 2018
@ordian
Copy link
Collaborator

ordian commented Oct 29, 2018

@niklasad1 looks nice, but I'm yet to test it. Could you add a unit test? :)

@niklasad1 niklasad1 force-pushed the light/readonly-cant-run-out-of-gas branch 2 times, most recently from 452a20d to 418d20f Compare October 29, 2018 15:41
@niklasad1 niklasad1 requested a review from cheme October 29, 2018 15:55
@niklasad1
Copy link
Collaborator Author

@ordian
Yes, ideally I should have but it would require to mock a Full Node which is a much bigger task. Is manual testing ok for this one?

Might be a little annoying but change the start_gas in proved_read_only_execution to some value and create eth_call request without gas from an account with zero balance!

@niklasad1 niklasad1 closed this Oct 29, 2018
@niklasad1 niklasad1 reopened this Oct 29, 2018
Copy link
Contributor

@cheme cheme left a comment

Choose a reason for hiding this comment

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

The PR looks good (with the switch to virtual this is a nice optimization and should indeed solve the transaction cost issue (I did not test)), I got a few comment/suggestion.

I still believe we need to switch back to non virtual execution or find a way to circumvent the issue I talk to you about last friday (currently I could not think of any other way than switching back).

rpc/src/v1/helpers/light_fetch.rs Outdated Show resolved Hide resolved
} else {
return Ok(future::Loop::Continue(params))
}
// `OutOfGas` exception can't occur here because of virtual execution context
Copy link
Contributor

Choose a reason for hiding this comment

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

Even if it will not be executed, I think we should keep the existing code (with the new NotEnoughBaseGas exeption). That way we can still support non updated full peers (there should not be much in fact), and we could revert to non virtual full node execution more easily in the future (switching back to non virtual will not imply having to update every light client).

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I don't understand this. NotEnoughBasGas is not an exception, see https://github.com/paritytech/parity-ethereum/blob/master/ethcore/vm/src/error.rs#L38-#L86

Clarify please :P

Copy link
Contributor

Choose a reason for hiding this comment

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

👍 indeed, we could use vm::Error::OutOfGas instead.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Right, got it very good catch 👍

Ok(future::Loop::Break(Err(ExecutionError::NotEnoughBaseGas { required, got })))
}
}
// Non-recoverable execution error
Copy link
Contributor

Choose a reason for hiding this comment

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

Here (we need to test to assert the error actually occurs), there is possibly 'ExecutionError::BlockGasLimitReached', maybe we do not need the previous test.

Copy link
Collaborator Author

@niklasad1 niklasad1 Oct 30, 2018

Choose a reason for hiding this comment

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

Well, If we get BlockGasLimitReached then it is definitely a faulty request and AFAIK any of the others errors can't be recovered!

The possible errors can be found:
https://github.com/paritytech/parity-ethereum/blob/master/ethcore/src/executed.rs#L74-#L118

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes I was just wondering if the test above could be remove, but it seems safe to keep it.

trace!(target: "light_fetch", "Not enough start gas provided required: {}, got: {}", required, got);
if required <= params.hdr.gas_limit() {
params.tx.gas = required;
return Ok(future::Loop::Continue(params))
Copy link
Contributor

Choose a reason for hiding this comment

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

I am just thinking about it, but we probably want to apply a margin (a n% fix additional cost) : since the transaction may not run in the same block (and even in the same block it can vary) the cost may change when running the actual transaction.
It is not really related to this PR, but likely to happen with some contracts, this PR may makes it more obvious (previously by doubling gas cost there was lesser chance for it to happen).

Copy link
Contributor

Choose a reason for hiding this comment

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

this is something that we have historically decided not to handle on the node side in order to give the most faithful estimate we can. Wrappers around the RPCs typically add a few percent to the result of estimateGas.

@niklasad1 niklasad1 changed the title light: Execute read_only can't run out-of-gas and use required gas from response on failure light-fetch: Differiate between out-of-gas/manual throw and use required gas from response on failure Oct 30, 2018
@niklasad1 niklasad1 changed the title light-fetch: Differiate between out-of-gas/manual throw and use required gas from response on failure light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure Oct 30, 2018
@niklasad1 niklasad1 force-pushed the light/readonly-cant-run-out-of-gas branch from 418d20f to 592ca94 Compare October 30, 2018 12:59
This was referenced Nov 1, 2018
// TODO: how to distinguish between actual OOG and
// exception?
if executed.exception.is_some() {
// `OutOfGas` exception can only occur on full-nodes that run `Parity-Ethereum v2.1.1` or older
Copy link
Contributor

Choose a reason for hiding this comment

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

From our chat conversation of today, I think we may still run into out of gas.

Copy link
Collaborator Author

@niklasad1 niklasad1 Nov 9, 2018

Choose a reason for hiding this comment

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

Thanks, should be sufficient just to change the comment right?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think so, (we thankfully kept code for iterative querying).

@niklasad1 niklasad1 force-pushed the light/readonly-cant-run-out-of-gas branch 2 times, most recently from 6f8f743 to 4786558 Compare November 9, 2018 10:36
This was referenced Nov 13, 2018
if params.tx.gas > params.hdr.gas_limit() {
trace!(target: "light_fetch", "OutOutGas exception received, gas increase: failed");
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why dont we try with the params.hdr.gas_limit() at the very end? I can easily imagine a situation, where block_gas_limit / 2 + 1 is not sufficient, but block_gas_limit / 2 + 2 is enough.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Collaborator

@ordian ordian left a comment

Choose a reason for hiding this comment

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

I'm in favor of merging this PR. This comment can be addressed in a separate one.

@cheme
Copy link
Contributor

cheme commented Nov 13, 2018

Same thing here, I just feel that @tomusdrw comment should be addressed (when we multiply gas by 2 we should finish with max block size (if not already eq to max block size)).

Something along the line of :

if params.tx.gas == params.hdr.gas_limit() {
  trace!(target: "light_fetch", "OutOutGas exception received, gas increase: failed");
} else {
  params.tx.gas = params.tx.gas * 2_u32;

  if params.tx.gas > params.hdr.gas_limit() {
    params.tx.gas = params.hdr.gas_limit();
  }
  trace!(target: "light_fetch", "OutOutGas exception received, gas increase: succeed");
  return Ok(future::Loop::Continue(params))
}
  

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response
Try the `block_gas_limit` before regard the execution as an error
@niklasad1 niklasad1 force-pushed the light/readonly-cant-run-out-of-gas branch from 4786558 to 73c00b9 Compare November 13, 2018 17:31
Copy link
Contributor

@cheme cheme left a comment

Choose a reason for hiding this comment

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

LGTM, just a small nitpick on the comparison but it should not really be an issue.

rpc/src/v1/helpers/light_fetch.rs Outdated Show resolved Hide resolved
Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>
@ordian ordian added A8-looksgood 🦄 Pull request is reviewed well. A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. and removed A0-pleasereview 🤓 Pull request needs code review. A8-looksgood 🦄 Pull request is reviewed well. labels Nov 14, 2018
@ordian ordian merged commit 23a2943 into master Nov 14, 2018
@ordian ordian deleted the light/readonly-cant-run-out-of-gas branch November 14, 2018 10:04
ordian pushed a commit that referenced this pull request Nov 14, 2018
…quired gas from response on failure (#9824)

* fix start_gas, handle OOG exceptions & NotEnoughGas

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response

* fix(light-fetch): ensure block_gas_limit is tried

Try the `block_gas_limit` before regard the execution as an error

* Update rpc/src/v1/helpers/light_fetch.rs

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>
ordian pushed a commit that referenced this pull request Nov 14, 2018
…quired gas from response on failure (#9824)

* fix start_gas, handle OOG exceptions & NotEnoughGas

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response

* fix(light-fetch): ensure block_gas_limit is tried

Try the `block_gas_limit` before regard the execution as an error

* Update rpc/src/v1/helpers/light_fetch.rs

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>
ordian added a commit that referenced this pull request Nov 14, 2018
ordian added a commit that referenced this pull request Nov 14, 2018
Tbaut added a commit that referenced this pull request Nov 14, 2018
* bump stable 2.1.6

* ethcore: use Machine::verify_transaction on parent block (#9900)

* ethcore: use Machine::verify_transaction on parent block

also fixes off-by-one activation of transaction permission contract

* ethcore: clarify call to verify_transaction

* fix: Intermittent failing CI due to addr in use (#9885)

Allow OS to set port at runtime

* gitlab-ci: make android release build succeed (#9743)


* use docker cargo config file for android builds

* make android build succeed

* Update light-client hardcoded headers for
foundation: #6692865, ropsten: #4417537, kovan: #9363457

* Remove rust-toolchain file (#9906)

* light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure (#9824)

* fix start_gas, handle OOG exceptions & NotEnoughGas

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response

* fix(light-fetch): ensure block_gas_limit is tried

Try the `block_gas_limit` before regard the execution as an error

* Update rpc/src/v1/helpers/light_fetch.rs

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>

* fix #9824 merge artifacts

* simplify cargo audit

* ci: nuke the gitlab caches (#9855)
Tbaut added a commit that referenced this pull request Nov 14, 2018
* Bump beta to version 2.2.1

* fix: Intermittent failing CI due to addr in use (#9885)

Allow OS to set port at runtime

* Use Weak reference in PubSubClient (#9886)

* Fix json tracer overflow (#9873)

* Fix json tracer overflow

* Replace trace_executed with a direct trace push

* Remove unused variable

* Add test for 5a51

* Remove duplicate json!

* Fix docker script (#9854)


* Dockerfile: change source path of the newly added check_sync.sh (#9869)

* Allow to seal work on latest block (#9876)

* Allow to seal work on latest block.

* Test from @todr to check sealing conditions.

* gitlab-ci: make android release build succeed (#9743)

* use docker cargo config file for android builds

* make android build succeed

* ethcore: use Machine::verify_transaction on parent block (#9900)

* ethcore: use Machine::verify_transaction on parent block

also fixes off-by-one activation of transaction permission contract

* ethcore: clarify call to verify_transaction

* foundation: #6692865, ropsten: #4417537, kovan: #9363457

* Remove rust-toolchain file (#9906)

* EIP-712 implementation (#9631)

* EIP-712 impl

* added more tests

* removed size parsing unwrap

* corrected TYPE_REGEX to disallow zero sized fixed length arrays, replaced LinkedHashSet with IndexSet, added API spec to docs, fixed Type::Byte encoding branch

* use Option<u64> instead of u64 for Type::Array::Length

* replace `.iter()` with  `.values()`

Co-Authored-By: seunlanlege <seunlanlege@gmail.com>

* tabify eip712.rs

* use proper comments for docs

* Cargo.lock: revert unrelated changes

* tabify encode.rs

* EIP 191 (#9701)

* added sign_191 rpc method

* fixed hash_structured_data return type

* added ConfirmationPayload::SignMessage for non-prefixed signatures, added tests for sign191

* renamed WithValidator -> PresignedTransaction

* rename applicationData to data in test

* adds docs for EIP191Version, renamed SignRequest to EIP191SignRequest

* light-fetch: Differentiate between out-of-gas/manual throw and use required gas from response on failure (#9824)

* fix start_gas, handle OOG exceptions & NotEnoughGas

* Change START_GAS: 50_000 -> 60_000
* When the `OutOfGas exception` is received then try to double the gas until it succeeds or block gas limit is reached
* When `NotEnoughBasGas error` is received then use the required gas provided in the response

* fix(light-fetch): ensure block_gas_limit is tried

Try the `block_gas_limit` before regard the execution as an error

* Update rpc/src/v1/helpers/light_fetch.rs

Co-Authored-By: niklasad1 <niklasadolfsson1@gmail.com>

* simplify cargo audit

* Use block header for building finality (#9914)

* ci: nuke the gitlab caches (#9855)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
A6-mustntgrumble 💦 Pull request has areas for improvement. The author need not address them before merging. B0-patch-stable 🕷 Pull request should also be back-ported to the stable branch. M4-core ⛓ Core client code / Rust.
Projects
None yet
5 participants