diff --git a/apis/beacon/proof/block.yaml b/apis/beacon/proof/block.yaml new file mode 100644 index 00000000..7d73b606 --- /dev/null +++ b/apis/beacon/proof/block.yaml @@ -0,0 +1,58 @@ +get: + operationId: "getBlockProof" + summary: "Get partial Merkle proof for requested beacon block" + description: | + Returns [MultiProofResponse](../../../types/api.yaml#/MultiProofResponse) for block with given 'blockId' in the + specified [MultiProofRequest](../../../types/api.yaml#/MultiProofRequest) format. A response for the current head + is always guaranteed, for past blocks it is optional unless guaranteed by an active [subscription](./subscribe.yaml). + tags: + - Beacon + parameters: + - name: block_id + in: path + required: true + $ref: '../../../beacon-node-oapi.yaml#/components/parameters/BlockId' + - name: format + in: query + required: true + schema: + $ref: '../../../beacon-node-oapi.yaml#/components/schemas/MultiProofRequest' + + responses: + "200": + description: Success + content: + application/octet-stream: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/MultiProofResponse" + + "400": + description: "Invalid block ID" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Invalid block ID: current" + "404": + description: "Block not found" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 404 + message: "Block not found" + "422": + description: "Requested tree node not available" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Requested tree node not available: #1234" + "500": + $ref: '../../../beacon-node-oapi.yaml#/components/responses/InternalError' + diff --git a/apis/beacon/proof/state.yaml b/apis/beacon/proof/state.yaml new file mode 100644 index 00000000..7d5a72c4 --- /dev/null +++ b/apis/beacon/proof/state.yaml @@ -0,0 +1,58 @@ +get: + operationId: "getStateProof" + summary: "Get partial Merkle proof for requested beacon state" + description: | + Returns [MultiProofResponse](../../../types/api.yaml#/MultiProofResponse) for state with given 'stateId' + in the specified [MultiProofRequest](../../../types/api.yaml#/MultiProofRequest) format if available. A response for the current head + is always guaranteed, for past blocks it is optional unless guaranteed by an active [subscription](./subscribe.yaml). + tags: + - Beacon + parameters: + - name: state_id + in: path + required: true + $ref: '../../../beacon-node-oapi.yaml#/components/parameters/StateId' + - name: format + in: query + required: true + schema: + $ref: '../../../beacon-node-oapi.yaml#/components/schemas/MultiProofRequest' + + responses: + "200": + description: Success + content: + application/octet-stream: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/MultiProofResponse" + + "400": + description: "Invalid state ID" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Invalid state ID: current" + "404": + description: "State not found" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 404 + message: "State not found" + "422": + description: "Requested tree node not available" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Requested tree node not available: #1234" + "500": + $ref: '../../../beacon-node-oapi.yaml#/components/responses/InternalError' + diff --git a/apis/beacon/proof/subscribe.yaml b/apis/beacon/proof/subscribe.yaml new file mode 100644 index 00000000..42882b55 --- /dev/null +++ b/apis/beacon/proof/subscribe.yaml @@ -0,0 +1,66 @@ +get: + operationId: "subscribeToProofs" + summary: "Subscribe to state or block proofs of future blocks" + description: | + Ensures that a [MultiProofResponse](../../../types/api.yaml#/MultiProofResponse) will be available for the states or blocks of + all *requested* future blocks in the specified [MultiProofRequest](../../../types/api.yaml#/MultiProofRequest) format. A block is + *requested* if `block.slot >= first+k*period > block.parent.slot` for any non-negative integer `k`. The default values of `first` and + `period` are both 0. A [MultiProofResponse](../../../types/api.yaml#/MultiProofResponse) is immediately returned for the last existing + canonical *requested* block if the state or block Merkle tree of that block is available. Otherwise a zero-length byte vector is + returned which means that the subscription has been successfully activated for future *requested* blocks. The generated proofs are + guaranteed to be available through `state` or `block` requests for 60 seconds. The subscription is guaranteed to stay active until its + *inactive timer* reaches 60 seconds. This timer is started whenever a new proof for a *requested* block is generated and it is stopped + and reset to zero whenever a [state](./state.yaml) or [block](./block.yaml) request is made to any response generated by the subscription. + tags: + - Beacon + parameters: + - name: blocks_or_states + in: path + required: true + type: string + enum: ["blocks", "states"] + - name: format + in: query + required: true + schema: + $ref: '../../../beacon-node-oapi.yaml#/components/schemas/MultiProofRequest' + - name: first + in: query + required: false + schema: + $ref: '../../../beacon-node-oapi.yaml#/components/schemas/Uint64' + - name: period + in: query + required: false + schema: + $ref: '../../../beacon-node-oapi.yaml#/components/schemas/Uint64' + + responses: + "200": + description: Success + content: + application/octet-stream: + schema: + oneOf: + - $ref: "../../../beacon-node-oapi.yaml#/components/schemas/MultiProofResponse" + - description: "zero-length byte vector" + "422": + description: "Requested tree node not available" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 400 + message: "Requested tree node not available: #1234" + "500": + $ref: '../../../beacon-node-oapi.yaml#/components/responses/InternalError' + "503": + description: "Too many subscriptions" + content: + application/json: + schema: + $ref: "../../../beacon-node-oapi.yaml#/components/schemas/ErrorMessage" + example: + code: 503 + message: "Too many subscriptions" diff --git a/beacon-node-oapi.yaml b/beacon-node-oapi.yaml index fa1e6a22..2c252ea9 100644 --- a/beacon-node-oapi.yaml +++ b/beacon-node-oapi.yaml @@ -112,6 +112,12 @@ paths: $ref: "./apis/beacon/pool/voluntary_exists.yaml" /eth/v1/beacon/pool/bls_to_execution_changes: $ref: "./apis/beacon/pool/bls_to_execution_changes.yaml" + /eth/v0/beacon/proof/state: + $ref: "./apis/beacon/proof/state.yaml" + /eth/v0/beacon/proof/block: + $ref: "./apis/beacon/proof/block.yaml" + /eth/v0/beacon/proof/subscribe: + $ref: "./apis/beacon/proof/subscribe.yaml" /eth/v2/debug/beacon/states/{state_id}: $ref: './apis/debug/state.v2.yaml' @@ -314,6 +320,8 @@ components: $ref: './types/fork_choice.yaml#/Node' ExtraData: $ref: './types/fork_choice.yaml#/ExtraData' + MultiProofResponse: + $ref: './types/api.yaml#/MultiProofResponse' parameters: StateId: diff --git a/types/api.yaml b/types/api.yaml index 9f43e51b..1523ef80 100644 --- a/types/api.yaml +++ b/types/api.yaml @@ -62,3 +62,23 @@ Committee: description: "List of validator indices assigned to this committee" items: $ref: './primitive.yaml#/Uint64' + +MultiProofRequest: + description: | + The binary Merkle multi-proof request format, interpreted as an MSB-first bit list, recursively encodes the shape of the subtree + that the requested proof should cover. If the subtree is a single node whose Merkle proof is the tree node itself, it is encoded + as a single `1` bit. Otherwise the subtree encoding consists of a `0` bit, then the recursive encoding of the left child subtree, + then the right child subtree. This encoding always ends with a `1` bit and in total consists of `N` `1` bits and `N-1` `0` bits, + where `N` is the number of tree nodes stored in the resulting [MultiProofResponse](./api.yaml#/MultiProofResponse) in the same + order as the `1` bits representing the stored nodes in the format. After the last `1` bit the remaining least significant bits + of the last byte are filled with zeroes. The hex encoding should always have an even number of nibbles and leading zeroes should + not be discarded. For example, a proof that proves the generalized tree index 42 should be encoded as 0x25e0. + type: string + format: hex + example: "0x25e0" + pattern: "^0x[a-fA-F0-9]+$" + +MultiProofResponse: + description: | + An `N*32` bytes long raw byte vector consisting of `N` Merkle tree nodes, each corresponding to a `1` bit in the + [MultiProofRequest](./api.yaml#/MultiProofRequest) format description, stored in the same order.