Conversation
|
CI is failing. You can check for lints with |
## Description After a restart, a Lighthouse node can fail to resume syncing on a Gloas network. This can happen when the node persists a Gloas beacon block before it fully imports the payload envelope. A restart then clears the in-memory pending payload cache. Sync downloads the envelope and custody columns for the block again, but reprocessing the known block does not restore its signed execution payload bid. Lighthouse cannot join the downloaded components, and the lookup can run out of attempts. Dependent blocks then stop progressing. Custody-column and execution-proof processing now load the bid from the persisted block when the cache is empty. Envelope processing reuses the bid from the block that it already loaded.
## Issue Addressed Part of FOCIL (EIP-7805). This puts the inclusion list store from sigp#9744 onto `BeaconChain` and adds the read wrappers that will be used by gossip verification, fork-choice enforcement, and block production. ## Proposed Changes * Add an `inclusion_list_store` field to `BeaconChain`, initialise it from `ChainSpec` in `builder.rs`, and prune it in `per_slot_task`. * Add `inclusion_list_committee`, which resolves the ordered committee for a slot and returns it together with the dependent root used to key the store. * Add `get_inclusion_list_transactions`, `get_inclusion_list_bits`, and `is_inclusion_list_bits_inclusive` as wrappers around the store reads. * Add `BeaconChainError::InclusionListStoreError`. * Add tests covering each read path, the epoch boundary case, and pruning through `per_slot_task`. This is independent of sigp#9846, and nothing is calling these wrappers yet. Gossip verification will be the follow-up. ## Additional Info The wrappers take an anchor block root rather than using the head. `with_committee_cache` only resolves a block's own or next epoch shuffling, while inclusion list reads use `slot - 1`. Once per epoch, that falls into the previous epoch and fails when using the head root. There's a test covering this case. `with_committee_cache` already gives us the attester shuffling decision root, so we get both the committee and the store key from the same lookup. This is also the root that the producer puts in the message as `dependent_root`. `get_inclusion_list_transactions` only needs to resolve the shuffling for the dependent root and then discards the committee, since that root comes out of the same lookup. Co-authored-by: Eitan Seri- Levi <eserilev@gmail.com>
## Issue Addressed Part of FOCIL (EIP-7805). This adds `engine_newPayloadV6`, as specified in [Bogota](https://github.com/ethereum/execution-apis/blob/main/src/engine/bogota.md). ## Proposed Changes * Add `ENGINE_NEW_PAYLOAD_V6` and the `new_payload_v6` capability. * Add `inclusion_list_transactions` to `NewPayloadRequestHeze`. * Add `new_payload_v6_heze` and dispatch Heze requests to it. * Add `inclusion_list_satisfied` to `PayloadStatusV1` for the new `inclusionListSatisfied` response field. * Route the method in the mock EL, and fix its Heze fork check, which required V5. * Add tests for deserialising the response with and without `inclusionListSatisfied`. Nothing constructs a `NewPayloadRequestHeze` yet, so this doesn't change any behaviour. I also cleaned up the two now stale `TODO(heze)`s. ## Additional Info I kept `inclusion_list_satisfied` on `PayloadStatusV1` rather than introducing a `PayloadStatusV2`. The new field is `BOOLEAN|null`, and the existing fields already use `Option` for the same reason. The alternative would be to introduce a versioned superstruct like `PayloadAttributes`, but that would mean making changes outside `execution_layer`. I'm fine with going that way if that's preferred. The Heze arm in `payload_notifier.rs` will need the transactions from the store. That part follows once sigp#9960 merges.
…API 5/5) (sigp#9807) Final PR of the Gloas builder API stack: - sign builder request-auth and preferences (REQUEST_AUTH signing domain, web3signer message type) - add the builder configuration store (`builder_definitions.yml`) and book documentation - add the builder-preferences service and switch block production to `POST` produceBlockV4 with a `BuilderConfig` body, threading the `Eth-Builder-Url` header through block publication - remove the now-unused legacy `GET` produceBlockV4 client methods
## Description Adds the per-validator builder configuration endpoints from [ethereum/keymanager-APIs#88](ethereum/keymanager-APIs#88). - `GET /eth/v1/validator/{pubkey}/builder_config` returns the configuration in use for the validator. - `POST /eth/v1/validator/{pubkey}/builder_config` replaces and persists the full configuration on a per-validator basis. It does not merge with the previous entry. - `DELETE /eth/v1/validator/{pubkey}/builder_config` removes the stored entry, so the validator inherits the global configuration again. The API stores per-validator entries under `validator_configs` in `builder_definitions.yml`. Changes made by `POST` and `DELETE` apply to subsequent builder preference publication and Gloas block production without a restart. When `auth_data` is omitted, global and per-validator builder configurations use the builder URL's lowercase ASCII hostname, following [ethereum/builder-specs#168](ethereum/builder-specs#168), [ethereum/beacon-APIs#642](ethereum/beacon-APIs#642) and [ethereum/keymanager-APIs#94](ethereum/keymanager-APIs#94). URLs with and without a trailing slash produce the same auth data. Closes sigp#9796 Closes sigp#10076 Co-authored-by: Mark Mackey <mark@sigmaprime.io>
| query: PayloadAttestationPoolQuery, | ||
| accept_header: Option<Accept>| { | ||
| task_spawner.blocking_response_task(Priority::P1, move || { | ||
| let fork_name = ForkName::Gloas; |
There was a problem hiding this comment.
This will always hardcode the fork name as Gloas, which is not ideal. We should get the fork name from the current slot using: chain.spec.fork_name_at_slot, you can refer to other endpoint examples for this.
| // GET beacon/pool/payload_attestations | ||
| let get_beacon_pool_payload_attestations = | ||
| get_beacon_pool_payload_attestations(&beacon_pool_path); | ||
|
|
There was a problem hiding this comment.
We can move this above/below a few lines so that it doesn't intervene in between the post endpoint
| accept_header: Option<Accept>| { | ||
| task_spawner.blocking_response_task(Priority::P1, move || { | ||
| let fork_name = ForkName::Gloas; | ||
| let attestations = chain.op_pool.get_all_payload_attestations(query.slot); |
There was a problem hiding this comment.
nit: prefer to stick with the payload_attestation name, i.e., let payload_attestations so that it is clear and not confused with normal attestations. Same with other namings
| self.payload_attestation_messages | ||
| /// Returns all known `PayloadAttestation` objects, optionally filtered by slot. | ||
| /// Unlike `get_payload_attestations` this applies no block-root filter and no cap | ||
| pub fn get_all_payload_attestations( |
There was a problem hiding this comment.
For now we have 2 functions: get_payload_attestations and this get_all_payload_attestations. We could combine two into one I think, as what is done in attestations here:
lighthouse/beacon_node/operation_pool/src/lib.rs
Lines 783 to 793 in e423a66
That's a bit cleaner imo
| "valid payload attestation should be sent to network" | ||
| ); | ||
|
|
||
| self.harness.extend_slots(1).await; |
There was a problem hiding this comment.
At the time, extend_slots was added so that the following cases would be checked in a slot after the head:
- All payload attestations are returned when the slot query parameter is omitted
- Only the attestations for the queried slot are returned when a slot is given
- A slot with no payload attestations in the pool returns an empty list
but thinking about it now, this can be checked without the extra extend_slots so removed it in c5a4fb6
| pub async fn test_get_beacon_pool_payload_attestations_invalid_slot(self) -> Self { | ||
| // The typed client takes an `Option<Slot>`, so a malformed slot can only be sent raw. | ||
| let url = self | ||
| .client | ||
| .server() | ||
| .expose_full() | ||
| .join("/eth/v1/beacon/pool/payload_attestations?slot=abc") | ||
| .unwrap(); | ||
|
|
||
| let response = reqwest::Client::new().get(url).send().await.unwrap(); | ||
|
|
||
| assert_eq!(response.status(), StatusCode::BAD_REQUEST); | ||
|
|
||
| self | ||
| } |
There was a problem hiding this comment.
Maybe no need this test? because currently other endpoints also don't have this invalid slot. This looks a bit of trivial
There was a problem hiding this comment.
I added this to test out the invalid slot revert but since none of the other endpoints have it, it makes sense to remove it. Removed c5a4fb6
| self | ||
| } | ||
|
|
||
| pub async fn test_get_beacon_pool_payload_attestations_after_reorg(mut self) -> Self { |
There was a problem hiding this comment.
Not sure about this test too. Is this necessary?
There was a problem hiding this comment.
The test was added to ensure payload attestations can be fetched regardless of whether they have been incorporated into a block as mentioned in the spec but I now noticed that none of the other pool endpoints have such a test, so for uniformity it makes sense to remove this one. Removed c5a4fb6
| pub fn pooled_payload_attestation_bits(&self, data: &PayloadAttestationData) -> usize { | ||
| self.chain | ||
| .op_pool | ||
| .get_payload_attestations(data.slot, data.beacon_block_root) | ||
| .iter() | ||
| .filter(|attestation| &attestation.data == data) | ||
| .map(|attestation| attestation.aggregation_bits.num_set_bits()) | ||
| .sum() | ||
| } | ||
|
|
||
| /// Number of PTC positions held by `validator_index`, which is how many bits its message sets. | ||
| pub fn ptc_seats(&self, slot: Slot, validator_index: u64) -> usize { | ||
| self.chain | ||
| .canonical_head | ||
| .cached_head() | ||
| .snapshot | ||
| .beacon_state | ||
| .get_ptc(slot, &self.chain.spec) | ||
| .expect("should get PTC") | ||
| .0 | ||
| .iter() | ||
| .filter(|index| **index as u64 == validator_index) | ||
| .count() | ||
| } | ||
|
|
There was a problem hiding this comment.
These two functions are duplication of the one in http tests.rs. We should make things simpler and not have this duplication. We can put these functions in beacon_chain/src/test_utils.rs so that they only appear once
… address non-test related comments
Issue Addressed
Addressed the following 2 checklist items in #9045
GET /eth/v1/beacon/pool/payload_attestationsendpointGET /eth/v1/beacon/pool/payload_attestationsSSZ response to use ProgressiveListProposed Changes
get_payload_attestationsfunction is called at the time of block production. This further changed the pool which now holdsPayloadAttestationinstead ofPayloadAttestationMessage, keyed byPayloadAttestationData.get_payload_attestationsbecomes a filter-and-clone function as wellget_all_payload_attestationsfunction which returns the aggregated payload attestations in the pool based on the optionalslotfilter. An omittedslotreturns all of the aggregated payload attestations in the pool. The new function will be used by theGET beacon/pool/payload_attestationsendpoint and kept separate from the existingget_payload_attestationsfunctionGET beacon/pool/payload_attestationsas per beacon API spec of the endpoint. It serves JSON or SSZ, depending onAcceptheader with the SSZ response returning aProgressiveListas per beacon-APIs#635 changeshttp_apiandnetworktests now assert on the aggregation bits for the message'sdatainstead of the pool's message/aggregate count