Skip to content

Commit 96bd622

Browse files
lightclientterencechain
authored andcommitted
Simplify spec, update based on recent discussions (flashbots#82)
* simplify spec, update based on recent discussions * should be BeaconBlockHeader not BeaconBlock * add setFeeRecipient and spec out the signing operations * fix spacing * switch back to using BeaconBlock, tidying up * add public key to methods to verify BLS signatures * note that builder should respond to get payload requests immediately * add timestamp to fee recipient announcement * do some renaming, add a diagram, add in definiton for blind beacon block * fix malformed link * address review feedback Author: lightclient <[email protected]> Co-authored-by: terence tsao <[email protected]> Co-authored-by: terence tsao <[email protected]>
1 parent ad71c51 commit 96bd622

File tree

1 file changed

+153
-99
lines changed

1 file changed

+153
-99
lines changed

docs/specification.md

Lines changed: 153 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,207 @@
1-
# Version 0.1 (current, milestone 1, running on [Kiln testnet](https://kiln.themerge.dev/))
1+
# Version 0.2
22

3-
This initial milestone provides simple sidecar logic with minimal consensus client changes, simple networking, no validator authentication, and manual safety mechanism.
4-
5-
1. _mev-boost_ is initialized with a list of `RelayURI`s from trusted relays.
6-
7-
2. _mev-boost_ receives a [`engine_forkchoiceUpdatedV1`](#engine_forkchoiceupdatedv1) call from a beacon node and forwards it to all connected relays to communicate `feeRecipient`.
8-
9-
3. _mev_boost_ receives [`builder_getPayloadHeaderV1`](#builder_getpayloadheaderv1) request from the beacon node, and forwards it to all relays as `relay_getPayloadHeaderV1`. _mev-boost_ must return the [`ExecutionPayloadHeaderV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayloadheader) with the highest associated `feeRecipientDiff`.
10-
11-
4. The _beacon node_ must use the [`ExecutionPayloadHeaderV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/merge/beacon-chain.md#executionpayloadheader) received to assemble and sign a [`SignedBlindedBeaconBlock`](#signedblindedbeaconblock) and return it to _mev-boost_ using [`builder_proposeBlindedBlockV1`](#builder_proposeblindedblockv1).
12-
13-
5. _mev-boost_ must forward the [`SignedBlindedBeaconBlock`](#signedblindedbeaconblock) to all connected relays and attach the matching [`SignedMEVPayloadHeader`](#signedmevpayloadheader) using [`relay_proposeBlindedBlockV1`](#relay_proposeblindedblockv1) to inform the network of which relay created this payload.
14-
15-
6. If an [`ExecutionPayloadV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.6/specs/merge/beacon-chain.md#executionpayload) is returned, _mev-boost_ must verify that the root of the transaction list matches the expected transaction root from the [`SignedBlindedBeaconBlock`](#signedblindedbeaconblock) before returning it to the _beacon node_.
3+
This document specifies the Builder API methods that the Consensus Layer uses to interact with external block builders.
164

175
```mermaid
186
sequenceDiagram
7+
participant consensus
8+
participant mev_boost
9+
participant relays
1910
Title: Block Proposal
20-
consensus-->+mev_boost: engine_forkchoiceUpdatedV1
21-
mev_boost->>-relays: engine_forkchoiceUpdatedV1
11+
Note over consensus: sign fee recipient announcement
12+
consensus->>mev_boost: builder_setFeeRecipient
13+
mev_boost->>relays: builder_setFeeRecipient
2214
Note over consensus: wait for allocated slot
23-
consensus->>+mev_boost: builder_getPayloadHeaderV1
24-
mev_boost->>relays: relay_getPayloadHeaderV1
25-
Note over mev_boost: select most valuable payload
26-
mev_boost-->>-consensus: builder_getPayloadHeaderV1 response
15+
consensus->>mev_boost: builder_getHeader
16+
mev_boost->>relays: builder_getHeader
17+
relays-->>mev_boost: builder_getHeader response
18+
Note over mev_boost: verify response matches expected
19+
Note over mev_boost: select best payload
20+
mev_boost-->>consensus: builder_getHeader response
2721
Note over consensus: sign the block
28-
consensus->>+mev_boost: builder_proposeBlindedBlockV1
22+
consensus->>mev_boost: builder_getPayload
2923
Note over mev_boost: identify payload source
30-
mev_boost->>relays: relay_proposeBlindedBlockV1
24+
mev_boost->>relays: builder_getPayload
3125
Note over relays: validate signature
32-
relays-->>mev_boost: relay_proposeBlindedBlockV1 response
33-
mev_boost-->>-consensus: builder_proposeBlindedBlockV1 response
26+
relays-->>mev_boost: builder_getPayload response
27+
Note over mev_boost: verify response matches expected
28+
mev_boost-->>consensus: builder_getPayload response
3429
```
3530

36-
## Required client modifications
31+
## Structures
3732

38-
- consensus client must implement [blind transaction signing](https://hackmd.io/@paulhauner/H1XifIQ_t#Change-1-Blind-Transaction-Signing)
33+
### `ExecutionPayloadV1`
3934

40-
## API
35+
Mirror of [`ExecutionPayloadV1`][execution-payload].
4136

42-
Methods are prefixed using the following convention:
37+
### `ExecutionPayloadHeaderV1`
4338

44-
- `engine` prefix indicates calls made to the execution client. These methods are specified in the [execution engine APIs](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.8/src/engine/specification.md).
45-
- `builder` prefix indicates calls made to the mev-boost sidecar.
46-
- `relay` prefix indicates calls made to a relay.
39+
Equivalent to `ExecutionPayloadV1`, except `transactions` is replaced with `transactionsRoot`.
40+
- `parentHash`: `DATA`, 32 Bytes
41+
- `feeRecipient`: `DATA`, 20 Bytes
42+
- `stateRoot`: `DATA`, 32 Bytes
43+
- `receiptsRoot`: `DATA`, 32 Bytes
44+
- `logsBloom`: `DATA`, 256 Bytes
45+
- `prevRandao`: `DATA`, 32 Bytes
46+
- `blockNumber`: `QUANTITY`, 64 Bits
47+
- `gasLimit`: `QUANTITY`, 64 Bits
48+
- `gasUsed`: `QUANTITY`, 64 Bits
49+
- `timestamp`: `QUANTITY`, 64 Bits
50+
- `extraData`: `DATA`, 0 to 32 Bytes
51+
- `baseFeePerGas`: `QUANTITY`, 256 Bits
52+
- `blockHash`: `DATA`, 32 Bytes
53+
- `transactionsRoot`: `DATA`, 32 Bytes
4754

48-
### engine_forkchoiceUpdatedV1
55+
#### SSZ Objects
4956

50-
See [engine_forkchoiceUpdatedV1](https://github.com/ethereum/execution-apis/blob/v1.0.0-alpha.8/src/engine/specification.md#engine_forkchoiceupdatedv1).
57+
Consider the following definitions supplementary to the definitions in [`consensus-specs`][consensus-specs].
5158

52-
### builder_proposeBlindedBlockV1
59+
##### `builder_setFeeRecipientV1` Request
5360

54-
#### Request
61+
```python
62+
class Request(Container):
63+
feeRecipient: Bytes20
64+
timestamp: uint64
65+
```
5566

56-
- method: `builder_proposeBlindedBlockV1`
57-
- params:
58-
1. [`SignedBlindedBeaconBlock`](#signedblindedbeaconblock)
67+
##### `builder_getPayloadV1` Response
5968

60-
#### Response
69+
```python
70+
class Response(Container):
71+
payload: ExecutionPayloadHeader
72+
value: uint256
73+
```
6174

62-
- result: [`ExecutionPayloadV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayload).
63-
- error: code and message set in case an exception happens while proposing the payload.
75+
##### `builder_getPayloadV1` Request
6476

65-
Technically, this call only needs to return the `transactions` field of [`ExecutionPayloadV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayload), but we return the full payload for simplicity.
77+
###### `BlindBeaconBlock`
6678

67-
### builder_getPayloadHeaderV1
79+
```python
80+
class BlindBeaconBlock(Container):
81+
slot: Slot
82+
proposer_index: ValidatorIndex
83+
parent_root: Root
84+
state_root: Root
85+
body: BlindBeaconBlockBody
86+
```
6887

69-
#### Request
88+
###### `BlindBeaconBlockBody`
89+
90+
```python
91+
class BlindBeaconBlockBody(Container):
92+
randao_reveal: BLSSignature
93+
eth1_data: Eth1Data
94+
graffiti: Bytes32
95+
proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
96+
attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS]
97+
attestations: List[Attestation, MAX_ATTESTATIONS]
98+
deposits: List[Deposit, MAX_DEPOSITS]
99+
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
100+
sync_aggregate: SyncAggregate
101+
execution_payload: ExecutionPayloadHeader
102+
```
70103

71-
- method: `builder_getPayloadHeaderV1`
72-
- params:
73-
1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process
104+
## Errors
74105

75-
#### Response
106+
The list of error codes introduced by this specification can be found below.
76107

77-
- result: [`ExecutionPayloadHeaderV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayloadheader)
78-
- error: code and message set in case an exception happens while getting the payload.
108+
| Code | Message | Meaning |
109+
| - | - | - |
110+
| -32000 | Server error | Generic client error while processing request. |
111+
| -32001 | Unknown hash | No block with the provided hash is known. |
112+
| -32002 | Unknown validator | No known mapping between validator and feeRecipient. |
113+
| -32003 | Invalid SSZ | Unable to decode SSZ. |
114+
| -32004 | Unknown block | Block does not match the provided header. |
115+
| -32005 | Invalid signature | Provided signature is invalid. |
116+
| -32006 | Invalid timestamp | Provided timestamp was invalid. |
117+
| -32600 | Invalid request | The JSON sent is not a valid Request object. |
118+
| -32601 | Method not found | The method does not exist / is not available. |
119+
| -32602 | Invalid params | Invalid method parameter(s). |
120+
| -32603 | Internal error | Internal JSON-RPC error. |
121+
| -32700 | Parse error | Invalid JSON was received by the server. |
79122

80-
### relay_getPayloadHeaderV1
123+
## Routines
81124

82-
#### Request
125+
### Signing
83126

84-
- method: `relay_getPayloadHeaderV1`
85-
- params:
86-
1. `payloadId`: `DATA`, 8 Bytes - Identifier of the payload build process
127+
All signature operations should follow the [standard BLS operations][bls] interface defined in `consensus-specs`.
87128

88-
#### Response
129+
There are two types of data to sign over in the Builder API:
130+
* In-protocol messages, e.g. [`BlindBeaconBlock`](#blindbeaconblock), which should compute the signing root using [`computer_signing_root`][compute-signing-root] and use the domain specified for beacon block proposals.
131+
* Builder API messages, e.g. [`builder_setFeeRecipientV1`](#builder_setFeeRecipientV1) and the response to [`builder_getHeader`](#response-2), which should compute the signing root using [`compute_signing_root`][compute-signing-root] and the domain `DomainType('0xXXXXXXXX')` (TODO: get a proper domain).
89132

90-
- result: [`SignedMEVPayloadHeader`](#signedmevpayloadheader)
91-
- error: code and message set in case an exception happens while getting the payload.
133+
As `compute_signing_root` takes `SSZObject` as input, client software should convert in-protocol messages to their SSZ representation to compute the signing root and Builder API messages to the SSZ representations defined [above](#sszobjects).
134+
135+
## Methods
92136

93-
### relay_proposeBlindedBlockV1
137+
### `builder_setFeeRecipientV1`
94138

95139
#### Request
96140

97-
- method: `relay_proposeBlindedBlockV1`
141+
- method: `builder_setFeeRecipientV1`
98142
- params:
99-
1. [`SignedBlindedBeaconBlock`](#signedblindedbeaconblock)
100-
2. [`SignedMEVPayloadHeader`](#signedmevpayloadheader)
143+
1. `feeRecipient`: `DATA`, 20 Bytes - Address of account which should receive fees.
144+
2. `timestamp`: `QUANTITY`, uint64 - Unix timestamp of announcement.
145+
2. `publicKey`: `DATA`, 48 Bytes - Public key of validator.
146+
3. `signature`: `DATA`, 96 Bytes - Signature over `feeRecipient` and `timestamp`.
101147

102148
#### Response
103149

104-
- result: [`ExecutionPayloadV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayload)
105-
- error: code and message set in case an exception happens while proposing the payload.
106-
107-
Technically, this call only needs to return the `transactions` field of [`ExecutionPayloadV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayload), but we return the full payload for simplicity.
108-
109-
### Types
110-
111-
#### SignedMEVPayloadHeader
150+
- result: `null`
151+
- error: code and message set in case an exception happens while getting the payload.
112152

113-
See [here](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/beacon-chain.md#custom-types) for the definition of fields like `BLSSignature`
153+
#### Specification
154+
1. Builder software **MUST** verify `signature` is valid under `publicKey`.
155+
2. Builder software **MUST** respond to requests where `timestamp` is before the latest announcement from the validator or more than +/- 10 seconds from the current time with `-32006: Invalid timestamp`.
156+
3. Builder software **MUST** store `feeRecipient` in a map keyed by `publicKey`.
114157

115-
- message: [MEVPayloadHeader](#mevpayloadheader)
116-
- signature: BLSSignature
158+
### `builder_getHeaderV1`
117159

118-
#### MEVPayloadHeader
160+
#### Request
119161

120-
- payloadHeader: [`ExecutionPayloadHeaderV1`](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayloadheader)
121-
- feeRecipientDiff: Quantity, 256 Bits - the change in balance of the feeRecipient address
162+
- method: `builder_getHeaderV1`
163+
- params:
164+
1. `hash`: `DATA`, 32 Bytes - Hash of block which the validator intends to use as the parent for its proposal.
122165

123-
#### SignedBlindedBeaconBlock
166+
#### Response
124167

125-
See [here](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/beacon-chain.md#custom-types) for the definition of fields like `BLSSignature`
168+
- result: `object`
169+
- `header`: [`ExecutionPayloadHeaderV1`](#executionpayloadheaderv1).
170+
- `value`: `DATA`, 32 Bytes - the change in wei balance of the `feeRecipient` account.
171+
- `publicKey`: `DATA`, 48 Bytes - the public key associated with the builder.
172+
- `signature`: `DATA`, 96 Bytes - BLS signature of the builder over `payload` and `value`.
173+
- error: code and message set in case an exception happens while getting the payload.
126174

127-
- message: [BlindedBeaconBlock](#blindedbeaconblock)
128-
- signature: BLSSignature
175+
#### Specification
176+
1. Builder software **SHOULD** respond immediately with the `header` that increases the `feeRecipient`'s balance by the most.
177+
2. Builder software **MUST** return `-32001: Unknown hash` if the block identified by `hash` does not exist.
178+
3. Builder software **MUST** return `-32002: Unknown validator` if the validator the builder expects to propose in the current slot has not been mapped to a `feeRecipient`.
129179

130-
#### BlindedBeaconBlock
180+
### `builder_getPayloadV1`
131181

132-
This is forked from [here](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/phase0/beacon-chain.md#beaconblock) with `body` replaced with `BlindedBeaconBlockBody`
182+
#### Request
133183

134-
- slot: Slot
135-
- proposer_index: ValidatorIndex
136-
- parent_root: Root
137-
- state_root: Root
138-
- body: BlindedBeaconBlockBody
184+
- method: `builder_getPayloadV1`
185+
- params:
186+
1. `block`: `DATA`, arbitray length - SSZ encoded [`BlindBeaconBlock`](#blindbeaconblock).
187+
2. `signature`: `DATA`, 96 Bytes - BLS signature of the validator over `block`.
139188

140-
#### BlindedBeaconBlockBody
189+
#### Response
141190

142-
This is forked from [here](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/merge/beacon-chain.md#beaconblockbody) with `execution_payload` replaced with [execution_payload_header](https://github.com/ethereum/consensus-specs/blob/v1.1.10/specs/bellatrix/beacon-chain.md#executionpayloadheader)
191+
- result: [`ExecutionPayloadV1`](#executionpayloadv1).
192+
- error: code and message set in case an exception happens while proposing the payload.
143193

144-
- randao_reveal: BLSSignature
145-
- eth1_data: Eth1Data
146-
- graffiti: Bytes32
147-
- proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
148-
- attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS]
149-
- attestations: List[Attestation, MAX_ATTESTATIONS]
150-
- deposits: List[Deposit, MAX_DEPOSITS]
151-
- voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
152-
- sync_aggregate: SyncAggregate
153-
- execution_payload_header: ExecutionPayloadHeader
194+
#### Specification
195+
1. Builder software **MUST** verify that `block` is an SSZ encoded [`BlindBeaconBlock`](#blindbeaconblock). If the block is encoded incorrectly, the builder **MUST** return `-32003: Invalid SSZ`. If the block is encoded correctly, but does not match the `ExecutionPayloadHeaderV1` provided in `builder_getExecutionPayloadHeaderV1`, the builder **SHOULD** return `-32004: Unknown block`. If the CL modifies the payload in such a way that it is still valid and the builder is able to unblind it, the builder **MAY** update the payload on it's end to reflect the CL's changes before returning it.
196+
2. Builder software **MUST** verify that `signature` is a BLS signature over `block`, verifiable using [`verify_block_signature`][verify-block-signature] and the validator public key that is expected to propose in the given slot. If the signature is determined to be invalid or from a different validator than expected, the builder **MUST** return `-32005: Invalid signature`.
197+
198+
[consensus-specs]: https://github.com/ethereum/consensus-specs
199+
[bls]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#bls-signatures
200+
[compute-signing-root]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#compute_signing_root
201+
[bytes20]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#aliases
202+
[uint256]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#basic-types
203+
[execution-payload-header]: https://github.com/ethereum/consensus-specs/blob/dev/specs/bellatrix/beacon-chain.md#executionpayloadheader
204+
[execution-payload]: https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md#executionpayloadv1
205+
[hash-tree-root]: https://github.com/ethereum/consensus-specs/blob/dev/ssz/simple-serialize.md#merkleization
206+
[beacon-block]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beaconblock
207+
[verify-block-signature]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#beacon-chain-state-transition-function

0 commit comments

Comments
 (0)