Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add execution_optimistic flag to responses #190

Merged
merged 5 commits into from
Mar 2, 2022
Merged

Conversation

paulhauner
Copy link
Contributor

@paulhauner paulhauner commented Feb 4, 2022

Overview

Adds an execution_optimistic: bool to the "metadata" of endpoints which might be "tainted" by an assumption about execution payload validity in an optimistic node.

This PR conflicts with the "Ethereum Beacon APIs" section of the optimistic sync spec. I propose that these changes should supersede the opt sync spec. That spec will need to be updated if this PR is merged.

I have not done a version bump (e.g., add a v2 and deprecate v1) for most endpoints. I am operating under the assumption that an optional field can be added to metadata without breaking the API. I'm interested to other opinions about bumping the version of all affected endpoints. I'm open to bumping all versions that's expected.

It should be mentioned that I'm not attached to this proposal, but I'm concerned that we're running out of time to standardise API behaviour with optimistic sync. I'm completely open to criticism and alternate proposals. I suggest reading the Optimistic Sync: HTTP API to understand the problem this PR is trying to address.

Notes

I've added help text for the execution_optimistic bool, but I'm not sure there's a way to view it from the UI. My Swagger skills are poor, perhaps someone could help understand how to access it or where to make that info more prominent.

When it comes to choosing if to set execution_optimsitic, I think clients should be free to return true whenever their head is optimistic. A lot of endpoints are based around an assumption about the head, for instance getting the block at slot 1 involves making an assumption about what the head is. Clients can also be free to set it on a more granular basis.

@ajsutton
Copy link
Contributor

ajsutton commented Feb 4, 2022

Shouldn't need to bump the version number - adding a field is backwards compatible. And we do have precedent for that - we added dependent_root for duties without bumping the version number.

@arnetheduck
Copy link
Contributor

Shouldn't need to bump the version number - adding a field is backwards compatible.

this is only partially true: de-facto, clients have been strict on extra fields because adding a field may alter the semantic requirements of correctly handling the message - we've had cross-client compatibility problems with different parsing strictness requirements on this point. basically, this would mean that any existing versions of clients possibly will stop working, forcing an upgrade, when the new field is added, until the strictness is relaxed.

If we're going to start adding fields, we should also decide on a policy for where this is allowed, with which constraints and what "old" versions of clients should do when they encounter a field they do not understand: what happens for example if a field is added to a spec type (like BeaconBlock) that you didn't expect to be there? It seems trivial now, but with enough forks "out there" it will be hard to maintain compatibility.

Even the config endpoint, which is an "open experimentation ground" for random constants has seen exhibits strictness compatibility issues.

@mcdee
Copy link
Contributor

mcdee commented Feb 4, 2022

I would argue that metadata changes should not fall under the requirement of requiring a version bump. One of the reasons we designed the API to return results under a data heading is to allow for additional fields at the top level without disrupting the data itself. An optimistic-sync-unaware client should be able to continue with this change without any alteration in its behavior.

@arnetheduck
Copy link
Contributor

arnetheduck commented Feb 4, 2022

One of the reasons we designed

This is a useful distinction, and if this is the way to go, we should make it explicit so that clients can design compatible data validation routines (and appropriately scope future additions to such "optional" fields)

@mcdee
Copy link
Contributor

mcdee commented Feb 4, 2022

This is a useful distinction, and if this is the way to go, we should make it explicit so that clients can design compatible data validation routines (and appropriately scope future additions to such "optional" fields)

Totally agree with that, unfortunately there are various pieces of the API that are still way too much implicit rather than clearly stated anywhere. I'll see if I put together a PR to make this clear in the appropriate place in the spec.

@djrtwo
Copy link
Contributor

djrtwo commented Feb 7, 2022

checking in on this -- There seem to be two things under discussion

  1. the use of execution_optimistic
  2. how to extend the spec with additional optional data

Are we blocked on (1) until a subsequent PR for (2)

Or can we move forward tackling (1) here and now

@paulhauner
Copy link
Contributor Author

Are we blocked on (1) until a subsequent PR for (2)

IMO we should move ahead with discussing execution_optimsitic regardless if we need to bump API versions or not. It's an important enough change to warrant a version bump if need be.

@paulhauner
Copy link
Contributor Author

I'm looking for some help on getting CI passing 🙏 @mpetrunic, perhaps you are familiar with the error I'm getting?

@mpetrunic
Copy link
Collaborator

I'm looking for some help on getting CI passing pray @mpetrunic, perhaps you are familiar with the error I'm getting?

