Skip to content

Commit 4a8100c

Browse files
authored
Contributor documentation (#291)
* wip * more wip * update contributor docs * add testing docs * few more updates * update main readme * fix spelling error * fix more spelling * fix line width for paragraph * rm extra new line * moar
1 parent 4accc7a commit 4a8100c

File tree

3 files changed

+231
-18
lines changed

3 files changed

+231
-18
lines changed

README.md

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
# Ethereum API Specification
1+
# Execution API Specification
22

33
## JSON-RPC
44

55
[View the spec][playground]
66

7-
The Ethereum JSON-RPC is a collection of methods that all clients implement.
7+
The Ethereum JSON-RPC is a standard collection of methods that all execution
8+
clients implement. It is the canonical interface between users and the network.
89
This interface allows downstream tooling and infrastructure to treat different
910
Ethereum clients as modules that can be swapped at will.
1011

12+
### Contributing
13+
14+
Please see the contributors guide in [`docs/making-changes.md`][making-changes]
15+
for general information about the process of standardizing new API methods and
16+
making changes to existing ones. Information on test generation can be found
17+
in [`tests/README.md`][test-gen]
18+
19+
The specification itself is written in [OpenRPC][openrpc]. Refer to the OpenRPC
20+
specification and the JSON schema [specification][json-schema] to get started.
21+
1122
### Building
1223

1324
The specification is split into multiple files to improve readability. The
@@ -22,35 +33,42 @@ Build successful.
2233
This will output the file `openrpc.json` in the root of the project. This file
2334
will have all schema `#ref`s resolved.
2435

25-
### Contributing
26-
27-
The specification is written in [OpenRPC][openrpc]. Refer to the
28-
OpenRPC specification and the JSON schema specification to get started.
29-
3036
#### Testing
3137

32-
There are currently three tools for testing contributions. The main two that
33-
run as GitHub actions are an [OpenRPC validator][validator] and a
34-
[spellchecker][spellchecker]:
38+
There are several mechanisms for testing specification contributions and client
39+
conformance.
40+
41+
First is the [OpenRPC validator][validator]. It performs some basic syntactic
42+
checks on the generated specification.
3543

3644
```console
3745
$ npm install
3846
$ npm run lint
3947
OpenRPC spec validated successfully.
48+
```
4049

41-
$ pip install pyspelling
42-
$ pyspelling -c spellcheck.yaml
43-
Spelling check passed :)
50+
Next is `speccheck`. This tool validates the test cases in the `tests`
51+
directory against the specification.
52+
53+
```console
54+
$ go install github.com/lightclient/rpctestgen/cmd/speccheck@latest
55+
$ speccheck -v
56+
all passing.
4457
```
4558

46-
The third tool can validate a live JSON-RPC provider hosted at
47-
`http://localhost:8545` against the specification:
59+
The spell checker ensures the specification is free of spelling errors.
4860

4961
```console
50-
$ ./scripts/debug.sh eth_getBlockByNumber \"0xc7d772\",false
51-
data.json valid
62+
$ pip install pyspelling
63+
$ pyspelling -c spellcheck.yaml
64+
Spelling check passed :)
5265
```
5366

67+
Finally, the test cases in the `tests/` directory may be run against individual
68+
execution client using the [`hive`] simulator [`rpc-compat`][rpc-compat].
69+
Please see the documentation in the aforementioned repositories for more
70+
information.
71+
5472
## GraphQL
5573

5674
[View the spec][graphql-schema]
@@ -81,6 +99,10 @@ This repository is licensed under [CC0](LICENSE).
8199
[playground]: https://ethereum.github.io/execution-apis/api-documentation/
82100
[openrpc]: https://open-rpc.org
83101
[validator]: https://open-rpc.github.io/schema-utils-js/globals.html#validateopenrpcdocument
84-
[spellchecker]: https://facelessuser.github.io/pyspelling/
85102
[graphql-schema]: http://graphql-schema.ethdevops.io/?url=https://raw.githubusercontent.com/ethereum/execution-apis/main/graphql.json
86103
[eip-1767]: https://eips.ethereum.org/EIPS/eip-1767
104+
[making-changes]: docs/making-changes.md
105+
[json-schema]: https://json-schema.org
106+
[hive]: https://github.com/ethereum/hive
107+
[rpc-compat]: https://github.com/ethereum/hive/tree/master/simulators/ethereum/rpc-compat
108+
[test-gen]: tests/README.md

