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

graphql, internal/ethapi: extend eth_call #19917

Merged
merged 2 commits into from
Aug 8, 2019

Conversation

rjl493456442
Copy link
Member

@rjl493456442 rjl493456442 commented Aug 6, 2019

This PR implements the feature required by #19836

The JSON RPC spec of this API is

eth_call
Executes a new message call with a set of overloaded contract code.

Parameters
1. Object - The transaction call object
from: DATA, 20 Bytes - (optional) The address the transaction is sent from.
to: DATA, 20 Bytes - The address the transaction is directed to.
gas: QUANTITY - (optional) Integer of the gas provided for the transaction execution. eth_call consumes zero gas, but this parameter may be needed by some executions.
gasPrice: QUANTITY - (optional) Integer of the gasPrice used for each paid gas
value: QUANTITY - (optional) Integer of the value sent with this transaction
data: DATA - (optional) Hash of the method signature and encoded parameters. For details see Ethereum Contract ABI

2. Block number
QUANTITY|TAG - integer block number, or the string "latest", "earliest" or "pending", see the default block parameter

3. Codes
DATA: DATA - (optional) the override map contains all contract address and new execution code mappings.

Returns
DATA - the return value of executed contract.

curl example:

curl -H "Content-Type: application/json" -X POST  localhost:8545 --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to": "oxaddr", "data": "oxdata"}, "latest", {"0xaddr1":"0xcode1...", "0xaddr2":"0xcode2..."}],"id":1}'

or

curl -H "Content-Type: application/json" -X POST  localhost:8545 --data '{"jsonrpc":"2.0","method":"eth_call","params":[{"to": "oxaddr", "data": "oxdata"}, "latest"],"id":1}'

@rjl493456442 rjl493456442 changed the title graphql, internal/ethapi: implement eth_callCode graphql, internal/ethapi: extend eth_call Aug 6, 2019
This PR offers the third option parameter for eth_call API.
Caller can specify a batch of contracts for overriding the
original account metadata(nonce, balance, code, state).
It has a few advantages:

* It's friendly for debugging
* It's can make on-chain contract lighter for getting rid of
  state access functions
internal/ethapi/api.go Outdated Show resolved Hide resolved
internal/ethapi/api.go Outdated Show resolved Hide resolved
internal/ethapi/api.go Outdated Show resolved Hide resolved
internal/ethapi/api.go Outdated Show resolved Hide resolved
internal/ethapi/api.go Outdated Show resolved Hide resolved
core/state/state_object.go Outdated Show resolved Hide resolved
core/state/statedb.go Outdated Show resolved Hide resolved
@karalabe karalabe added this to the 1.9.2 milestone Aug 8, 2019
Copy link
Member

@karalabe karalabe left a comment

Choose a reason for hiding this comment

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

SGTM

@karalabe karalabe merged commit c9cdf14 into ethereum:master Aug 8, 2019
@egalano
Copy link

egalano commented Aug 13, 2019

@karalabe like @rjl493456442 mentioned in #19836 I think should have been discussed in an EIP. While it is backwards compatible with the current implementation, the additional functionality breaks compatibility of eth_call across client implementations. Currently, eth_call rpc users are able to swap parity for pantheon or geth interchangeably. This change removes that flexibility.

Additionally, for API providers like us (Infura) and Cloudflare, this has significant security and stability implications. My understanding of the code is that while the storage is only modified for the duration of the request, it does not have sole access to the storage during that period in time so any additional RPC requests which access this storage key during that time will be hitting the polluted/modified storage.

I would propose that this functionality should be included in the debug namespace as debug_callWithContext or something similar. If a dapp needs to override eth_call to get this functionality they can override web3.call in their provider library.

In general I would propose that any changes backwards compatible or not that change the behavior of eth_call to introduce new functionality be proposed as an EIP to ensure that if it lands in the eth_ namespace it is compatible cross-client.

@karalabe
Copy link
Member

Hey @egalano, thanks for reaching out with your concerns. Here's a few answers to clarify the details:

@karalabe like @rjl493456442 mentioned in #19836 I think should have been discussed in an EIP. While it is backwards compatible with the current implementation, the additional functionality breaks compatibility of eth_call across client implementations. Currently, eth_call rpc users are able to swap parity for pantheon or geth interchangeably. This change removes that flexibility.

I was under the impression that this feature is mostly a debugging tool to aid @chriseth, I didn't consider it something that all clients would expect to implement. Retrospectively - with the proposed use case of offchain contract snippets - it makes a lot more sense to EIP it. I'm fine with defining the spec in an EIP and making any necessary changes to adhere to any changes.

Additionally, for API providers like us (Infura) and Cloudflare, this has significant security and stability implications. My understanding of the code is that while the storage is only modified for the duration of the request, it does not have sole access to the storage during that period in time so any additional RPC requests which access this storage key during that time will be hitting the polluted/modified storage.

Your understanding is wrong here. The modifications are never pushed or exposed to any other part of the system, or even other concurrent calls. What happens is that a new state is assembled in-memory against which the call executes. This modified state is exclusively scoped to the individual API call. There's no way that one call can influence any other call or any other part of the system. IF not, that's definitely a huge problem that needs to be fixed (please send a repro).

@egalano
Copy link

egalano commented Aug 13, 2019

I'm fine with defining the spec in an EIP and making any necessary changes to adhere to any changes.

Thanks for this. I'm happy to contribute to that EIP discussion.

What happens is that a new state is assembled in-memory against which the call executes. There's no way that one call can influence any other call or any other part of the system...If not, that's definitely a huge problem that needs to be fixed

Ah got it. Thanks for clarifying. We haven't tested the new functionality yet but will report any issues we encounter.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants