diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..27805f0 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,3 @@ +# -*- mode: gitattributes; -*- + +dist/** linguist-vendored diff --git a/.gitignore b/.gitignore index 485dee6..33a4b1c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ .idea +.DS_Store +node_modules + diff --git a/apis/relay/builder/blocks.yaml b/apis/relay/builder/blocks.yaml index b4315b5..7eef599 100644 --- a/apis/relay/builder/blocks.yaml +++ b/apis/relay/builder/blocks.yaml @@ -1,5 +1,5 @@ post: - operationId: "submitBlock" + operationId: "blocks_submit" summary: Submit a new block to the relay. description: | * Blocks can be submitted as JSON or SSZ, and optionally GZIP encoded. To be @@ -61,10 +61,9 @@ post: content: application/json: schema: - allOf: - - $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" - - example: - code: 400 - message: "payload for this slot was already delivered" + $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "payload for this slot was already delivered" "500": $ref: "../../../relay-oapi.yaml#/components/responses/InternalError" diff --git a/apis/relay/builder/headers.yaml b/apis/relay/builder/headers.yaml new file mode 100644 index 0000000..cbf92bd --- /dev/null +++ b/apis/relay/builder/headers.yaml @@ -0,0 +1,66 @@ +post: + operationId: "submitHeader" + summary: Submit optimistic header to the relay. + description: | + * Headers can be submitted as JSON or SSZ, and optionally GZIP encoded. To be + clear, there are four options: JSON, JSON+GZIP, SSZ, SSZ+GZIP. If JSON, the + content type should be `application/json`. If SSZ, the content type should + be `application/octet-stream`. + + * To enable GZIP compression for the request body, the HTTP content encoding + should be `gzip`. Compression is optional. + + * The relay will check that the builder has enough collateral to cover the + value of the bid. Otherwise the relay will not accept the optimistic header. + + * The relay will need the rest of payload via the optimistic v2 endpoint. If + not received in time, the relay will penalize the builder's collateral. + + * For accountability, builder signature is over the SSZ encoded `message`. + + * The `message`, which does not include the transactions, will be made + public via the data API, allowing anyone to verify the builder signature. + tags: + - Builder + parameters: + - name: cancellations + in: query + required: false + description: If set to 1, opt into bid cancellations. + schema: + $ref: "../../../relay-oapi.yaml#/components/schemas/Uint64" + requestBody: + description: A signed bid with an execution header. + required: true + content: + application/json: + schema: + oneOf: + - $ref: "../../../relay-oapi.yaml#/components/schemas/Bellatrix.SubmitHeaderRequest" + - $ref: "../../../relay-oapi.yaml#/components/schemas/Capella.SubmitHeaderRequest" + - $ref: "../../../relay-oapi.yaml#/components/schemas/Deneb.SubmitHeaderRequest" + examples: + bellatrix: + $ref: "../../../relay-oapi.yaml#/components/examples/Bellatrix.SubmitHeaderRequest" + capella: + $ref: "../../../relay-oapi.yaml#/components/examples/Capella.SubmitHeaderRequest" + deneb: + $ref: "../../../relay-oapi.yaml#/components/examples/Deneb.SubmitHeaderRequest" + application/octet-stream: + schema: + description: "SSZ serialized request. Use content type header to indicate that SSZ data is contained in the request body." + responses: + "200": + description: Success response. + "400": + description: Error response. + content: + application/json: + schema: + allOf: + - $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" + - example: + code: 400 + message: "payload for this slot was already delivered" + "500": + $ref: "../../../relay-oapi.yaml#/components/responses/InternalError" diff --git a/apis/relay/builder/validators.yaml b/apis/relay/builder/validators.yaml index 0ce39e0..0730759 100644 --- a/apis/relay/builder/validators.yaml +++ b/apis/relay/builder/validators.yaml @@ -1,5 +1,5 @@ get: - operationId: "getValidators" + operationId: "validators_list" summary: | Get a list of validator registrations for validators scheduled to propose in the current and next epoch. diff --git a/apis/relay/data/builder_blocks_received.yaml b/apis/relay/data/builder_blocks_received.yaml index 8cdddbf..4e39d38 100644 --- a/apis/relay/data/builder_blocks_received.yaml +++ b/apis/relay/data/builder_blocks_received.yaml @@ -1,5 +1,5 @@ get: - operationId: "getReceivedBids" + operationId: "blocks_list_received" summary: Get builder bid submissions. description: | * Returns a list of builder bids without execution payloads. @@ -50,10 +50,9 @@ get: content: application/json: schema: - allOf: - - $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" - - example: - code: 400 - message: "cannot specify both slot and cursor" + $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "cannot specify both slot and cursor" "500": $ref: "../../../relay-oapi.yaml#/components/responses/InternalError" diff --git a/apis/relay/data/proposer_payload_delivered.yaml b/apis/relay/data/proposer_payload_delivered.yaml index 013f4e5..5c8b6d6 100644 --- a/apis/relay/data/proposer_payload_delivered.yaml +++ b/apis/relay/data/proposer_payload_delivered.yaml @@ -1,5 +1,5 @@ get: - operationId: "getDeliveredPayloads" + operationId: "payloads_list_delivered" summary: Get payloads that were delivered to proposers. description: | * Payloads become available after the relay responds to a `getPayload` request from the proposer. @@ -68,10 +68,9 @@ get: content: application/json: schema: - allOf: - - $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" - - example: - code: 400 - message: "invalid block_hash argument" + $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "invalid block_hash argument" "500": $ref: "../../../relay-oapi.yaml#/components/responses/InternalError" diff --git a/apis/relay/data/validator_registration.yaml b/apis/relay/data/validator_registration.yaml index e1111a5..6da3be7 100644 --- a/apis/relay/data/validator_registration.yaml +++ b/apis/relay/data/validator_registration.yaml @@ -1,5 +1,5 @@ get: - operationId: "getValidatorRegistration" + operationId: "validators_get_registration" summary: Check that a validator is registered with the relay. description: | * Returns the latest validator registration for a given pubkey. @@ -26,10 +26,9 @@ get: content: application/json: schema: - allOf: - - $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" - - example: - code: 400 - message: "missing pubkey argument" + $ref: "../../../relay-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "missing pubkey argument" "500": $ref: "../../../relay-oapi.yaml#/components/responses/InternalError" diff --git a/beacon-apis b/beacon-apis index 2e7c4aa..69d2feb 160000 --- a/beacon-apis +++ b/beacon-apis @@ -1 +1 @@ -Subproject commit 2e7c4aabcf60f5ae6d414866c268aff350a70e81 +Subproject commit 69d2feb12a6047c4f21e628dea8b0135b7e9013a diff --git a/builder-specs b/builder-specs index 5cb324e..ae1d97d 160000 --- a/builder-specs +++ b/builder-specs @@ -1 +1 @@ -Subproject commit 5cb324e34e173d963d1233e238bf50e4d7497653 +Subproject commit ae1d97d080a12bfb7ca248b58fb1fc6b10aed02e diff --git a/examples/bellatrix/submit_header_request.json b/examples/bellatrix/submit_header_request.json new file mode 100644 index 0000000..422658a --- /dev/null +++ b/examples/bellatrix/submit_header_request.json @@ -0,0 +1,32 @@ +{ + "value": { + "message": { + "slot": "1", + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "builder_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "proposer_fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "gas_limit": "1", + "gas_used": "1", + "value": "1" + }, + "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/capella/submit_header_request.json b/examples/capella/submit_header_request.json new file mode 100644 index 0000000..4fd326f --- /dev/null +++ b/examples/capella/submit_header_request.json @@ -0,0 +1,32 @@ +{ + "value": { + "message": { + "slot": "1", + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "builder_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "proposer_fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "gas_limit": "1", + "gas_used": "1", + "value": "1" + }, + "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", + "withdrawals_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +} diff --git a/examples/deneb/submit_header_request.json b/examples/deneb/submit_header_request.json new file mode 100644 index 0000000..3eeee6c --- /dev/null +++ b/examples/deneb/submit_header_request.json @@ -0,0 +1,35 @@ +{ + "value": { + "message": { + "slot": "1", + "parent_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "block_hash": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2", + "builder_pubkey": "0x93247f2209abcacf57b75a51dafae777f9dd38bc7053d1af526f220a7489a6d3a2753e5f3e8b1cfe39b56f43611df74a", + "proposer_fee_recipient": "0xabcf8e0d4e9587369b2301d0790347320302cc09", + "gas_limit": "1", + "gas_used": "1", + "value": "1" + }, + "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", + "withdrawals_root": "0xcf8e0d4e9587369b2301d0790347320302cc0943d5a1884560367e8208d920f2" + }, + "blob_kzg_commitments": [ + "0xa94170080872584e54a1cf092d845703b13907f2e6b3b1c0ad573b910530499e3bcd48c6378846b80d2bfa58c81cf3d5" + ], + "signature": "0x1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505cc411d61252fb6cb3fa0017b679f8bb2305b26a285fa2737f175668d0dff91cc1b66ac1fb663c9bc59509846d6ec05345bd908eda73e670af888da41af171505" + } +} diff --git a/relay-oapi.yaml b/relay-oapi.yaml index 7f6044d..5be2c33 100644 --- a/relay-oapi.yaml +++ b/relay-oapi.yaml @@ -38,6 +38,13 @@ paths: $ref: "./apis/relay/data/validator_registration.yaml" components: + securitySchemes: + ApiKey: + type: apiKey + in: header + name: X-API-Key + description: Optional API key for authenticated requests + schemas: Uint64: $ref: "./beacon-apis/types/primitive.yaml#/Uint64" @@ -63,10 +70,92 @@ components: $ref: "./types/responses.yaml#/DeliveredPayloadsResponse" ReceivedBlocksResponse: $ref: "./types/responses.yaml#/ReceivedBlocksResponse" + PageInfo: + type: object + properties: + next_cursor: + type: string + description: "Cursor for next page of results" + has_more: + type: boolean + description: "Whether more results exist beyond this page" + ValidatorsPage: + type: object + properties: + data: + $ref: "#/components/schemas/ValidatorsResponse" + page_info: + $ref: "#/components/schemas/PageInfo" + DeliveredPayloadsPage: + type: object + properties: + data: + $ref: "#/components/schemas/DeliveredPayloadsResponse" + page_info: + $ref: "#/components/schemas/PageInfo" + ReceivedBlocksPage: + type: object + properties: + data: + $ref: "#/components/schemas/ReceivedBlocksResponse" + page_info: + $ref: "#/components/schemas/PageInfo" + $shared.BidTrace: + $ref: "./types/bids.yaml#/BidTraceV2" + $shared.BidTraceWithTimestamp: + $ref: "./types/bids.yaml#/BidTraceV2WithTimestamp" + $shared.ValidatorRegistration: + $ref: "./beacon-apis/types/registration.yaml#/SignedValidatorRegistration" + $shared.Signature: + $ref: "./beacon-apis/types/primitive.yaml#/Signature" + $shared.Pubkey: + $ref: "./beacon-apis/types/primitive.yaml#/Pubkey" + $shared.Uint64: + $ref: "./beacon-apis/types/primitive.yaml#/Uint64" + $shared.Root: + $ref: "./beacon-apis/types/primitive.yaml#/Root" + ValidationError: + allOf: + - $ref: "#/components/schemas/ErrorMessage" + - type: object + properties: + field_errors: + type: array + items: + type: object + properties: + field: + type: string + description: "Field name that caused the error" + message: + type: string + description: "Error message for this field" + description: "List of field-specific validation errors" + AuthenticationError: + allOf: + - $ref: "#/components/schemas/ErrorMessage" + - type: object + properties: + error_type: + type: string + enum: ["missing_api_key", "invalid_api_key", "expired_api_key"] + description: "Type of authentication error" responses: InternalError: $ref: "./types/http.yaml#/InternalError" + ValidationError: + description: "Validation error response" + content: + application/json: + schema: + $ref: "#/components/schemas/ValidationError" + AuthenticationError: + description: "Authentication error response" + content: + application/json: + schema: + $ref: "#/components/schemas/AuthenticationError" examples: Bellatrix.SubmitBlockRequest: diff --git a/types/bellatrix/requests.yaml b/types/bellatrix/requests.yaml index 6b26223..3c578d7 100644 --- a/types/bellatrix/requests.yaml +++ b/types/bellatrix/requests.yaml @@ -14,3 +14,11 @@ Bellatrix: properties: execution_payload: $ref: "../../beacon-apis/types/bellatrix/execution_payload.yaml#/Bellatrix/ExecutionPayload" + + SubmitHeaderRequest: + allOf: + - $ref: '#/Bellatrix/SubmitBlockRequestCommon' + - type: object + properties: + header: + $ref: "../../beacon-apis/types/bellatrix/execution_payload.yaml#/Bellatrix/ExecutionPayloadHeader" diff --git a/types/capella/requests.yaml b/types/capella/requests.yaml index f28c62e..ca92a9c 100644 --- a/types/capella/requests.yaml +++ b/types/capella/requests.yaml @@ -6,3 +6,11 @@ Capella: properties: execution_payload: $ref: "../../beacon-apis/types/capella/execution_payload.yaml#/Capella/ExecutionPayload" + + SubmitHeaderRequest: + allOf: + - $ref: '#/Bellatrix/SubmitBlockRequestCommon' + - type: object + properties: + header: + $ref: "../../beacon-apis/types/bellatrix/execution_payload.yaml#/Capella/ExecutionPayloadHeader" diff --git a/types/deneb/requests.yaml b/types/deneb/requests.yaml index 3488862..27f4865 100644 --- a/types/deneb/requests.yaml +++ b/types/deneb/requests.yaml @@ -3,3 +3,17 @@ Deneb: allOf: - $ref: '../bellatrix/requests.yaml#/Bellatrix/SubmitBlockRequestCommon' - $ref: "../../builder-specs/types/deneb/execution_payload_and_blobs_bundle.yaml#/Deneb/ExecutionPayloadAndBlobsBundle" + + SubmitHeaderRequest: + allOf: + - $ref: '#/Bellatrix/SubmitBlockRequestCommon' + - type: object + properties: + header: + $ref: "../../beacon-apis/types/bellatrix/execution_payload.yaml#/Deneb/ExecutionPayloadHeader" + blob_kzg_commitments: + type: array + items: + $ref: '../../beacon-apis/types/primitive.yaml#/KZGCommitment' + minItems: 0 + maxItems: 4096 \ No newline at end of file diff --git a/wordlist.txt b/wordlist.txt index 390a228..70895ed 100644 --- a/wordlist.txt +++ b/wordlist.txt @@ -13,6 +13,7 @@ gzip http https json +kzg mev nodejs npm