docs/making-changes.md

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
# Contributors Guide
2+
3+
This guide will explain for new and experienced contributors alike how to
4+
propose changes to Ethereum JSON-RPC API.
5+
6+
## Introduction
7+
8+
The Ethereum JSON-RPC API is the canonical interface between users and the
9+
Ethereum network. Each execution layer client implements the API as defined by
10+
the spec.
11+
12+
As the main source of chain information, anything that is not provided over via
13+
API will not be easily accessible to users.
14+
15+
## Guiding Principles
16+
17+
When considering a change to the API, it's important to keep a few guiding
18+
principles in mind.
19+
20+
### Necessity
21+
22+
The most common path to a newly standardized method is necessity. As the
23+
protocol changes over time, new types of data become available. EIP-2930
24+
necessitated the introduction of `eth_accessList` and EIP-1559 neccesitated
25+
`eth_feeHistory`.
26+
27+
Therefore, a good question to ask before making a new API proposal is whether
28+
or not the method is strictly neccessary. Sometimes the answer is yes even
29+
without a protocol change. For example, `eth_getProof` has been possible since
30+
the inital version of Ethereum -- yet, it was only standardized in recent years
31+
as demand for the functionality grew. Before `eth_getProof`, there was no
32+
interface for getting intermediary trie nodes over the API. This is a great
33+
example of a method that became more neccessary over time.
34+
35+
Sometimes efficiency is the basis of necessity. If certain patterns of requests
36+
becomes popular, it can be adventageous to enshrine the behavior into the API.
37+
38+
### Implementation Complexity
39+
40+
How a method is implemented should be carefully considered before proposing a
41+
change to the API. Although each client is able to validate the Ethereum chain,
42+
there can be a huge variance in actual design decisions.
43+
44+
As an example, a proposal for a method such as `eth_totalSupply` seems
45+
reasonable. This is a quanity that users are often interested in and it would
46+
nice to have it available. However, tracking the total supply is tricky. There
47+
are several avenues where ether can enter and leave supply. This method would
48+
need to either i) compute the value on demand or ii) store value for each block
49+
height.
50+
51+
Option i) is out, because it would involve executing each block starting with
52+
genesis. Option ii) is viable, but it starts enforcing certain requirements on
53+
clients beyond being able to simply validate the chain. Now during block
54+
ingestion, each client needs to store in their database the supply for that
55+
height. The chain reorg logic also needs to consider this new data. It is not
56+
trivial.
57+
58+
### Backwards Compatibility
59+
60+
There is currently no accepted path to making backwards incompatible changes to
61+
the API. This means that proposals which change syntax or semantics of existing
62+
methods are unlikely to be accepted. A more viable approach is to propose a new
63+
method be created.
64+
65+
## Standardization
66+
67+
There is not a formal process for standardization of API changes. However, the
68+
outline below should given proposal authors and champions a rough process to
69+
follow.
70+
71+
### Idea
72+
73+
An often overlooked aspect on the standardization journey is the idea phase.
74+
This is an important period of time, because some focused effort at this point
75+
in time can save time and make the rest of the process much smoother.
76+
77+
During the idea phase, it is recommended to contemplate the proposal idea in
78+
the context of the guiding principles above. It's also good to get feedback on
79+
the idea in the open. Just one or two rough acknowledgements from client
80+
developers that an idea makes sense and is worth pursing can avoid wasting a
81+
lot of time formalizing a proposal that has little change of being accepted.
82+
83+
### Proposal
84+
85+
The formal proposal stage is where the bulk of time will be spent. A formal
86+
proposal is a PR to this repository ([ethereum/execution-apis][exec-apis]). A
87+
good proposal will have the following:
88+
89+
* a modification to the specification implementing the proposal
90+
* test cases for proposal ([guide][test-gen])
91+
* motivation for the change
92+
* links to acknowledgements that proposal idea is sound
93+
* clear rationale for non-obvious design decisions
94+
95+
### Acquiring Support
96+
97+
Once a formal proposal has been created, formal support of clients can be
98+
acquired. This has historically been done via the AllCoreDevs call. It is
99+
recommended to post a request on the AllCoreDevs agenda (usually in
100+
[ethereum/pm][pm]) to discuss the proposal, at which point formal support can
101+
be ascertained.
102+
103+
Often times, support will be conditional certain changes. This means that
104+
proposals will cycle between formal proposal work and earning support from
105+
clients. This should be expected and not discourage authors.
106+
107+
### Accepting the Change
108+
109+
After client teams acknowledge and accept the change, it is usually on them to
110+
implement the method in their client. Due to the lack of versioning of the API,
111+
it is preferable that clients release the method roughly at the same time so
112+
that there is not much time where some clients support a certain methods and
113+
others don't.
114+
115+
116+
[exec-apis]: https://github.com/ethereum/execution-apis
117+
[pm]: https://github.com/ethereum/pm
118+
[test-gen]: ../tests/README.md

tests/README.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Tests
2+
3+
The Execution API has a comprehensive test suite to verify conformance of
4+
clients. The tests in this repository are loaded into the [`hive`][hive] test
5+
simulator [`rpc-compat`][rpc-compat] and validated against every major client.
6+
7+
The test suite is run daily and results are always available [here][hivetests2]
8+
under the tag `rpc-compat`.
9+
10+
To learn more about the `rpc-compat` simulator, please see its
11+
[documentation][rpc-compat].
12+
13+
## Format
14+
15+
Tests are written to describe the round-trip of a single request-response
16+
cycle. A test starts with a `>> ` denoting the request portion. It is delimited
17+
by `\n` and then a `<< ` is used to denote the response. All together, it looks
18+
something like this:
19+
20+
```javascript
21+
>> {"jsonrpc":"2.0","id":1,"method":"eth_blockNumber"}
22+
<< {"jsonrpc":"2.0","id":1,"result":"0x3"}
23+
```
24+
25+
For organizational purposes, tests are stored at a path following the template
26+
`tests/{method-name}/{test-name}.io`. The path does not affect the validity of
27+
the test and is only used to describe what the test is aiming to test.
28+
29+
## Generation
30+
31+
Test generation can be broken down into two parts. First is the generation of a
32+
chain against which tests will be executed. Second is executing the actual
33+
tests and recording their round-trip.
34+
35+
Although the `io` format is agnostic to the generation tool, it is preferred
36+
test contributors use the generation tool [`rpctestgen`][rpctestgen].
37+
`rpctestgen` takes care of both pieces of test generation.
38+
39+
### Chain making
40+
41+
Inside the `tests` directory are three chain-related files that test authors
42+
must be aware of.
43+
44+
`genesis.json` - a standard genesis config file in the go-ethereum format.
45+
`chain.rlp` - a newline-delimited list of blocks making up the test chain.
46+
`bad.rlp` - a newline-delimited list of blocks that are sealed and
47+
conduct an invalid transition.
48+
49+
Generally, test authors should ingest `genesis.json` and `chain.rlp` and
50+
generate tests against the head of that chain. If a test requires a certain
51+
condition exist in the chain that does not currently exist, then the author may
52+
append a block to head of the chain and regenerate all tests against the new
53+
`chain.rlp`.
54+
55+
### Test Generation
56+
57+
Once a test chain has been created, test authors may move on to generating the
58+
actual test fixtures. To do so, authors must follow the format defined above.
59+
Tests should be limited to a single round-trip interaction. At this time, this
60+
precludes subscription methods from being tested.
61+
62+
It is also recommended that test authors test their tests. Each interaction
63+
should be validated against the expected values. Due to the number of fixtures
64+
generated, it is easy accept incorrect responses.
65+
66+
A good final verification of tests is to run them in the hive simulator
67+
[`rpc-compat`][rpc-compat]. More information on how to run custom tests in the
68+
simulator can be found with there.
69+
70+
[hive]: https://github.com/ethereum/hive
71+
[hivetests2]: https://hivetests2.ethdevops.io
72+
[rpc-compat]: https://github.com/ethereum/hive/tree/master/simulators/ethereum/rpc-compat
73+
[rpctestgen]: https://github.com/lightclient/rpctestgen

0 commit comments

Comments
 (0)