diff --git a/.github/workflows/spellcheck.yaml b/.github/workflows/spellcheck.yaml new file mode 100644 index 0000000..79fde0c --- /dev/null +++ b/.github/workflows/spellcheck.yaml @@ -0,0 +1,11 @@ +name: Spellcheck +on: [push, pull_request, workflow_dispatch] + +jobs: + build: + name: Spellcheck + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@master + - uses: rojopolis/spellcheck-github-actions@0.16.0 + name: Spellcheck diff --git a/README.md b/README.md index cc03461..ad08b05 100644 --- a/README.md +++ b/README.md @@ -1,51 +1,99 @@ -# Ethereum Builder Specification +# Ethereum Builder API Specification -![CI](https://github.com/ethereum/builder-specs/workflows/CI/badge.svg) +![CI][ci] -Collection of RESTful APIs provided by external builder nodes. +The Builder API is an interface for consensus layer clients to source blocks +built by external entities. -## Render +In this repository: +* [API specification][oas-spec] +* [Additional definitions][spec] -To render spec in browser you will need any http server to load `index.html` file -in root of the repo. +### Why? -##### Python +Block building is a specialized activity that requires high fixed costs to be +an efficient validator. This creates an advantage for staking pools as they can +effectively distribute the cost across many validators. -``` -python -m http.server 8080 -``` -And api spec will render on [http://localhost:8080](http://localhost:8080). +[Proposer-builder separation][pbs] (PBS) fixes this by spliting the roles of a +validator into block proposing and block building. However, PBS requires +modifications to the Beacon chain and will therefore not be possible at the +time of the merge. -### Usage +The Builder API is a temporary solution that requires higher trust assumptions +than PBS, but can be fully implemented without modification to the base +protocol. This is done by providing the proposer with a "blind" execution layer +header to incorporate into a block and a "value" amount which will be +transferred to the proposer once they create a block with the aforementioned +header. Once the proposer signs a block with the header, they are bound to the +choice (or risk being slashed due to equivocation). That allows the builder to +reveal the blinded transactions without the possibility of the proposer +tampering with them. + +This design is based on the original proposal for trusted external builders: +["MEV-Boost: Merge ready Flashbots Architecture"](mev-boost-ethr). -Local changes will be observable if "dev" is selected in the "Select a definition" drop-down in the web UI. +#### Builder software -Users may need to tick the "Disable Cache" box in their browser's developer tools to see changes after modifying the source. +Users will typically connect their CL clients to builders with builder +multiplexers. Please see their respective repositories for more information: + +* [`mev-boost`][mev-boost] +* [`mev-boost-rs`][mev-boost-rs] ## Contributing -API spec is checked for lint errors before merge. +The API specification is checked for lint errors before merging pull requests. -To run lint locally, install linter with -``` +To run the linter locally, install it with: +```console npm install -g @stoplight/spectral-cli@6.2.1 ``` -and run lint with -``` +and then run it: +```console spectral lint builder-oapi.yaml ``` +### Render API Specification + +To render spec in browser, you will simply need an HTTP server to load the +`index.html` file in root of the repo. + +For example: +```console +python -m http.server 8080 +``` + +The spec will render at [http://localhost:8080](http://localhost:8080). + +### Usage + +Local changes will be observable if "dev" is selected in the "Select a +definition" drop-down in the web UI. + +It may be necessary to tick the "Disable Cache" box in their browser's +developer tools to see changes after modifying the source. + ## Releasing 1. Create and push tag + - Make sure `info.version` in `builder-oapi.yaml` file is updated before + tagging. + - CI will create a github release and upload bundled spec file +2. Add release entrypoint in `index.html` - - Make sure info.version in builder-oapi.yaml file is updated before tagging. - - CD will create github release and upload bundled spec file +In `SwaggerUIBundle` configuration (inside `index.html` file), add another +entry in `urls` field. Entry should be in following format (replace `` +with real tag name from step 1.): -2. Add release entrypoint in index.html - -In SwaggerUIBundle configuration (inside index.html file), add another entry in "urls" field (SwaggerUI will load first item as default). -Entry should be in following format(replace `` with real tag name from step 1.): ```javascript - {url: "https://github.com/ethereum/builder-apis/releases/download//builder-oapi.yaml", name: ""}, +{url: "https://github.com/ethereum/builder-apis/releases/download//builder-oapi.yaml", name: ""}, ``` + +[ci]: https://github.com/ethereum/builder-specs/workflows/CI/badge.svg +[oas-spec]: https://ethereum.github.io/builder-specs/ +[spec]: specs/README.md +[pbs]: https://ethresear.ch/t/proposer-block-builder-separation-friendly-fee-market-designs/9725 +[mev-boost-ethr]: https://ethresear.ch/t/mev-boost-merge-ready-flashbots-architecture/11177 +[mev-boost]: https://github.com/flashbots/mev-boost +[mev-boost-rs]: https://github.com/ralexstokes/mev-boost-rs diff --git a/apis/builder/blinded_blocks.yaml b/apis/builder/blinded_blocks.yaml new file mode 100644 index 0000000..affa7ad --- /dev/null +++ b/apis/builder/blinded_blocks.yaml @@ -0,0 +1,56 @@ +post: + operationId: "submitBlindedBlock" + summary: Submit a signed blinded block and get unblinded execution payload. + description: | + Submits a `SignedBlindedBeaconBlock` to the builder, binding the proposer + to the block. The builder is now able to unblind the transactions in + `ExecutionPayloadHeader` without the possibility of the validator modifying + them. + + If the builder is not able to unblind the corresponding + `ExecutionPayloadHeader`, it must error. + tags: + - Builder + requestBody: + description: A `SignedBlindedBeaconBlock`. + required: true + content: + application/json: + schema: + oneOf: + - $ref: "../../builder-oapi.yaml#/components/schemas/Bellatrix.SignedBlindedBeaconBlock" + examples: + bellatrix: + $ref: "../../builder-oapi.yaml#/components/examples/Bellatrix.SignedBlindedBeaconBlock" + + responses: + "200": + description: Success response. + content: + application/json: + schema: + title: SubmitBlindedBlockResponse + type: object + properties: + version: + type: string + enum: [ bellatrix ] + example: "bellatrix" + data: + oneOf: + - $ref: "../../builder-oapi.yaml#/components/schemas/Bellatrix.ExecutionPayload" + examples: + bellatrix: + $ref: "../../builder-oapi.yaml#/components/examples/Bellatrix.ExecutionPayload" + "400": + description: Error response. + content: + application/json: + schema: + allOf: + - $ref: "../../builder-oapi.yaml#/components/schemas/ErrorMessage" + - example: + code: 400 + message: "Invalid block: missing signature" + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/apis/builder/header.yaml b/apis/builder/header.yaml new file mode 100644 index 0000000..3e06bc6 --- /dev/null +++ b/apis/builder/header.yaml @@ -0,0 +1,73 @@ +get: + operationId: "getHeader" + summary: Get an execution payload header. + description: | + Requests a builder node to produce a valid execution payload header, which + can be integrated into a blinded beacon block and signed. + + Builder must immediately return the header that is able to pay the + proposer's registered `fee_recipient` the most. If the builder is unaware + of `parent_hash`, it must error. If `pubkey` does not match the builder's + expected proposer `pubkey` for `slot`, it must error. If the builder has + not received a validator registration associated with `pubkey`, it must + error. + + When possible, the builder must return a header with `gas_limit` equal to + proposer's registered value. If this isn't possible due to the large + difference between `parent.gas_limit` and the preferred `gas_limit`, the + builder must return a header that moves `gas_limit` the maximum amount + allowed under the rules of consensus (currently `parent.gas_limit +/- + parent.gas_limit / 1024`). + tags: + - Builder + parameters: + - name: slot + in: path + required: true + description: The slot for which the block should be proposed. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Uint64" + - name: parent_hash + in: path + required: true + description: Hash of execution layer block the proposer will build on. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Root" + - name: pubkey + in: path + required: true + description: The validator's BLS public key. + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/Pubkey" + responses: + "200": + description: Success response. + content: + application/json: + schema: + title: GetHeaderResponse + type: object + properties: + version: + type: string + enum: [ bellatrix ] + example: "bellatrix" + data: + oneOf: + - $ref: "../../builder-oapi.yaml#/components/schemas/Bellatrix.SignedBuilderBid" + examples: + bellatrix: + $ref: "../../builder-oapi.yaml#/components/examples/Bellatrix.SignedBuilderBid" + "400": + description: Error response. + content: + application/json: + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/ErrorMessage" + examples: + InvalidRequest: + value: + code: 400 + message: "Unknown hash: missing parent hash" + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/apis/builder/status.yaml b/apis/builder/status.yaml new file mode 100644 index 0000000..948888f --- /dev/null +++ b/apis/builder/status.yaml @@ -0,0 +1,11 @@ +get: + operationId: "status" + summary: Check if builder is healthy. + description: Checks if builder can respond to requests normally. + tags: + - Builder + responses: + "200": + description: Success response. + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/apis/builder/validators.yaml b/apis/builder/validators.yaml new file mode 100644 index 0000000..afe852d --- /dev/null +++ b/apis/builder/validators.yaml @@ -0,0 +1,36 @@ +post: + operationId: "registerValidator" + summary: Register or update a validator's block building preferences. + description: | + Registers a validator's preferred fee recipient and gas limit. + + Builders should verify that `pubkey` corresponds to an active or pending + validator, and that `signature` is valid under `pubkey`. Otherwise, builder + must error. Requests with `timestamp` less than or equal to the previous + successful announcement must error. Requests with `timestamp` more than 10 + seconds in the future must error. + tags: + - Builder + requestBody: + description: | + A signed declaration of a validator's block building preferences. + required: true + content: + application/json: + schema: + $ref: "../../builder-oapi.yaml#/components/schemas/SignedValidatorRegistration" + responses: + "200": + description: Success response. + "400": + description: Error response. + content: + application/json: + schema: + allOf: + - $ref: "../../builder-oapi.yaml#/components/schemas/ErrorMessage" + - example: + code: 400 + message: "unknown validator" + "500": + $ref: "../../builder-oapi.yaml#/components/responses/InternalError" diff --git a/builder-oapi.yaml b/builder-oapi.yaml new file mode 100644 index 0000000..822778b --- /dev/null +++ b/builder-oapi.yaml @@ -0,0 +1,85 @@ +openapi: "3.0.3" + +info: + title: Builder API + description: | + API specification for external builder nodes. This interface enables + validators to delegate block building duties such that attribution can be + had in the case of most faults (e.g. producing an invalid block). + + API endpoints are individually versioned. As such, there is no direct + relationship between all v1 endpoints, all v2 endpoints, _etc._ and no such + relationship should be inferred. All JSON responses return the requested + data under a `data` key in the top level of their response. Additional + metadata may or may not be present in other keys at the top level of the + response, dependent on the endpoint. The rules that require an increase in + version number are as follows: + + - no field that is listed in an endpoint shall be removed without an + increase in the version number + - no field that is listed in an endpoint shall be altered in terms of + format (_e.g._ from a string to an array) without an increase in the + version number + + Note that it is possible for a field to be added to an endpoint's data or + metadata without an increase in the version number. + version: "dev" + contact: + name: Ethereum Github + url: https://github.com/ethereum/builder-apis/issues + license: + name: "CC0-1.0" + url: "https://creativecommons.org/publicdomain/zero/1.0/" + +servers: + - url: "{server_url}" + variables: + server_url: + description: "Builder node URL" + default: "http://localhost:18550" + +tags: + - name: Builder + description: Set of endpoints to interact with an external block builder. +paths: + /eth/v1/builder/validators: + $ref: "./apis/builder/validators.yaml" + /eth/v1/builder/header/{slot}/{parent_hash}/{pubkey}: + $ref: "./apis/builder/header.yaml" + /eth/v1/builder/blinded_blocks: + $ref: "./apis/builder/blinded_blocks.yaml" + /eth/v1/builder/status: + $ref: "./apis/builder/status.yaml" + +components: + schemas: + Uint64: + $ref: "./beacon-apis/types/primitive.yaml#/Uint64" + Root: + $ref: "./beacon-apis/types/primitive.yaml#/Root" + Pubkey: + $ref: "./beacon-apis/types/primitive.yaml#/Pubkey" + ErrorMessage: + $ref: "./beacon-apis/types/http.yaml#/ErrorMessage" + Bellatrix.ExecutionPayload: + $ref: "./beacon-apis/types/bellatrix/execution_payload.yaml#/Bellatrix/ExecutionPayload" + Bellatrix.SignedBlindedBeaconBlock: + $ref: "./beacon-apis/types/bellatrix/block.yaml#/Bellatrix/SignedBlindedBeaconBlock" + + Bellatrix.SignedBuilderBid: + $ref: "./types/bellatrix/bid.yaml#/Bellatrix/SignedBuilderBid" + SignedValidatorRegistration: + $ref: "./types/registration.yaml#/SignedValidatorRegistration" + + + responses: + InternalError: + $ref: "./types/http.yaml#/InternalError" + + examples: + Bellatrix.SignedBlindedBeaconBlock: + $ref: "./examples/bellatrix/signed_blinded_beacon_block.json" + Bellatrix.ExecutionPayload: + $ref: "./examples/bellatrix/execution_payload.json" + Bellatrix.SignedBuilderBid: + $ref: "./examples/bellatrix/signed_builder_bid.json" diff --git a/dictionary.dic b/dictionary.dic new file mode 100644 index 0000000..f8749ae Binary files /dev/null and b/dictionary.dic differ diff --git a/examples/bellatrix/execution_payload.json b/examples/bellatrix/execution_payload.json new file mode 100644 index 0000000..69bed39 --- /dev/null +++ b/examples/bellatrix/execution_payload.json @@ -0,0 +1,23 @@ +{ + "value": { + "version": "bellatrix", + "data": { + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_number": "1", + "gas_limit": "1", + "gas_used": "1", + "timestamp": "1", + "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "base_fee_per_gas": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "transactions": [ + "0x02f878831469668303f51d843b9ac9f9843b9aca0082520894c93269b73096998db66be0441e836d873535cb9c8894a19041886f000080c001a031cc29234036afbf9a1fb9476b463367cb1f957ac0b919b69bbc798436e604aaa018c4e9c3914eb27aadd0b91e10b18655739fcf8c1fc398763a9f1beecb8ddc86" + ] + } + } +} diff --git a/examples/bellatrix/signed_blinded_beacon_block.json b/examples/bellatrix/signed_blinded_beacon_block.json new file mode 100644 index 0000000..993f49f --- /dev/null +++ b/examples/bellatrix/signed_blinded_beacon_block.json @@ -0,0 +1,147 @@ +{ + "value": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body": { + "randao_reveal": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "eth1_data": { + "deposit_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "deposit_count": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "graffiti": "0xdeadbeefc0ffee", + "proposer_slashings": [ + { + "signed_header_1": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "signed_header_2": { + "message": { + "slot": "1", + "proposer_index": "1", + "parent_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "body_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ], + "attester_slashings": [ + { + "attestation_1": { + "attesting_indices": [ + "1" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "attestation_2": { + "attesting_indices": [ + "1" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } + } + ], + "attestations": [ + { + "aggregation_bits": "0x01", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505", + "data": { + "slot": "1", + "index": "1", + "beacon_block_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "source": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "target": { + "epoch": "1", + "root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + } + ], + "deposits": [ + { + "proof": [ + "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + ], + "data": { + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "withdrawal_credentials": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "amount": "1", + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } + ], + "voluntary_exits": [ + { + "message": { + "epoch": "1", + "validator_index": "1" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + ], + "sync_aggregate": { + "sync_committee_bits": "0x01", + "sync_committee_signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + }, + "execution_payload_header": { + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_number": "1", + "gas_limit": "1", + "gas_used": "1", + "timestamp": "1", + "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "base_fee_per_gas": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + } + } + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +} diff --git a/examples/bellatrix/signed_builder_bid.json b/examples/bellatrix/signed_builder_bid.json new file mode 100644 index 0000000..9e009f4 --- /dev/null +++ b/examples/bellatrix/signed_builder_bid.json @@ -0,0 +1,28 @@ +{ + "value": { + "version": "bellatrix", + "data": { + "message": { + "header": { + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "state_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "receipts_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "logs_bloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "prev_randao": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_number": "1", + "gas_limit": "1", + "gas_used": "1", + "timestamp": "1", + "extra_data": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "base_fee_per_gas": "1", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "transactions_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "value": "1", + "pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } + } +} diff --git a/specs/README.md b/specs/README.md new file mode 100644 index 0000000..0ba4907 --- /dev/null +++ b/specs/README.md @@ -0,0 +1,136 @@ +# Builder API + +## Table of Contents + +* [Containers](#containers) + * [Independently Versioned](#independentlyversioned) + * [`ValidatorRegistrationV1`](#validatorregistrationv1) + * [`SignedValidatorRegistrationV1`](#signedvalidatorregistrationv1) + * [Fork Versioned](#forkversioned) + * [Bellatrix](#forkversioned) + * [`BuilderBid`](#builderbid) + * [`SignedBuilderBid`](#signedbuilderbid) + * [`BlindedBeaconBlockBody`](#blindedbeaconblockbody) + * [`BlindedBeaconBlock`](#blindedbeaconblock) + * [`SignedBlindedBeaconBlock`](#signedblindedbeaconblock) + * [Signing](#signing) +* [Endpoints](#endpoints) + +## Containers + +Consider the following definitions supplementary to the definitions in +[`consensus-specs`][consensus-specs]. For information on how containers are +signed, see [Signing](#signing). + +### Independently Versioned + +Some objects can be updated independently of the `consensus-specs`, because +they originate solely from this specification. The objects are postfixed with +`VX` to denote their revision. + +#### `ValidatorRegistrationV1` + +```python +class ValidatorRegistrationV1(Container): + fee_recipient: ExecutionAddress + gas_limit: uint64 + timestamp: uint64 + pubkey: BLSPubkey +``` + +#### `SignedValidatorRegistrationV1` + +```python +class SignedValidatorRegistrationV1(Container): + message: ValidatorRegistrationV1 + signature: BLSSignature +``` + +### Fork Versioned + +Other objects are derivatives of `consensus-specs` types and depend on the +latest canonical fork. These objects are namespaced by their fork (e.g. +Bellatrix). + +#### Bellatrix + +##### `BuilderBid` + +```python +class BuilderBid(Container): + header: ExecutionPayloadHeader + value: uint256 + pubkey: BLSPubkey +``` + +##### `SignedBuilderBid` + +```python +class SignedBuilderBid(Container): + message: BuilderBid + signature: BLSSignature +``` + +##### `BlindedBeaconBlockBody` + +```python +class BlindedBeaconBlockBody(Container): + randao_reveal: BLSSignature + eth1_data: Eth1Data + graffiti: Bytes32 + proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS] + attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS] + attestations: List[Attestation, MAX_ATTESTATIONS] + deposits: List[Deposit, MAX_DEPOSITS] + voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS] + sync_aggregate: SyncAggregate + execution_payload_header: ExecutionPayloadHeader +``` + +##### `BlindedBeaconBlock` + +```python +class BlindedBeaconBlock(Container): + slot: Slot + proposer_index: ValidatorIndex + parent_root: Root + state_root: Root + body: BlindedBeaconBlockBody +``` + +##### `SignedBlindedBeaconBlock` + +```python +class SignedBlindedBeaconBlock(Container): + message: BlindedBeaconBlock + signature: BLSSignature +``` + +### Signing + +All signature operations should follow the [standard BLS operations][bls] +interface defined in `consensus-specs`. + +There are two types of data to sign over in the Builder API: +* In-protocol messages, e.g. [`BlindedBeaconBlock`](#blindedbeaconblock), which + should compute the signing root using [`compute_signing_root`][compute-root] + and use the domain specified for beacon block proposals. +* Builder API messages, e.g. validator registration, which should compute the + signing root using [`compute_signing_root`][compute-root] and the domain + `DomainType('0x00000001')`. +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](#containers). + + +## Endpoints + +Builder API endpoints are defined in `builder-oapi.yaml` in the root of the +repository. A rendered version can be viewed at +https://ethereum.github.io/builder-specs/. + + +[consensus-specs]: https://github.com/ethereum/consensus-specs +[bls]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#bls-signatures +[compute-root]: https://github.com/ethereum/consensus-specs/blob/dev/specs/phase0/beacon-chain.md#compute_signing_root diff --git a/spellcheck.yaml b/spellcheck.yaml new file mode 100644 index 0000000..8a75080 --- /dev/null +++ b/spellcheck.yaml @@ -0,0 +1,36 @@ +matrix: + - name: markdown + sources: + - '**/*.md|!beacon-apis/**' + aspell: + lang: en + d: en_US + ignore-case: true + run-together: true + run-together-min: 2 + run-together-limit: 256 + dictionary: + wordlists: + - wordlist.txt + encoding: utf-8 + pipeline: + - pyspelling.filters.markdown: + - pyspelling.filters.html: + comments: false + ignores: + - code + - pre + - name: yaml schemas + sources: + - '**/*.yaml|!beacon-apis/**|!spellcheck.yaml' + aspell: + lang: en + d: en_US + run-together: true + run-together-min: 2 + run-together-limit: 256 + dictionary: + wordlists: + - wordlist.txt + encoding: utf-8 + pipeline: null diff --git a/types/bellatrix/bid.yaml b/types/bellatrix/bid.yaml new file mode 100644 index 0000000..3e9e7fb --- /dev/null +++ b/types/bellatrix/bid.yaml @@ -0,0 +1,23 @@ +Bellatrix: + BuilderBid: + type: object + description: "The `BuilderBid` object from the Builder API spec." + properties: + header: + $ref: "../../beacon-apis/types/bellatrix/execution_payload.yaml#/Bellatrix/ExecutionPayloadHeader" + description: "`ExecutionPayloadHeader` to use in block proposal." + value: + $ref: "../../beacon-apis/types/primitive.yaml#/Uint256" + description: "Payment in wei that will be paid to the `fee_recipient` account." + pubkey: + $ref: "../../beacon-apis/types/primitive.yaml#/Pubkey" + description: "BLS public key of builder." + + SignedBuilderBid: + type: object + description: "The `SignedBuilderBid` object from the Builder API spec." + properties: + message: + $ref: "#/Bellatrix/BuilderBid" + signature: + $ref: "../../beacon-apis/types/primitive.yaml#/Signature" diff --git a/types/http.yaml b/types/http.yaml new file mode 100644 index 0000000..8ec5aae --- /dev/null +++ b/types/http.yaml @@ -0,0 +1,22 @@ +InternalError: + description: "Builder node internal error." + content: + application/json: + schema: + type: object + properties: + code: + description: "Either specific error code in case of invalid request or http status code" + type: number + example: 404 + message: + description: "Message describing error" + type: string + stacktraces: + description: "Optional stacktraces, sent when node is in debug mode" + type: array + items: + type: string + example: + code: 500 + message: "Internal server error" diff --git a/types/registration.yaml b/types/registration.yaml new file mode 100644 index 0000000..1eeefee --- /dev/null +++ b/types/registration.yaml @@ -0,0 +1,35 @@ +ValidatorRegistration: + type: object + description: | + The `ValidatorRegistration` object from the Builder API spec. + + Note, this type will be removed once it is included in the Beacon API. + properties: + fee_recipient: + allOf: + - $ref: "../beacon-apis/types/primitive.yaml#/ExecutionAddress" + - description: "Address to receive fees from the block." + gas_limit: + allOf: + - $ref: "../beacon-apis/types/primitive.yaml#/Uint64" + - description: "Gas limit the validator desires to target." + timestamp: + allOf: + - $ref: "../beacon-apis/types/primitive.yaml#/Uint64" + - description: "Unix timestamp of registration." + pubkey: + allOf: + - $ref: "../beacon-apis/types/primitive.yaml#/Pubkey" + - description: "BLS public key of validator." + +SignedValidatorRegistration: + type: object + description: | + The `SignedValidatorRegistration` object from the Builder API spec. + + Note, this type will be removed once it is included in the Beacon API. + properties: + message: + $ref: "#/ValidatorRegistration" + signature: + $ref: "../beacon-apis/types/primitive.yaml#/Signature" diff --git a/wordlist.txt b/wordlist.txt new file mode 100644 index 0000000..136669a --- /dev/null +++ b/wordlist.txt @@ -0,0 +1,26 @@ +apis +bellatrix +bls +bn +cli +dev +eth +http +https +json +mev +nodejs +npm +oapi +openapi +ssz +tbh +ui +uint +unblind +unblinded +url +validators +validator's +vc +wei