I already put PR with fix for it: #191 but we need to nudge @djrtwo or somebody with write access to approve so I can merge 😅

@ajsutton
Copy link
Contributor

What does the block/state ID head mean during optimistic sync? Should it mean the optimistic head or the fully verified ancestor? I think given we're exposing optimistic data now I'd say it should be the optimistic head but we should make that clear.

Currently it's defined as "head" (canonical head in node's view)

@mpetrunic
Copy link
Collaborator

@paulhauner could you check "Allow edits from maintainers" or rebase latest master to fix ci 😄

@paulhauner
Copy link
Contributor Author

@paulhauner could you check "Allow edits from maintainers" or rebase latest master to fix ci smile

Unfortunately I can't allow edits, the checkbox is missing.

I did rebase on master, but that doesn't seem to have helped much sorry.

slot:
$ref: "../../beacon-node-oapi.yaml#/components/schemas/Uint64"
execution_optimistic:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ExecutionOptimistic"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong reference, one too many ../

@@ -27,6 +27,8 @@ get:
type: string
enum: [ phase0, altair ]
example: "phase0"
execution_optimistic:
$ref: "../../../beacon-node-oapi.yaml#/components/schemas/ExecutionOptimistic"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wrong reference, one too many ../

@mpetrunic
Copy link
Collaborator

@paulhauner looked closely and it seems you have some wrong refs :)

Copy link
Collaborator

@mpetrunic mpetrunic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@paulhauner duuude haha one more :)

apis/debug/heads.v2.yaml Outdated Show resolved Hide resolved
Co-authored-by: Marin Petrunić <mpetrunic@users.noreply.github.com>
@mcdee
Copy link
Contributor

mcdee commented Mar 1, 2022

Is this good to merge now? Would be good to have the API locked down as much as possible before kiln is released.

@arnetheduck
Copy link
Contributor

Sorry for the late idea, but one thing that makes the transition period easier here would be that the field is only added after the client has transitioned into the merge epoch - this allows existing mainnet and testnets to not be affected by the change until the upgrade has happened and the field becomes relevant.

This is a better approach compatibility-wise because the hard fork guarantees that only updated clients access the api:s this way - thoughts?

@ajsutton
Copy link
Contributor

Sorry for the late idea, but one thing that makes the transition period easier here would be that the field is only added after the client has transitioned into the merge epoch - this allows existing mainnet and testnets to not be affected by the change until the upgrade has happened and the field becomes relevant.

This is doable but does make things more complex than I'd ideally like and means that any incompatibility is only discovered when Bellatrix is enabled.
Currently Teku is setup to only add the field if Bellatrix is enabled for a network (ie the fork epoch is not FAR_FUTURE_EPOCH) which has a similar effect of delaying the appearance of the field to give people time to ensure compatibility, just with a condition that doesn't change without a restart so makes things a bit easier. By the time we set a fork epoch for MainNet people will have had plenty of time to update so the new field is handled safely, but it's not so late as to be caught up in the actual fork activation.

bors bot pushed a commit to sigp/lighthouse that referenced this pull request Jul 25, 2022
## Issue Addressed

#3031 

## Proposed Changes

Updates the following API endpoints to conform with ethereum/beacon-APIs#190 and ethereum/beacon-APIs#196
- [x] `beacon/states/{state_id}/root` 
- [x] `beacon/states/{state_id}/fork`
- [x] `beacon/states/{state_id}/finality_checkpoints`
- [x] `beacon/states/{state_id}/validators`
- [x] `beacon/states/{state_id}/validators/{validator_id}`
- [x] `beacon/states/{state_id}/validator_balances`
- [x] `beacon/states/{state_id}/committees`
- [x] `beacon/states/{state_id}/sync_committees`
- [x] `beacon/headers`
- [x] `beacon/headers/{block_id}`
- [x] `beacon/blocks/{block_id}`
- [x] `beacon/blocks/{block_id}/root`
- [x] `beacon/blocks/{block_id}/attestations`
- [x] `debug/beacon/states/{state_id}`
- [x] `debug/beacon/heads`
- [x] `validator/duties/attester/{epoch}`
- [x] `validator/duties/proposer/{epoch}`
- [x] `validator/duties/sync/{epoch}`

Updates the following Server-Sent Events:
- [x]  `events?topics=head`
- [x]  `events?topics=block`
- [x]  `events?topics=finalized_checkpoint`
- [x]  `events?topics=chain_reorg`

