This EIP specifies a GraphQL schema for accessing data stored on an Ethereum node. It aims to provide a complete replacement to the read-only information exposed via the present JSON-RPC interface, while improving on usability, consistency, efficiency, and future-proofing.
## Motivation
The current JSON-RPC interface for Ethereum nodes has a number of shortcomings. It's informally and incompletely specified in areas, which has led to incompatibilities around issues such as representation of empty byte strings ("" vs "0x" vs "0x0"), and it has to make educated guesses about the data a user will request, which often leads to unnecessary work.
For example, the `totalDifficulty` field is stored separately from the block header in common Ethereum node implementations, and many callers do not require this field. However, every call to `eth_getBlock` still retrieves this field, requiring a separate disk read, because the RPC server has no way of knowing if the user requires this field or not.
Similarly, transaction receipts in go-ethereum are stored on disk as a single binary blob for each block. Fetching a receipt for a single transaction requires fetching and deserializing this blob, then finding the relevant entry and returning it; this is accomplished by the `eth_getTransactionReceipt` API call. A common task for API consumers is to fetch all the receipts in a block; as a result, node implementations end up fetching and deserializing the same data repeatedly, leading to `O(n^2)` effort to fetch all transaction receipts from a block instead of `O(n)`.
Some of these issues could be fixed with changes to the existing JSON-RPC interface, at the cost of complicating the interface somewhat. Instead, we propose adopting a standard query language, GraphQL, which facilitates more efficient API implementations, while also increasing flexibility.
Nick Johnson and [EthQL](https://github.com/ConsenSys/ethql) independently developed a GraphQL schema for node data. Once the parties were made aware of the shared effort, they made efforts to bring their schemas into alignment. The current schema proposed in this EIP is derived primarily from the EthQL schema.
Compatible nodes MUST provide a GraphQL endpoint available over HTTP. This SHOULD be offered on port 8547 by default. The path to the GraphQL endpoint SHOULD be '/graphql'.
Compatible nodes MAY offer a GraphiQL interactive query explorer on the root path ('/').
### Schema
The GraphQL schema for this service is defined as follows:
```
# Bytes32 is a 32 byte binary string, represented as 0x-prefixed hexadecimal.
scalar Bytes32
# Address is a 20 byte Ethereum address, represented as 0x-prefixed hexadecimal.
scalar Address
# Bytes is an arbitrary length binary string, represented as 0x-prefixed hexadecimal.
# An empty byte string is represented as '0x'. Byte strings must have an even number of hexadecimal nybbles.
scalar Bytes
# BigInt is a large integer. Input is accepted as either a JSON number or as a string.
# Strings may be either decimal or 0x-prefixed hexadecimal. Output values are all
# 0x-prefixed hexadecimal.
scalar BigInt
# Long is a 64 bit unsigned integer.
scalar Long
schema {
query: Query
mutation: Mutation
}
# Account is an Ethereum account at a particular block.
type Account {
# Address is the address owning the account.
address: Address!
# Balance is the balance of the account, in wei.
balance: BigInt!
# TransactionCount is the number of transactions sent from this account,
# or in the case of a contract, the number of contracts created. Otherwise
# known as the nonce.
transactionCount: Long!
# Code contains the smart contract code for this account, if the account
# is a (non-self-destructed) contract.
code: Bytes!
# Storage provides access to the storage of a contract account, indexed
# by its 32 byte slot identifier.
storage(slot: Bytes32!): Bytes32!
}
# Log is an Ethereum event log.
type Log {
# Index is the index of this log in the block.
index: Int!
# Account is the account which generated this log - this will always
# be a contract account.
account(block: Long): Account!
# Topics is a list of 0-4 indexed topics for the log.
topics: [Bytes32!]!
# Data is unindexed data for this log.
data: Bytes!
# Transaction is the transaction that generated this log entry.
transaction: Transaction!
}
# Transaction is an Ethereum transaction.
type Transaction {
# Hash is the hash of this transaction.
hash: Bytes32!
# Nonce is the nonce of the account this transaction was generated with.
nonce: Long!
# Index is the index of this transaction in the parent block. This will
# Logs returns log entries matching the provided filter.
logs(filter: FilterCriteria!): [Log!]!
# GasPrice returns the node's estimate of a gas price sufficient to
# ensure a transaction is mined in a timely fashion.
gasPrice: BigInt!
# ProtocolVersion returns the current wire protocol version number.
protocolVersion: Int!
# Syncing returns information on the current synchronisation state.
syncing: SyncState
}
type Mutation {
# SendRawTransaction sends an RLP-encoded transaction to the network.
sendRawTransaction(data: Bytes!): Bytes32!
}
```
Nodes MAY offer a superset of this schema, by adding new fields or types. Experimental or client-specific fields MUST be prefixed with '_client_' (eg, '_geth_' or '_parity_'). Unprefixed fields MUST be specified in a new EIP that extends this one.
## Rationale
Ethereum nodes have been moving away from providing read-write functionality such as transaction and message signing, and from other services such as code compilation, in favor of a more 'unix-like' approach where each task is performed by a dedicated process. We have thus specified a core set of types and fields that reflects this trend, leaving out functionality that is presently, or intended to be, deprecated:
-`eth_compile*` calls are deprecated, and hence not provided here.
-`eth_accounts`, `eth_sign`, and `eth_sendTransaction` are considered by many to be deprecated, and are not provided here; callers should use local accounts or a separate signing daemon instead.
Further, two areas of the current API interface have been omitted for simplicity in this initial standard, with the intention that they will be defined in a later EIP:
- Filters will require use of GraphQL subscriptions, and require careful consideration around the desire for nodes without local per-caller state.
- Mining functionality is less-used and benefits less from reimplementation in GraphQL, and should be specified in a separate EIP.
## Backwards Compatibility
This schema implements the bulk of the current read-only functionality provided by the JSON-RPC node interface. Existing RPC calls can be mapped to GraphQL queries as follows:
| eth_getCompilers | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_compileLLL | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_compileSolidity | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_compileSerpent | NOT IMPLEMENTED | Compiler functionality is deprecated in JSON-RPC. |
| eth_newFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_newBlockFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_newPendingTransactionFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_uninstallFilter | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_getFilterChanges | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_getFilterLogs | NOT IMPLEMENTED | Filter functionality may be specified in a future EIP. |
| eth_accounts | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
| eth_sign | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
| eth_sendTransaction | NOT IMPLEMENTED | Accounts functionality is not part of the core node API. |
| eth_coinbase | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_getWork | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_hashRate | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_mining | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_submitHashrate | NOT IMPLEMENTED | Mining functionality to be defined separately. |
| eth_submitWork | NOT IMPLEMENTED | Mining functionality to be defined separately. |
For specific reasoning behind omitted functionality, see the Rationale section.
## Test Cases
TBD.
## Implementation
A go-ethereum implementation was completed in [PR 18445](https://github.com/ethereum/go-ethereum/pull/18445) and will be available in a forthcoming geth release.
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).