## Backwards Incompatible
There is a very minor breaking change with the way the API now handles requests to `beacon/blocks/{block_id}/root` and `beacon/states/{state_id}/root` when `block_id` or `state_id` is the `Root` variant of `BlockId` and `StateId` respectively.

Previously a request to a non-existent root would simply echo the root back to the requester:
```
curl "http://localhost:5052/eth/v1/beacon/states/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/root"
{"data":{"root":"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}}
```
Now it will return a `404`:
```
curl "http://localhost:5052/eth/v1/beacon/blocks/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/root"
{"code":404,"message":"NOT_FOUND: beacon block with root 0xaaaa…aaaa","stacktraces":[]}
```

In addition to this is the block root `0x0000000000000000000000000000000000000000000000000000000000000000` previously would return the genesis block. It will now return a `404`:
```
curl "http://localhost:5052/eth/v1/beacon/blocks/0x0000000000000000000000000000000000000000000000000000000000000000"
{"code":404,"message":"NOT_FOUND: beacon block with root 0x0000…0000","stacktraces":[]}
```

## Additional Info
- `execution_optimistic` is always set, and will return `false` pre-Bellatrix. I am also open to the idea of doing something like `#[serde(skip_serializing_if = "Option::is_none")]`.
- The value of `execution_optimistic` is set to `false` where possible. Any computation that is reliant on the `head` will simply use the `ExecutionStatus` of the head (unless the head block is pre-Bellatrix).

Co-authored-by: Paul Hauner <paul@paulhauner.com>
bors bot pushed a commit to sigp/lighthouse that referenced this pull request Jul 25, 2022
## Issue Addressed

#3031 

## Proposed Changes

Updates the following API endpoints to conform with ethereum/beacon-APIs#190 and ethereum/beacon-APIs#196
- [x] `beacon/states/{state_id}/root` 
- [x] `beacon/states/{state_id}/fork`
- [x] `beacon/states/{state_id}/finality_checkpoints`
- [x] `beacon/states/{state_id}/validators`
- [x] `beacon/states/{state_id}/validators/{validator_id}`
- [x] `beacon/states/{state_id}/validator_balances`
- [x] `beacon/states/{state_id}/committees`
- [x] `beacon/states/{state_id}/sync_committees`
- [x] `beacon/headers`
- [x] `beacon/headers/{block_id}`
- [x] `beacon/blocks/{block_id}`
- [x] `beacon/blocks/{block_id}/root`
- [x] `beacon/blocks/{block_id}/attestations`
- [x] `debug/beacon/states/{state_id}`
- [x] `debug/beacon/heads`
- [x] `validator/duties/attester/{epoch}`
- [x] `validator/duties/proposer/{epoch}`
- [x] `validator/duties/sync/{epoch}`

Updates the following Server-Sent Events:
- [x]  `events?topics=head`
- [x]  `events?topics=block`
- [x]  `events?topics=finalized_checkpoint`
- [x]  `events?topics=chain_reorg`

## Backwards Incompatible
There is a very minor breaking change with the way the API now handles requests to `beacon/blocks/{block_id}/root` and `beacon/states/{state_id}/root` when `block_id` or `state_id` is the `Root` variant of `BlockId` and `StateId` respectively.

Previously a request to a non-existent root would simply echo the root back to the requester:
```
curl "http://localhost:5052/eth/v1/beacon/states/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/root"
{"data":{"root":"0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}}
```
Now it will return a `404`:
```
curl "http://localhost:5052/eth/v1/beacon/blocks/0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/root"
{"code":404,"message":"NOT_FOUND: beacon block with root 0xaaaa…aaaa","stacktraces":[]}
```

In addition to this is the block root `0x0000000000000000000000000000000000000000000000000000000000000000` previously would return the genesis block. It will now return a `404`:
```
curl "http://localhost:5052/eth/v1/beacon/blocks/0x0000000000000000000000000000000000000000000000000000000000000000"
{"code":404,"message":"NOT_FOUND: beacon block with root 0x0000…0000","stacktraces":[]}
```

## Additional Info
- `execution_optimistic` is always set, and will return `false` pre-Bellatrix. I am also open to the idea of doing something like `#[serde(skip_serializing_if = "Option::is_none")]`.
- The value of `execution_optimistic` is set to `false` where possible. Any computation that is reliant on the `head` will simply use the `ExecutionStatus` of the head (unless the head block is pre-Bellatrix).

Co-authored-by: Paul Hauner <paul@paulhauner.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants