From 9a295d09b4d79100ead84c25a2e6e7ee23e942a1 Mon Sep 17 00:00:00 2001 From: ethDreamer <37123614+ethDreamer@users.noreply.github.com> Date: Wed, 21 Aug 2024 23:51:43 -0500 Subject: [PATCH] Implement Electra `devnet-1` changes (#5937) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into p2p-electra * Merge branch 'p2p-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * fix genesis from eth1 for electra * Fix Electra Fork Choice Tests (#5764) * add new operation tests * Fix Electra Fork Choice Tests (#5764) * Fix Electra Fork Choice Tests (#5764) * Fix Electra Fork Choice Tests (#5764) * add epoch processing new tests * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into p2p-electra * Merge branch 'ef-tests-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * Merge branch 'p2p-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * fix ef test compilation * disable and enable ef test for epoch processing appropriately * add consolidations to merkle calc for inclusion proof * fix should_override_fc tests * Merge branch 'ef-tests-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * get ssz tests compiling * ssz merkle validity for only deneb * im dumb af * Merge remote-tracking branch 'upstream/ef-tests-electra' into ef-tests-electra * enable tests * Fix Consolidation Sigs & Withdrawals * Merge pull request #5766 from ethDreamer/two_fixes Fix Consolidation Sigs & Withdrawals * Merge branches 'block-processing-electra' and 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into p2p-electra * Merge branch 'p2p-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * comment out consolidation operation ef tests until they are added * add signed consolidation ssz tests * add as_iter to all List and Vector fields in the beacon state * remove dbg * Send unagg attestation based on fork * Merge branch 'beacon-api-electra' into p2p-electra * Merge branch 'p2p-electra' into ef-tests-electra * Fix Epoch Processing Consolidations * Fix Final Spec Tests! * Fix ser/de * Merge branch 'electra-engine-api' into beacon-api-electra * Merge branch 'beacon-api-electra' into p2p-electra * Merge branch 'p2p-electra' into ef-tests-electra * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * update electra readiness with new endpoints * don't block mev boost till genesis finalization * Publish all aggregates * just one more check bro plz.. * Fix Bug In Block Processing with 0x02 Credentials * fix slashing handling * Fix Bug In Block Processing with 0x02 Credentials * Merge remote-tracking branch 'upstream/unstable' * Send unagg attestation based on fork * Publish all aggregates * just one more check bro plz.. * Merge pull request #5832 from ethDreamer/electra_attestation_changes_merge_unstable Merge `unstable` into `electra_attestation_changes` * Merge pull request #5835 from realbigsean/fix-validator-logic Fix validator logic * Merge pull request #5816 from realbigsean/electra-attestation-slashing-handling Electra slashing handling * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into p2p-electra * Merge branch 'p2p-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * Rename deploy block electra (#5853) * Rename deploy_block.txt to deposit_contract_block.txt * fmt * Change for prater too * fix: serde rename camle case for execution payload body (#5846) * Merge branch 'electra-engine-api' into beacon-api-electra * Merge branch 'beacon-api-electra' into p2p-electra * Merge branch 'p2p-electra' into ef-tests-electra * Electra attestation changes rm decode impl (#5856) * Remove Crappy Decode impl for Attestation * Remove Inefficient Attestation Decode impl * Implement Schema Upgrade / Downgrade * Update beacon_node/beacon_chain/src/schema_change/migration_schema_v20.rs Co-authored-by: Michael Sproul --------- Co-authored-by: Michael Sproul * Fix failing attestation tests and misc electra attestation cleanup (#5810) * - get attestation related beacon chain tests to pass - observed attestations are now keyed off of data + committee index - rename op pool attestationref to compactattestationref - remove unwraps in agg pool and use options instead - cherry pick some changes from ef-tests-electra * cargo fmt * fix failing test * Revert dockerfile changes * make committee_index return option * function args shouldnt be a ref to attestation ref * fmt * fix dup imports --------- Co-authored-by: realbigsean * fix some todos (#5817) * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * add consolidations to merkle calc for inclusion proof * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into p2p-electra * Merge branch 'p2p-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * Remove Duplicate KZG Commitment Merkle Proof Code (#5874) * Remove Duplicate KZG Commitment Merkle Proof Code * s/tree_lists/fields/ * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * fix compile * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * Fix slasher tests (#5906) * Fix electra tests * Add electra attestations to double vote tests * Update superstruct to 0.8 * Merge remote-tracking branch 'origin/unstable' into electra_attestation_changes * Small cleanup in slasher tests * Clean up Electra observed aggregates (#5929) * Use consistent key in observed_attestations * Remove unwraps from observed aggregates * move committee bits to the last index in attestation (#5924) * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * De-dup attestation constructor logic * Remove unwraps in Attestation construction * Dedup match_attestation_data * Remove outdated TODO * Use ForkName Ord in fork-choice tests * Use ForkName Ord in BeaconBlockBody * Make to_electra not fallible * Remove TestRandom impl for IndexedAttestation * Remove IndexedAttestation faulty Decode impl * Drop TestRandom impl * Add PendingAttestationInElectra * Indexed att on disk (#35) * indexed att on disk * fix lints * Update slasher/src/migrate.rs Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com> --------- Co-authored-by: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com> * add electra fork enabled fn to ForkName impl (#36) * add electra fork enabled fn to ForkName impl * remove inadvertent file * Update common/eth2/src/types.rs Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com> * Dedup attestation constructor logic in attester cache * Use if let Ok for committee_bits * Dedup Attestation constructor code * Diff reduction in tests * Fix beacon_chain tests * Diff reduction * Use Ord for ForkName in pubsub * Resolve into_attestation_and_indices todo * Remove stale TODO * Fix beacon_chain tests * Test spec invariant * Use electra_enabled in pubsub * Remove get_indexed_attestation_from_signed_aggregate * Use ok_or instead of if let else * committees are sorted * remove dup method `get_indexed_attestation_from_committees` * Merge pull request #5940 from dapplion/electra_attestation_changes_lionreview Electra attestations #5712 review * update default persisted op pool deserialization * ensure aggregate and proof uses serde untagged on ref * Fork aware ssz static attestation tests * Electra attestation changes from Lions review (#5971) * dedup/cleanup and remove unneeded hashset use * remove irrelevant TODOs * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * Merge branch 'ef-tests-electra' of https://github.com/sigp/lighthouse into electra-devnet-1 * Fix Compilation Break * Merge pull request #5973 from ethDreamer/beacon-api-electra Fix Compilation Break * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * Merge branch 'ef-tests-electra' of https://github.com/sigp/lighthouse into electra-devnet-1 * Rename Constants, Structures, and Fields * Second Round * Third Round * Round Four * Electra attestation changes sean review (#5972) * instantiate empty bitlist in unreachable code * clean up error conversion * fork enabled bool cleanup * remove a couple todos * return bools instead of options in `aggregate` and use the result * delete commented out code * use map macros in simple transformations * remove signers_disjoint_from * get ef tests compiling * get ef tests compiling * update intentionally excluded files * Avoid changing slasher schema for Electra * Delete slasher schema v4 * Fix clippy * Fix compilation of beacon_chain tests * Update database.rs * Update per_block_processing.rs * Add electra lightclient types * Update slasher/src/database.rs * fix imports * Merge pull request #5980 from dapplion/electra-lightclient Add electra lightclient types * Merge pull request #5975 from michaelsproul/electra-slasher-no-migration Avoid changing slasher schema for Electra * Update beacon_node/beacon_chain/src/attestation_verification.rs * Update beacon_node/beacon_chain/src/attestation_verification.rs * Merge pull request #5974 from ethDreamer/electra-devnet-1 Electra: `devnet-1` Rename and Move Stuff * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * Merge branch 'electra_attestation_changes' of https://github.com/realbigsean/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * clean up enabled and disabled fork logic in ef tests * Merge branch 'ef-tests-electra' of https://github.com/sigp/lighthouse into electra-devnet-1 * Electra devnet 1 process operations (#5994) * Implement `process_consolidation_requests()` * Finish Changes to `process_operations()` * Fix Lint * Fix test * use electra_enabled() * add light client ssz tests * Update `engine-api` for `devnet-1` * disable failing light client ssz tests * correctly exclude light client struct from accessed files * Fix Failing Tests * Fix Calculations Relying on MAX_EB (#5983) * Fix Calculations Relying on MAX_EB * Use spec fn for max_effective_balance * The great renaming receipt -> request * Address some more review comments * Electra: Get `devnet-1` ef-tests Working * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra-engine-api * Update beacon_node/beacon_chain/src/electra_readiness.rs * Update consensus/types/src/chain_spec.rs * Update pending balance deposit processing (#6005) * Update pending balance deposit processing * Update single_pass.rs --------- Co-authored-by: Lion - dapplion <35266934+dapplion@users.noreply.github.com> * Merge pull request #6001 from ethDreamer/electra-devnet-1-engine-api Update `engine-api` for `devnet-1` * Merge pull request #6019 from ethDreamer/electra-devnet-1-ef-tests Electra: Get `devnet-1` ef-tests Working * Fix Bug in `engine_api` by Renaming Field * Merge pull request #6047 from ethDreamer/electra-devnet-1-engine-api-fix Fix Bug in `engine_api` by Renaming Field * one more stupid rename * update GET requests * update POST requests * add client updates and test updates * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * compile after merge * unwrap -> unwrap_err * self review * fix tests * convert op pool messages to electra in electra * remove methods to post without content header * Add BeaconBlocksByRange v3 * Revert "Add BeaconBlocksByRange v3" This reverts commit e3ce7fc5eae558da117b41ca7abbd6e03f4e420d. * filter instead of convert * Add range sync metrics to track efficiency (#6095) * Add more range sync metrics to track efficiency * Add ignored blocks metrics * Enable the outbound rate limiter by default, and update blobs method quotas (#6093) * Enable the outbound rate limiter by default, and update blobs method quotas. * Lint and book updates. * Beacon api + validator electra (#5744) * Attestation superstruct changes for EIP 7549 (#5644) * update * experiment * superstruct changes * revert * superstruct changes * fix tests * indexed attestation * indexed attestation superstruct * updated TODOs * `superstruct` the `AttesterSlashing` (#5636) * `superstruct` Attester Fork Variants * Push a little further * Deal with Encode / Decode of AttesterSlashing * not so sure about this.. * Stop Encode/Decode Bounds from Propagating Out * Tons of Changes.. * More Conversions to AttestationRef * Add AsReference trait (#15) * Add AsReference trait * Fix some snafus * Got it Compiling! :D * Got Tests Building * Get beacon chain tests compiling --------- Co-authored-by: Michael Sproul * Merge remote-tracking branch 'upstream/unstable' into electra_attestation_changes * Make EF Tests Fork-Agnostic (#5713) * Finish EF Test Fork Agnostic (#5714) * Superstruct `AggregateAndProof` (#5715) * Upgrade `superstruct` to `0.8.0` * superstruct `AggregateAndProof` * Merge remote-tracking branch 'sigp/unstable' into electra_attestation_changes * cargo fmt * Merge pull request #5726 from realbigsean/electra_attestation_changes Merge unstable into Electra attestation changes * process withdrawals updates * cleanup withdrawals processing * update `process_operations` deposit length check * add apply_deposit changes * add execution layer withdrawal request processing * process deposit receipts * add consolidation processing * update process operations function * exit updates * clean up * update slash_validator * EIP7549 `get_attestation_indices` (#5657) * get attesting indices electra impl * fmt * get tests to pass * fmt * fix some beacon chain tests * fmt * fix slasher test * fmt got me again * fix more tests * fix tests * Some small changes (#5739) * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * cargo fmt (#5740) * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * fix attestation verification * Add new engine api methods * Fix the versioning of v4 requests * Handle new engine api methods in mock EL * Note todo * Fix todos * Add support for electra fields in getPayloadBodies * Add comments for potential versioning confusion * udpates for aggregate attestation endpoint * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Sketch op pool changes * fix get attesting indices (#5742) * fix get attesting indices * better errors * fix compile * only get committee index once * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Ef test fixes (#5753) * attestation related ef test fixes * delete commented out stuff * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Fix Aggregation Pool for Electra (#5754) * Fix Aggregation Pool for Electra * Remove Outdated Interface * fix ssz (#5755) * Get `electra_op_pool` up to date (#5756) * fix get attesting indices (#5742) * fix get attesting indices * better errors * fix compile * only get committee index once * Ef test fixes (#5753) * attestation related ef test fixes * delete commented out stuff * Fix Aggregation Pool for Electra (#5754) * Fix Aggregation Pool for Electra * Remove Outdated Interface * fix ssz (#5755) --------- Co-authored-by: realbigsean * Revert "Get `electra_op_pool` up to date (#5756)" (#5757) This reverts commit ab9e58aa3d0e6fe2175a4996a5de710e81152896. * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into electra_op_pool * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Compute on chain aggregate impl (#5752) * add compute_on_chain_agg impl to op pool changes * fmt * get op pool tests to pass * update beacon api aggregate attestationendpoint * update the naive agg pool interface (#5760) * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * updates after merge * Fix bugs in cross-committee aggregation * Add comment to max cover optimisation * Fix assert * Electra epoch processing * add deposit limit for old deposit queue * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge pull request #5749 from sigp/electra_op_pool Optimise Electra op pool aggregation * don't fail on empty consolidations * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * update committee offset * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * update committee offset * update committee offset * update committee offset * only increment the state deposit index on old deposit flow * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * use correct max eb in epoch cache initialization * drop initiate validator ordering optimization * fix initiate exit for single pass * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * accept new payload v4 in mock el * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Fix Electra Fork Choice Tests (#5764) * Fix Electra Fork Choice Tests (#5764) * Fix Electra Fork Choice Tests (#5764) * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Fix Consolidation Sigs & Withdrawals * Merge pull request #5766 from ethDreamer/two_fixes Fix Consolidation Sigs & Withdrawals * Merge branches 'block-processing-electra' and 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Send unagg attestation based on fork * Fix ser/de * Merge branch 'electra-engine-api' into beacon-api-electra * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * Subscribe to the correct subnets for electra attestations (#5782) * subscribe to the correct att subnets for electra * subscribe to the correct att subnets for electra * cargo fmt * update electra readiness with new endpoints * fix slashing handling * Fix Bug In Block Processing with 0x02 Credentials * Merge remote-tracking branch 'upstream/unstable' * Send unagg attestation based on fork * Publish all aggregates * just one more check bro plz.. * Merge pull request #5832 from ethDreamer/electra_attestation_changes_merge_unstable Merge `unstable` into `electra_attestation_changes` * Merge pull request #5835 from realbigsean/fix-validator-logic Fix validator logic * Merge pull request #5816 from realbigsean/electra-attestation-slashing-handling Electra slashing handling * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * fix: serde rename camle case for execution payload body (#5846) * Merge branch 'electra-engine-api' into beacon-api-electra * Electra attestation changes rm decode impl (#5856) * Remove Crappy Decode impl for Attestation * Remove Inefficient Attestation Decode impl * Implement Schema Upgrade / Downgrade * Update beacon_node/beacon_chain/src/schema_change/migration_schema_v20.rs Co-authored-by: Michael Sproul --------- Co-authored-by: Michael Sproul * Fix failing attestation tests and misc electra attestation cleanup (#5810) * - get attestation related beacon chain tests to pass - observed attestations are now keyed off of data + committee index - rename op pool attestationref to compactattestationref - remove unwraps in agg pool and use options instead - cherry pick some changes from ef-tests-electra * cargo fmt * fix failing test * Revert dockerfile changes * make committee_index return option * function args shouldnt be a ref to attestation ref * fmt * fix dup imports --------- Co-authored-by: realbigsean * fix some todos (#5817) * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * add consolidations to merkle calc for inclusion proof * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Remove Duplicate KZG Commitment Merkle Proof Code (#5874) * Remove Duplicate KZG Commitment Merkle Proof Code * s/tree_lists/fields/ * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * fix compile * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Fix slasher tests (#5906) * Fix electra tests * Add electra attestations to double vote tests * Update superstruct to 0.8 * Merge remote-tracking branch 'origin/unstable' into electra_attestation_changes * Small cleanup in slasher tests * Clean up Electra observed aggregates (#5929) * Use consistent key in observed_attestations * Remove unwraps from observed aggregates * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * De-dup attestation constructor logic * Remove unwraps in Attestation construction * Dedup match_attestation_data * Remove outdated TODO * Use ForkName Ord in fork-choice tests * Use ForkName Ord in BeaconBlockBody * Make to_electra not fallible * Remove TestRandom impl for IndexedAttestation * Remove IndexedAttestation faulty Decode impl * Drop TestRandom impl * Add PendingAttestationInElectra * Indexed att on disk (#35) * indexed att on disk * fix lints * Update slasher/src/migrate.rs Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com> --------- Co-authored-by: Lion - dapplion <35266934+dapplion@users.noreply.github.com> Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com> * add electra fork enabled fn to ForkName impl (#36) * add electra fork enabled fn to ForkName impl * remove inadvertent file * Update common/eth2/src/types.rs Co-authored-by: ethDreamer <37123614+ethDreamer@users.noreply.github.com> * Dedup attestation constructor logic in attester cache * Use if let Ok for committee_bits * Dedup Attestation constructor code * Diff reduction in tests * Fix beacon_chain tests * Diff reduction * Use Ord for ForkName in pubsub * Resolve into_attestation_and_indices todo * Remove stale TODO * Fix beacon_chain tests * Test spec invariant * Use electra_enabled in pubsub * Remove get_indexed_attestation_from_signed_aggregate * Use ok_or instead of if let else * committees are sorted * remove dup method `get_indexed_attestation_from_committees` * Merge pull request #5940 from dapplion/electra_attestation_changes_lionreview Electra attestations #5712 review * update default persisted op pool deserialization * ensure aggregate and proof uses serde untagged on ref * Fork aware ssz static attestation tests * Electra attestation changes from Lions review (#5971) * dedup/cleanup and remove unneeded hashset use * remove irrelevant TODOs * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * Merge branch 'electra_attestation_changes' of https://github.com/sigp/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * Fix Compilation Break * Merge pull request #5973 from ethDreamer/beacon-api-electra Fix Compilation Break * Electra attestation changes sean review (#5972) * instantiate empty bitlist in unreachable code * clean up error conversion * fork enabled bool cleanup * remove a couple todos * return bools instead of options in `aggregate` and use the result * delete commented out code * use map macros in simple transformations * remove signers_disjoint_from * get ef tests compiling * get ef tests compiling * update intentionally excluded files * Avoid changing slasher schema for Electra * Delete slasher schema v4 * Fix clippy * Fix compilation of beacon_chain tests * Update database.rs * Update per_block_processing.rs * Add electra lightclient types * Update slasher/src/database.rs * fix imports * Merge pull request #5980 from dapplion/electra-lightclient Add electra lightclient types * Merge pull request #5975 from michaelsproul/electra-slasher-no-migration Avoid changing slasher schema for Electra * Update beacon_node/beacon_chain/src/attestation_verification.rs * Update beacon_node/beacon_chain/src/attestation_verification.rs * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra_attestation_changes * Merge branch 'electra_attestation_changes' of https://github.com/realbigsean/lighthouse into block-processing-electra * Merge branch 'block-processing-electra' of https://github.com/sigp/lighthouse into electra-epoch-proc * Merge branch 'electra-epoch-proc' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * The great renaming receipt -> request * Address some more review comments * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra-engine-api * Update beacon_node/beacon_chain/src/electra_readiness.rs * Update consensus/types/src/chain_spec.rs * update GET requests * update POST requests * add client updates and test updates * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra-engine-api * Merge branch 'electra-engine-api' of https://github.com/sigp/lighthouse into beacon-api-electra * compile after merge * unwrap -> unwrap_err * self review * fix tests * convert op pool messages to electra in electra * remove methods to post without content header * filter instead of convert * Merge branch 'unstable' of https://github.com/sigp/lighthouse into beacon-api-electra * Merge branch 'beacon-api-electra' of https://github.com/sigp/lighthouse into ef-tests-electra * fix ef test compile * use `enabled` fork methods * get tests passing * last updates * Fix bug on engine api with consolidations (#6101) * Fix small bug in engine_api * Merge pull request #6116 from ethDreamer/electra-devnet-1 Fix payload_bodies bug in engine_api * Merge branch 'unstable' of https://github.com/sigp/lighthouse into ef-tests-electra * add deposit request file * Merge branch 'unstable' of https://github.com/sigp/lighthouse into ef-tests-electra * Merge branch 'ef-tests-electra' of https://github.com/sigp/lighthouse into electra-devnet-1 * clean up after merge * Fix Broken Test on `devnet-1` * another small bug * Merge pull request #6132 from ethDreamer/devnet-1-fix-test Fix Broken Test on `devnet-1` * Fix Deserialization Bug in `engine-api` * Merge pull request #6235 from ethDreamer/fix_deserialization Fix Deserialization Bug in `engine-api` * Merge branch 'unstable' into electra-devnet-1 * remove import * Merge branch 'unstable' of https://github.com/sigp/lighthouse into electra-devnet-1 * Remove false negative checks on `shuffling_is_compatible` * Fix flaky validator monitor test --- .../beacon_chain/src/beacon_block_streamer.rs | 4 +- beacon_node/beacon_chain/src/beacon_chain.rs | 2 - beacon_node/beacon_chain/tests/store_tests.rs | 12 +- .../beacon_chain/tests/validator_monitor.rs | 42 ++- beacon_node/execution_layer/src/engine_api.rs | 304 ++++++++++++------ .../execution_layer/src/engine_api/http.rs | 93 +++++- .../src/engine_api/json_structures.rs | 151 ++++++--- beacon_node/execution_layer/src/lib.rs | 21 +- .../test_utils/execution_block_generator.rs | 2 + .../src/test_utils/handle_rpc.rs | 70 ++++ .../execution_layer/src/test_utils/mod.rs | 2 + beacon_node/http_api/tests/tests.rs | 2 +- consensus/fork_choice/tests/tests.rs | 2 +- consensus/state_processing/src/genesis.rs | 11 + .../block_signature_verifier.rs | 22 -- .../src/per_block_processing/errors.rs | 40 --- .../process_operations.rs | 255 ++++++--------- .../per_block_processing/signature_sets.rs | 38 +-- .../src/per_epoch_processing/single_pass.rs | 61 +++- consensus/types/presets/gnosis/electra.yaml | 2 +- consensus/types/presets/mainnet/electra.yaml | 2 +- consensus/types/presets/minimal/electra.yaml | 2 +- consensus/types/src/attestation.rs | 2 +- consensus/types/src/beacon_block.rs | 2 - consensus/types/src/beacon_block_body.rs | 6 - consensus/types/src/beacon_state.rs | 17 +- consensus/types/src/consolidation.rs | 37 --- ...solidation.rs => consolidation_request.rs} | 14 +- consensus/types/src/eth_spec.rs | 14 +- consensus/types/src/execution_payload.rs | 12 +- .../types/src/execution_payload_header.rs | 15 +- consensus/types/src/lib.rs | 10 +- consensus/types/src/payload.rs | 130 ++++++-- consensus/types/src/preset.rs | 5 +- consensus/types/src/signed_beacon_block.rs | 2 - consensus/types/src/validator.rs | 1 + ...rawal_request.rs => withdrawal_request.rs} | 4 +- testing/ef_tests/Makefile | 2 +- testing/ef_tests/check_all_files_accessed.py | 5 +- testing/ef_tests/src/cases/operations.rs | 22 +- testing/ef_tests/src/type_name.rs | 5 +- testing/ef_tests/tests/tests.rs | 53 ++- 42 files changed, 874 insertions(+), 624 deletions(-) delete mode 100644 consensus/types/src/consolidation.rs rename consensus/types/src/{signed_consolidation.rs => consolidation_request.rs} (53%) rename consensus/types/src/{execution_layer_withdrawal_request.rs => withdrawal_request.rs} (84%) diff --git a/beacon_node/beacon_chain/src/beacon_block_streamer.rs b/beacon_node/beacon_chain/src/beacon_block_streamer.rs index d63a3ee7ead..b68423422e9 100644 --- a/beacon_node/beacon_chain/src/beacon_block_streamer.rs +++ b/beacon_node/beacon_chain/src/beacon_block_streamer.rs @@ -1,5 +1,5 @@ use crate::{metrics, BeaconChain, BeaconChainError, BeaconChainTypes, BlockProcessStatus}; -use execution_layer::{ExecutionLayer, ExecutionPayloadBodyV1}; +use execution_layer::{ExecutionLayer, ExecutionPayloadBody}; use slog::{crit, debug, error, Logger}; use std::collections::HashMap; use std::sync::Arc; @@ -57,7 +57,7 @@ struct BodiesByRange { struct BlockParts { blinded_block: Box>, header: Box>, - body: Option>>, + body: Option>>, } impl BlockParts { diff --git a/beacon_node/beacon_chain/src/beacon_chain.rs b/beacon_node/beacon_chain/src/beacon_chain.rs index e290b4903a3..66e7d06ad7c 100644 --- a/beacon_node/beacon_chain/src/beacon_chain.rs +++ b/beacon_node/beacon_chain/src/beacon_chain.rs @@ -5531,8 +5531,6 @@ impl BeaconChain { bls_to_execution_changes: bls_to_execution_changes.into(), blob_kzg_commitments: kzg_commitments .ok_or(BlockProductionError::InvalidPayloadFork)?, - // TODO(electra): finish consolidations when they're more spec'd out - consolidations: Vec::new().into(), }, }), maybe_blobs_and_proofs, diff --git a/beacon_node/beacon_chain/tests/store_tests.rs b/beacon_node/beacon_chain/tests/store_tests.rs index 7049bf14fde..c1071d55cf6 100644 --- a/beacon_node/beacon_chain/tests/store_tests.rs +++ b/beacon_node/beacon_chain/tests/store_tests.rs @@ -1437,18 +1437,16 @@ fn check_shuffling_compatible( head_state.current_epoch(), |committee_cache, _| { let state_cache = head_state.committee_cache(RelativeEpoch::Current).unwrap(); + // We used to check for false negatives here, but had to remove that check + // because `shuffling_is_compatible` does not guarantee their absence. + // + // See: https://github.com/sigp/lighthouse/issues/6269 if current_epoch_shuffling_is_compatible { assert_eq!( committee_cache, state_cache.as_ref(), "block at slot {slot}" ); - } else { - assert_ne!( - committee_cache, - state_cache.as_ref(), - "block at slot {slot}" - ); } Ok(()) }, @@ -1479,8 +1477,6 @@ fn check_shuffling_compatible( let state_cache = head_state.committee_cache(RelativeEpoch::Previous).unwrap(); if previous_epoch_shuffling_is_compatible { assert_eq!(committee_cache, state_cache.as_ref()); - } else { - assert_ne!(committee_cache, state_cache.as_ref()); } Ok(()) }, diff --git a/beacon_node/beacon_chain/tests/validator_monitor.rs b/beacon_node/beacon_chain/tests/validator_monitor.rs index c2c03baff04..b4a54d26676 100644 --- a/beacon_node/beacon_chain/tests/validator_monitor.rs +++ b/beacon_node/beacon_chain/tests/validator_monitor.rs @@ -4,7 +4,7 @@ use beacon_chain::test_utils::{ use beacon_chain::validator_monitor::{ValidatorMonitorConfig, MISSED_BLOCK_LAG_SLOTS}; use logging::test_logger; use std::sync::LazyLock; -use types::{Epoch, EthSpec, Keypair, MainnetEthSpec, PublicKeyBytes, Slot}; +use types::{Epoch, EthSpec, ForkName, Keypair, MainnetEthSpec, PublicKeyBytes, Slot}; // Should ideally be divisible by 3. pub const VALIDATOR_COUNT: usize = 48; @@ -128,7 +128,7 @@ async fn produces_missed_blocks() { let initial_blocks = slots_per_epoch * nb_epoch_to_simulate.as_u64() - 1; // The validator index of the validator that is 'supposed' to miss a block - let mut validator_index_to_monitor = 1; + let validator_index_to_monitor = 1; // 1st scenario // // @@ -201,34 +201,22 @@ async fn produces_missed_blocks() { // Missed block happens when slot and prev_slot are not in the same epoch // making sure that the cache reloads when the epoch changes // in that scenario the slot that missed a block is the first slot of the epoch - validator_index_to_monitor = 7; // We are adding other validators to monitor as these ones will miss a block depending on // the fork name specified when running the test as the proposer cache differs depending on // the fork name (cf. seed) // // If you are adding a new fork and seeing errors, print // `validator_indexes[slot_in_epoch.as_usize()]` and add it below. - let validator_index_to_monitor_altair = 2; - // Same as above but for the merge upgrade - let validator_index_to_monitor_bellatrix = 4; - // Same as above but for the capella upgrade - let validator_index_to_monitor_capella = 11; - // Same as above but for the deneb upgrade - let validator_index_to_monitor_deneb = 3; - // Same as above but for the electra upgrade - let validator_index_to_monitor_electra = 6; - - let harness2 = get_harness( - validator_count, - vec![ - validator_index_to_monitor, - validator_index_to_monitor_altair, - validator_index_to_monitor_bellatrix, - validator_index_to_monitor_capella, - validator_index_to_monitor_deneb, - validator_index_to_monitor_electra, - ], - ); + let validator_index_to_monitor = match harness1.spec.fork_name_at_slot::(Slot::new(0)) { + ForkName::Base => 7, + ForkName::Altair => 2, + ForkName::Bellatrix => 4, + ForkName::Capella => 11, + ForkName::Deneb => 3, + ForkName::Electra => 1, + }; + + let harness2 = get_harness(validator_count, vec![validator_index_to_monitor]); let advance_slot_by = 9; harness2 .extend_chain( @@ -300,6 +288,12 @@ async fn produces_missed_blocks() { duplicate_block_root = *_state2.block_roots().get(idx as usize).unwrap(); validator_indexes = _state2.get_beacon_proposer_indices(&harness2.spec).unwrap(); let not_monitored_validator_index = validator_indexes[slot_in_epoch.as_usize()]; + // This could do with a refactor: https://github.com/sigp/lighthouse/issues/6293 + assert_ne!( + not_monitored_validator_index, + validator_index_to_monitor, + "this test has a fragile dependency on hardcoded indices. you need to tweak some settings or rewrite this" + ); assert_eq!( _state2.set_block_root(prev_slot, duplicate_block_root), diff --git a/beacon_node/execution_layer/src/engine_api.rs b/beacon_node/execution_layer/src/engine_api.rs index 6a56a5d076f..316b0dfa86a 100644 --- a/beacon_node/execution_layer/src/engine_api.rs +++ b/beacon_node/execution_layer/src/engine_api.rs @@ -2,7 +2,8 @@ use crate::engines::ForkchoiceState; use crate::http::{ ENGINE_FORKCHOICE_UPDATED_V1, ENGINE_FORKCHOICE_UPDATED_V2, ENGINE_FORKCHOICE_UPDATED_V3, ENGINE_GET_CLIENT_VERSION_V1, ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1, - ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, + ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2, ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, + ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2, ENGINE_GET_PAYLOAD_V1, ENGINE_GET_PAYLOAD_V2, ENGINE_GET_PAYLOAD_V3, ENGINE_GET_PAYLOAD_V4, ENGINE_NEW_PAYLOAD_V1, ENGINE_NEW_PAYLOAD_V2, ENGINE_NEW_PAYLOAD_V3, ENGINE_NEW_PAYLOAD_V4, }; @@ -20,11 +21,11 @@ use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use strum::IntoStaticStr; use superstruct::superstruct; -use types::execution_payload::{DepositRequests, WithdrawalRequests}; +use types::execution_payload::{ConsolidationRequests, DepositRequests, WithdrawalRequests}; pub use types::{ - Address, BeaconBlockRef, EthSpec, ExecutionBlockHash, ExecutionPayload, ExecutionPayloadHeader, - ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, Uint256, VariableList, - Withdrawal, Withdrawals, + Address, BeaconBlockRef, ConsolidationRequest, EthSpec, ExecutionBlockHash, ExecutionPayload, + ExecutionPayloadHeader, ExecutionPayloadRef, FixedVector, ForkName, Hash256, Transactions, + Uint256, VariableList, Withdrawal, Withdrawals, }; use types::{ ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb, @@ -42,7 +43,7 @@ pub use new_payload_request::{ NewPayloadRequestDeneb, NewPayloadRequestElectra, }; -use self::json_structures::{JsonDepositRequest, JsonWithdrawalRequest}; +use self::json_structures::{JsonConsolidationRequest, JsonDepositRequest, JsonWithdrawalRequest}; pub const LATEST_TAG: &str = "latest"; @@ -74,6 +75,7 @@ pub enum Error { UnsupportedForkVariant(String), InvalidClientVersion(String), RlpDecoderError(rlp::DecoderError), + TooManyConsolidationRequests(usize), } impl From for Error { @@ -206,6 +208,8 @@ pub struct ExecutionBlockWithTransactions { pub deposit_requests: Vec, #[superstruct(only(Electra))] pub withdrawal_requests: Vec, + #[superstruct(only(Electra))] + pub consolidation_requests: Vec, } impl TryFrom> for ExecutionBlockWithTransactions { @@ -323,6 +327,11 @@ impl TryFrom> for ExecutionBlockWithTransactions .into_iter() .map(|withdrawal| withdrawal.into()) .collect(), + consolidation_requests: block + .consolidation_requests + .into_iter() + .map(Into::into) + .collect(), }) } }; @@ -541,27 +550,106 @@ impl GetPayloadResponse { } } +#[superstruct( + variants(V1, V2), + variant_attributes(derive(Clone, Debug),), + partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant") +)] #[derive(Clone, Debug)] -pub struct ExecutionPayloadBodyV1 { +pub struct ExecutionPayloadBody { pub transactions: Transactions, pub withdrawals: Option>, + #[superstruct(only(V2))] pub deposit_requests: Option>, + #[superstruct(only(V2))] pub withdrawal_requests: Option>, + #[superstruct(only(V2))] + pub consolidation_requests: Option>, } -impl ExecutionPayloadBodyV1 { +impl ExecutionPayloadBody { + #[allow(clippy::type_complexity)] + pub fn deconstruct( + self, + ) -> ( + Transactions, + Option>, + Option>, + Option>, + Option>, + ) { + match self { + ExecutionPayloadBody::V1(body) => { + (body.transactions, body.withdrawals, None, None, None) + } + ExecutionPayloadBody::V2(body) => ( + body.transactions, + body.withdrawals, + body.deposit_requests, + body.withdrawal_requests, + body.consolidation_requests, + ), + } + } pub fn to_payload( self, header: ExecutionPayloadHeader, ) -> Result, String> { - match header { - ExecutionPayloadHeader::Bellatrix(header) => { - if self.withdrawals.is_some() { + let header_fork = header.fork_name_unchecked(); + match &self { + Self::V1(_) => { + if header_fork.electra_enabled() { return Err(format!( - "block {} is merge but payload body has withdrawals", - header.block_hash + "block {} is {} but response is ExecutionPayloadBodyV1. Does the EL support {}?", + header.block_hash(), + header_fork, + ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2, )); } + } + Self::V2(_) => {} + } + + let ( + transactions, + withdrawals, + deposit_requests, + withdrawal_requests, + consolidation_requests, + ) = self.deconstruct(); + if !header_fork.capella_enabled() && withdrawals.is_some() { + return Err(format!( + "block {} is {} but payload body has withdrawals", + header.block_hash(), + header_fork + )); + } + if !header_fork.electra_enabled() { + if deposit_requests.is_some() { + return Err(format!( + "block {} is {} but payload body has deposit_requests", + header.block_hash(), + header_fork + )); + } + if withdrawal_requests.is_some() { + return Err(format!( + "block {} is {} but payload body has withdrawal_requests", + header.block_hash(), + header_fork + )); + } + if consolidation_requests.is_some() { + return Err(format!( + "block {} is {} but payload body has consolidation_requests", + header.block_hash(), + header_fork + )); + } + } + + match header { + ExecutionPayloadHeader::Bellatrix(header) => { Ok(ExecutionPayload::Bellatrix(ExecutionPayloadBellatrix { parent_hash: header.parent_hash, fee_recipient: header.fee_recipient, @@ -576,100 +664,108 @@ impl ExecutionPayloadBodyV1 { extra_data: header.extra_data, base_fee_per_gas: header.base_fee_per_gas, block_hash: header.block_hash, - transactions: self.transactions, + transactions, })) } ExecutionPayloadHeader::Capella(header) => { - if let Some(withdrawals) = self.withdrawals { - Ok(ExecutionPayload::Capella(ExecutionPayloadCapella { - parent_hash: header.parent_hash, - fee_recipient: header.fee_recipient, - state_root: header.state_root, - receipts_root: header.receipts_root, - logs_bloom: header.logs_bloom, - prev_randao: header.prev_randao, - block_number: header.block_number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: header.extra_data, - base_fee_per_gas: header.base_fee_per_gas, - block_hash: header.block_hash, - transactions: self.transactions, - withdrawals, - })) - } else { - Err(format!( - "block {} is capella but payload body doesn't have withdrawals", - header.block_hash - )) - } + let withdrawals = withdrawals.ok_or_else(|| { + format!( + "block {} is {} but payload body has withdrawals set to null", + header.block_hash, header_fork + ) + })?; + Ok(ExecutionPayload::Capella(ExecutionPayloadCapella { + parent_hash: header.parent_hash, + fee_recipient: header.fee_recipient, + state_root: header.state_root, + receipts_root: header.receipts_root, + logs_bloom: header.logs_bloom, + prev_randao: header.prev_randao, + block_number: header.block_number, + gas_limit: header.gas_limit, + gas_used: header.gas_used, + timestamp: header.timestamp, + extra_data: header.extra_data, + base_fee_per_gas: header.base_fee_per_gas, + block_hash: header.block_hash, + transactions, + withdrawals, + })) } ExecutionPayloadHeader::Deneb(header) => { - if let Some(withdrawals) = self.withdrawals { - Ok(ExecutionPayload::Deneb(ExecutionPayloadDeneb { - parent_hash: header.parent_hash, - fee_recipient: header.fee_recipient, - state_root: header.state_root, - receipts_root: header.receipts_root, - logs_bloom: header.logs_bloom, - prev_randao: header.prev_randao, - block_number: header.block_number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: header.extra_data, - base_fee_per_gas: header.base_fee_per_gas, - block_hash: header.block_hash, - transactions: self.transactions, - withdrawals, - blob_gas_used: header.blob_gas_used, - excess_blob_gas: header.excess_blob_gas, - })) - } else { - Err(format!( - "block {} is post-capella but payload body doesn't have withdrawals", - header.block_hash - )) - } + let withdrawals = withdrawals.ok_or_else(|| { + format!( + "block {} is {} but payload body has withdrawals set to null", + header.block_hash, header_fork + ) + })?; + Ok(ExecutionPayload::Deneb(ExecutionPayloadDeneb { + parent_hash: header.parent_hash, + fee_recipient: header.fee_recipient, + state_root: header.state_root, + receipts_root: header.receipts_root, + logs_bloom: header.logs_bloom, + prev_randao: header.prev_randao, + block_number: header.block_number, + gas_limit: header.gas_limit, + gas_used: header.gas_used, + timestamp: header.timestamp, + extra_data: header.extra_data, + base_fee_per_gas: header.base_fee_per_gas, + block_hash: header.block_hash, + transactions, + withdrawals, + blob_gas_used: header.blob_gas_used, + excess_blob_gas: header.excess_blob_gas, + })) } ExecutionPayloadHeader::Electra(header) => { - let withdrawals_exist = self.withdrawals.is_some(); - let deposit_requests_exist = self.deposit_requests.is_some(); - let withdrawal_requests_exist = self.withdrawal_requests.is_some(); - if let (Some(withdrawals), Some(deposit_requests), Some(withdrawal_requests)) = ( - self.withdrawals, - self.deposit_requests, - self.withdrawal_requests, - ) { - Ok(ExecutionPayload::Electra(ExecutionPayloadElectra { - parent_hash: header.parent_hash, - fee_recipient: header.fee_recipient, - state_root: header.state_root, - receipts_root: header.receipts_root, - logs_bloom: header.logs_bloom, - prev_randao: header.prev_randao, - block_number: header.block_number, - gas_limit: header.gas_limit, - gas_used: header.gas_used, - timestamp: header.timestamp, - extra_data: header.extra_data, - base_fee_per_gas: header.base_fee_per_gas, - block_hash: header.block_hash, - transactions: self.transactions, - withdrawals, - blob_gas_used: header.blob_gas_used, - excess_blob_gas: header.excess_blob_gas, - deposit_requests, - withdrawal_requests, - })) - } else { - Err(format!( - "block {} is post-electra but payload body doesn't have withdrawals/deposit_requests/withdrawal_requests \ - withdrawals: {}, deposit_requests: {}, withdrawal_requests: {}", - header.block_hash, withdrawals_exist, deposit_requests_exist, withdrawal_requests_exist - )) - } + let withdrawals = withdrawals.ok_or_else(|| { + format!( + "block {} is {} but payload body has withdrawals set to null", + header.block_hash, header_fork + ) + })?; + let deposit_requests = deposit_requests.ok_or_else(|| { + format!( + "block {} is {} but payload body has deposit_requests set to null", + header.block_hash, header_fork + ) + })?; + let withdrawal_requests = withdrawal_requests.ok_or_else(|| { + format!( + "block {} is {} but payload body has withdrawal_requests set to null", + header.block_hash, header_fork + ) + })?; + let consolidation_requests = consolidation_requests.ok_or_else(|| { + format!( + "block {} is {} but payload body has consolidation_requests set to null", + header.block_hash, header_fork + ) + })?; + Ok(ExecutionPayload::Electra(ExecutionPayloadElectra { + parent_hash: header.parent_hash, + fee_recipient: header.fee_recipient, + state_root: header.state_root, + receipts_root: header.receipts_root, + logs_bloom: header.logs_bloom, + prev_randao: header.prev_randao, + block_number: header.block_number, + gas_limit: header.gas_limit, + gas_used: header.gas_used, + timestamp: header.timestamp, + extra_data: header.extra_data, + base_fee_per_gas: header.base_fee_per_gas, + block_hash: header.block_hash, + transactions, + withdrawals, + blob_gas_used: header.blob_gas_used, + excess_blob_gas: header.excess_blob_gas, + deposit_requests, + withdrawal_requests, + consolidation_requests, + })) } } } @@ -686,6 +782,8 @@ pub struct EngineCapabilities { pub forkchoice_updated_v3: bool, pub get_payload_bodies_by_hash_v1: bool, pub get_payload_bodies_by_range_v1: bool, + pub get_payload_bodies_by_hash_v2: bool, + pub get_payload_bodies_by_range_v2: bool, pub get_payload_v1: bool, pub get_payload_v2: bool, pub get_payload_v3: bool, @@ -723,6 +821,12 @@ impl EngineCapabilities { if self.get_payload_bodies_by_range_v1 { response.push(ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1); } + if self.get_payload_bodies_by_hash_v2 { + response.push(ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2); + } + if self.get_payload_bodies_by_range_v2 { + response.push(ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2); + } if self.get_payload_v1 { response.push(ENGINE_GET_PAYLOAD_V1); } diff --git a/beacon_node/execution_layer/src/engine_api/http.rs b/beacon_node/execution_layer/src/engine_api/http.rs index ecaf9c6c23e..1838d13bb06 100644 --- a/beacon_node/execution_layer/src/engine_api/http.rs +++ b/beacon_node/execution_layer/src/engine_api/http.rs @@ -50,6 +50,8 @@ pub const ENGINE_FORKCHOICE_UPDATED_TIMEOUT: Duration = Duration::from_secs(8); pub const ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1: &str = "engine_getPayloadBodiesByHashV1"; pub const ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1: &str = "engine_getPayloadBodiesByRangeV1"; +pub const ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2: &str = "engine_getPayloadBodiesByHashV2"; +pub const ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2: &str = "engine_getPayloadBodiesByRangeV2"; pub const ENGINE_GET_PAYLOAD_BODIES_TIMEOUT: Duration = Duration::from_secs(10); pub const ENGINE_EXCHANGE_CAPABILITIES: &str = "engine_exchangeCapabilities"; @@ -78,6 +80,8 @@ pub static LIGHTHOUSE_CAPABILITIES: &[&str] = &[ ENGINE_FORKCHOICE_UPDATED_V3, ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1, ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1, + ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2, + ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2, ENGINE_GET_CLIENT_VERSION_V1, ]; @@ -1035,7 +1039,7 @@ impl HttpJsonRpc { pub async fn get_payload_bodies_by_hash_v1( &self, block_hashes: Vec, - ) -> Result>>, Error> { + ) -> Result>>, Error> { let params = json!([block_hashes]); let response: Vec>> = self @@ -1048,7 +1052,27 @@ impl HttpJsonRpc { Ok(response .into_iter() - .map(|opt_json| opt_json.map(From::from)) + .map(|opt_json| opt_json.map(|v1| JsonExecutionPayloadBody::V1(v1).into())) + .collect()) + } + + pub async fn get_payload_bodies_by_hash_v2( + &self, + block_hashes: Vec, + ) -> Result>>, Error> { + let params = json!([block_hashes]); + + let response: Vec>> = self + .rpc_request( + ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2, + params, + ENGINE_GET_PAYLOAD_BODIES_TIMEOUT * self.execution_timeout_multiplier, + ) + .await?; + + Ok(response + .into_iter() + .map(|opt_json| opt_json.map(|v2| JsonExecutionPayloadBody::V2(v2).into())) .collect()) } @@ -1056,7 +1080,7 @@ impl HttpJsonRpc { &self, start: u64, count: u64, - ) -> Result>>, Error> { + ) -> Result>>, Error> { #[derive(Serialize)] #[serde(transparent)] struct Quantity(#[serde(with = "serde_utils::u64_hex_be")] u64); @@ -1072,7 +1096,31 @@ impl HttpJsonRpc { Ok(response .into_iter() - .map(|opt_json| opt_json.map(From::from)) + .map(|opt_json| opt_json.map(|v1| JsonExecutionPayloadBody::V1(v1).into())) + .collect()) + } + + pub async fn get_payload_bodies_by_range_v2( + &self, + start: u64, + count: u64, + ) -> Result>>, Error> { + #[derive(Serialize)] + #[serde(transparent)] + struct Quantity(#[serde(with = "serde_utils::u64_hex_be")] u64); + + let params = json!([Quantity(start), Quantity(count)]); + let response: Vec>> = self + .rpc_request( + ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2, + params, + ENGINE_GET_PAYLOAD_BODIES_TIMEOUT * self.execution_timeout_multiplier, + ) + .await?; + + Ok(response + .into_iter() + .map(|opt_json| opt_json.map(|v2| JsonExecutionPayloadBody::V2(v2).into())) .collect()) } @@ -1099,6 +1147,10 @@ impl HttpJsonRpc { .contains(ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V1), get_payload_bodies_by_range_v1: capabilities .contains(ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V1), + get_payload_bodies_by_hash_v2: capabilities + .contains(ENGINE_GET_PAYLOAD_BODIES_BY_HASH_V2), + get_payload_bodies_by_range_v2: capabilities + .contains(ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2), get_payload_v1: capabilities.contains(ENGINE_GET_PAYLOAD_V1), get_payload_v2: capabilities.contains(ENGINE_GET_PAYLOAD_V2), get_payload_v3: capabilities.contains(ENGINE_GET_PAYLOAD_V3), @@ -1274,6 +1326,39 @@ impl HttpJsonRpc { } } + pub async fn get_payload_bodies_by_hash( + &self, + block_hashes: Vec, + ) -> Result>>, Error> { + let engine_capabilities = self.get_engine_capabilities(None).await?; + if engine_capabilities.get_payload_bodies_by_hash_v2 { + self.get_payload_bodies_by_hash_v2(block_hashes).await + } else if engine_capabilities.get_payload_bodies_by_hash_v1 { + self.get_payload_bodies_by_hash_v1(block_hashes).await + } else { + Err(Error::RequiredMethodUnsupported( + "engine_getPayloadBodiesByHash", + )) + } + } + + pub async fn get_payload_bodies_by_range( + &self, + start: u64, + count: u64, + ) -> Result>>, Error> { + let engine_capabilities = self.get_engine_capabilities(None).await?; + if engine_capabilities.get_payload_bodies_by_range_v2 { + self.get_payload_bodies_by_range_v2(start, count).await + } else if engine_capabilities.get_payload_bodies_by_range_v1 { + self.get_payload_bodies_by_range_v1(start, count).await + } else { + Err(Error::RequiredMethodUnsupported( + "engine_getPayloadBodiesByRange", + )) + } + } + // automatically selects the latest version of // forkchoice_updated that the execution engine supports pub async fn forkchoice_updated( diff --git a/beacon_node/execution_layer/src/engine_api/json_structures.rs b/beacon_node/execution_layer/src/engine_api/json_structures.rs index f654ba4a0ea..00572150e05 100644 --- a/beacon_node/execution_layer/src/engine_api/json_structures.rs +++ b/beacon_node/execution_layer/src/engine_api/json_structures.rs @@ -5,10 +5,7 @@ use strum::EnumString; use superstruct::superstruct; use types::beacon_block_body::KzgCommitments; use types::blob_sidecar::BlobsList; -use types::{ - DepositRequest, ExecutionLayerWithdrawalRequest, FixedVector, PublicKeyBytes, Signature, - Unsigned, -}; +use types::{DepositRequest, FixedVector, PublicKeyBytes, Signature, Unsigned, WithdrawalRequest}; #[derive(Debug, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -106,11 +103,13 @@ pub struct JsonExecutionPayload { #[serde(with = "serde_utils::u64_hex_be")] pub excess_blob_gas: u64, #[superstruct(only(V4))] - // TODO(electra): Field name should be changed post devnet-0. See https://github.com/ethereum/execution-apis/pull/544 pub deposit_requests: VariableList, #[superstruct(only(V4))] pub withdrawal_requests: VariableList, + #[superstruct(only(V4))] + pub consolidation_requests: + VariableList, } impl From> for JsonExecutionPayloadV1 { @@ -225,6 +224,12 @@ impl From> for JsonExecutionPayloadV4 .map(Into::into) .collect::>() .into(), + consolidation_requests: payload + .consolidation_requests + .into_iter() + .map(Into::into) + .collect::>() + .into(), } } } @@ -353,6 +358,12 @@ impl From> for ExecutionPayloadElectra .map(Into::into) .collect::>() .into(), + consolidation_requests: payload + .consolidation_requests + .into_iter() + .map(Into::into) + .collect::>() + .into(), } } } @@ -737,45 +748,71 @@ impl From for JsonForkchoiceUpdatedV1Response { } } -#[derive(Clone, Debug, Serialize, Deserialize)] -#[serde(bound = "E: EthSpec")] -#[serde(rename_all = "camelCase")] -pub struct JsonExecutionPayloadBodyV1 { +#[superstruct( + variants(V1, V2), + variant_attributes( + derive(Clone, Debug, Serialize, Deserialize), + serde(bound = "E: EthSpec", rename_all = "camelCase"), + ), + partial_getter_error(ty = "Error", expr = "Error::IncorrectStateVariant") +)] +#[derive(Clone, Debug, Serialize)] +#[serde(bound = "E: EthSpec", rename_all = "camelCase", untagged)] +pub struct JsonExecutionPayloadBody { #[serde(with = "ssz_types::serde_utils::list_of_hex_var_list")] pub transactions: Transactions, pub withdrawals: Option>, + #[superstruct(only(V2))] pub deposit_requests: Option>, + #[superstruct(only(V2))] pub withdrawal_requests: Option>, -} - -impl From> for ExecutionPayloadBodyV1 { - fn from(value: JsonExecutionPayloadBodyV1) -> Self { - Self { - transactions: value.transactions, - withdrawals: value.withdrawals.map(|json_withdrawals| { - Withdrawals::::from( - json_withdrawals - .into_iter() - .map(Into::into) - .collect::>(), - ) - }), - deposit_requests: value.deposit_requests.map(|json_receipts| { - DepositRequests::::from( - json_receipts - .into_iter() - .map(Into::into) - .collect::>(), - ) + #[superstruct(only(V2))] + pub consolidation_requests: + Option>, +} + +impl From> for ExecutionPayloadBody { + fn from(value: JsonExecutionPayloadBody) -> Self { + match value { + JsonExecutionPayloadBody::V1(body_v1) => Self::V1(ExecutionPayloadBodyV1 { + transactions: body_v1.transactions, + withdrawals: body_v1.withdrawals.map(|json_withdrawals| { + Withdrawals::::from( + json_withdrawals + .into_iter() + .map(Into::into) + .collect::>(), + ) + }), }), - withdrawal_requests: value.withdrawal_requests.map(|json_withdrawal_requests| { - WithdrawalRequests::::from( - json_withdrawal_requests - .into_iter() - .map(Into::into) - .collect::>(), - ) + JsonExecutionPayloadBody::V2(body_v2) => Self::V2(ExecutionPayloadBodyV2 { + transactions: body_v2.transactions, + withdrawals: body_v2.withdrawals.map(|json_withdrawals| { + Withdrawals::::from( + json_withdrawals + .into_iter() + .map(Into::into) + .collect::>(), + ) + }), + deposit_requests: body_v2.deposit_requests.map(|json_receipts| { + DepositRequests::::from( + json_receipts + .into_iter() + .map(Into::into) + .collect::>(), + ) + }), + withdrawal_requests: body_v2.withdrawal_requests.map(|json_withdrawal_requests| { + WithdrawalRequests::::from( + json_withdrawal_requests + .into_iter() + .map(Into::into) + .collect::>(), + ) + }), + consolidation_requests: body_v2.consolidation_requests, }), } } @@ -896,27 +933,55 @@ impl From for DepositRequest { #[serde(rename_all = "camelCase")] pub struct JsonWithdrawalRequest { pub source_address: Address, - pub validator_public_key: PublicKeyBytes, + pub validator_pubkey: PublicKeyBytes, #[serde(with = "serde_utils::u64_hex_be")] pub amount: u64, } -impl From for JsonWithdrawalRequest { - fn from(withdrawal_request: ExecutionLayerWithdrawalRequest) -> Self { +impl From for JsonWithdrawalRequest { + fn from(withdrawal_request: WithdrawalRequest) -> Self { Self { source_address: withdrawal_request.source_address, - validator_public_key: withdrawal_request.validator_pubkey, + validator_pubkey: withdrawal_request.validator_pubkey, amount: withdrawal_request.amount, } } } -impl From for ExecutionLayerWithdrawalRequest { +impl From for WithdrawalRequest { fn from(json_withdrawal_request: JsonWithdrawalRequest) -> Self { Self { source_address: json_withdrawal_request.source_address, - validator_pubkey: json_withdrawal_request.validator_public_key, + validator_pubkey: json_withdrawal_request.validator_pubkey, amount: json_withdrawal_request.amount, } } } + +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] +#[serde(rename_all = "camelCase")] +pub struct JsonConsolidationRequest { + pub source_address: Address, + pub source_pubkey: PublicKeyBytes, + pub target_pubkey: PublicKeyBytes, +} + +impl From for JsonConsolidationRequest { + fn from(consolidation_request: ConsolidationRequest) -> Self { + Self { + source_address: consolidation_request.source_address, + source_pubkey: consolidation_request.source_pubkey, + target_pubkey: consolidation_request.target_pubkey, + } + } +} + +impl From for ConsolidationRequest { + fn from(json_consolidation_request: JsonConsolidationRequest) -> Self { + Self { + source_address: json_consolidation_request.source_address, + source_pubkey: json_consolidation_request.source_pubkey, + target_pubkey: json_consolidation_request.target_pubkey, + } + } +} diff --git a/beacon_node/execution_layer/src/lib.rs b/beacon_node/execution_layer/src/lib.rs index eaa739d7a5d..0da9225173c 100644 --- a/beacon_node/execution_layer/src/lib.rs +++ b/beacon_node/execution_layer/src/lib.rs @@ -1771,10 +1771,10 @@ impl ExecutionLayer { pub async fn get_payload_bodies_by_hash( &self, hashes: Vec, - ) -> Result>>, Error> { + ) -> Result>>, Error> { self.engine() .request(|engine: &Engine| async move { - engine.api.get_payload_bodies_by_hash_v1(hashes).await + engine.api.get_payload_bodies_by_hash(hashes).await }) .await .map_err(Box::new) @@ -1785,14 +1785,11 @@ impl ExecutionLayer { &self, start: u64, count: u64, - ) -> Result>>, Error> { + ) -> Result>>, Error> { let _timer = metrics::start_timer(&metrics::EXECUTION_LAYER_GET_PAYLOAD_BODIES_BY_RANGE); self.engine() .request(|engine: &Engine| async move { - engine - .api - .get_payload_bodies_by_range_v1(start, count) - .await + engine.api.get_payload_bodies_by_range(start, count).await }) .await .map_err(Box::new) @@ -2010,6 +2007,15 @@ impl ExecutionLayer { .collect(), ) .map_err(ApiError::DeserializeWithdrawalRequests)?; + let n_consolidations = electra_block.consolidation_requests.len(); + let consolidation_requests = VariableList::new( + electra_block + .consolidation_requests + .into_iter() + .map(Into::into) + .collect::>(), + ) + .map_err(|_| ApiError::TooManyConsolidationRequests(n_consolidations))?; ExecutionPayload::Electra(ExecutionPayloadElectra { parent_hash: electra_block.parent_hash, fee_recipient: electra_block.fee_recipient, @@ -2030,6 +2036,7 @@ impl ExecutionLayer { excess_blob_gas: electra_block.excess_blob_gas, deposit_requests, withdrawal_requests, + consolidation_requests, }) } }; diff --git a/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs b/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs index 8619e24a238..216c3b7844f 100644 --- a/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs +++ b/beacon_node/execution_layer/src/test_utils/execution_block_generator.rs @@ -659,8 +659,10 @@ impl ExecutionBlockGenerator { withdrawals: pa.withdrawals.clone().into(), blob_gas_used: 0, excess_blob_gas: 0, + // TODO(electra): consider how to test these fields below deposit_requests: vec![].into(), withdrawal_requests: vec![].into(), + consolidation_requests: vec![].into(), }), _ => unreachable!(), }, diff --git a/beacon_node/execution_layer/src/test_utils/handle_rpc.rs b/beacon_node/execution_layer/src/test_utils/handle_rpc.rs index 0dc7a7759c5..b1788498424 100644 --- a/beacon_node/execution_layer/src/test_utils/handle_rpc.rs +++ b/beacon_node/execution_layer/src/test_utils/handle_rpc.rs @@ -589,6 +589,65 @@ pub async fn handle_rpc( .withdrawals() .ok() .map(|withdrawals| VariableList::from(withdrawals.clone())), + })); + } + None => response.push(None), + } + } + + Ok(serde_json::to_value(response).unwrap()) + } + ENGINE_GET_PAYLOAD_BODIES_BY_RANGE_V2 => { + #[derive(Deserialize)] + #[serde(transparent)] + struct Quantity(#[serde(with = "serde_utils::u64_hex_be")] pub u64); + + let start = get_param::(params, 0) + .map_err(|s| (s, BAD_PARAMS_ERROR_CODE))? + .0; + let count = get_param::(params, 1) + .map_err(|s| (s, BAD_PARAMS_ERROR_CODE))? + .0; + + let mut response = vec![]; + for block_num in start..(start + count) { + let maybe_block = ctx + .execution_block_generator + .read() + .execution_block_with_txs_by_number(block_num); + + match maybe_block { + Some(block) => { + let transactions = Transactions::::new( + block + .transactions() + .iter() + .map(|transaction| VariableList::new(transaction.rlp().to_vec())) + .collect::>() + .map_err(|e| { + ( + format!("failed to deserialize transaction: {:?}", e), + GENERIC_ERROR_CODE, + ) + })?, + ) + .map_err(|e| { + ( + format!("failed to deserialize transactions: {:?}", e), + GENERIC_ERROR_CODE, + ) + })?; + + // TODO(electra): add testing for: + // deposit_requests + // withdrawal_requests + // consolidation_requests + response.push(Some(JsonExecutionPayloadBodyV2:: { + transactions, + withdrawals: block + .withdrawals() + .ok() + .map(|withdrawals| VariableList::from(withdrawals.clone())), deposit_requests: block.deposit_requests().ok().map( |deposit_requests| VariableList::from(deposit_requests.clone()), ), @@ -597,6 +656,17 @@ pub async fn handle_rpc( VariableList::from(withdrawal_requests.clone()) }, ), + consolidation_requests: block.consolidation_requests().ok().map( + |consolidation_requests| { + VariableList::from( + consolidation_requests + .clone() + .into_iter() + .map(Into::into) + .collect::>(), + ) + }, + ), })); } None => response.push(None), diff --git a/beacon_node/execution_layer/src/test_utils/mod.rs b/beacon_node/execution_layer/src/test_utils/mod.rs index 004bb17616a..c6bcdf4e444 100644 --- a/beacon_node/execution_layer/src/test_utils/mod.rs +++ b/beacon_node/execution_layer/src/test_utils/mod.rs @@ -47,7 +47,9 @@ pub const DEFAULT_ENGINE_CAPABILITIES: EngineCapabilities = EngineCapabilities { forkchoice_updated_v2: true, forkchoice_updated_v3: true, get_payload_bodies_by_hash_v1: true, + get_payload_bodies_by_hash_v2: true, get_payload_bodies_by_range_v1: true, + get_payload_bodies_by_range_v2: true, get_payload_v1: true, get_payload_v2: true, get_payload_v3: true, diff --git a/beacon_node/http_api/tests/tests.rs b/beacon_node/http_api/tests/tests.rs index afed095dbaf..62c196d9177 100644 --- a/beacon_node/http_api/tests/tests.rs +++ b/beacon_node/http_api/tests/tests.rs @@ -3431,7 +3431,7 @@ impl ApiTester { .get_validator_aggregate_attestation_v2( attestation.data().slot, attestation.data().tree_hash_root(), - attestation.committee_index().unwrap(), + attestation.committee_index().expect("committee index"), ) .await .unwrap() diff --git a/consensus/fork_choice/tests/tests.rs b/consensus/fork_choice/tests/tests.rs index d2935dbca45..19faf69bcb4 100644 --- a/consensus/fork_choice/tests/tests.rs +++ b/consensus/fork_choice/tests/tests.rs @@ -1344,7 +1344,7 @@ async fn progressive_balances_cache_attester_slashing() { // (`HeaderInvalid::ProposerSlashed`). The harness should be re-worked to successfully skip // the slot in this scenario rather than panic-ing. The same applies to // `progressive_balances_cache_proposer_slashing`. - .apply_blocks(1) + .apply_blocks(2) .await .add_previous_epoch_attester_slashing() .await diff --git a/consensus/state_processing/src/genesis.rs b/consensus/state_processing/src/genesis.rs index 049599ea945..00697def5d2 100644 --- a/consensus/state_processing/src/genesis.rs +++ b/consensus/state_processing/src/genesis.rs @@ -7,6 +7,7 @@ use crate::upgrade::{ upgrade_to_altair, upgrade_to_bellatrix, upgrade_to_capella, upgrade_to_deneb, }; use safe_arith::{ArithError, SafeArith}; +use std::sync::Arc; use tree_hash::TreeHash; use types::*; @@ -122,6 +123,16 @@ pub fn initialize_beacon_state_from_eth1( // Remove intermediate Deneb fork from `state.fork`. state.fork_mut().previous_version = spec.electra_fork_version; + // TODO(electra): think about this more and determine the best way to + // do this. The spec tests will expect that the sync committees are + // calculated using the electra value for MAX_EFFECTIVE_BALANCE when + // calling `initialize_beacon_state_from_eth1()`. But the sync committees + // are actually calcuated back in `upgrade_to_altair()`. We need to + // re-calculate the sync committees here now that the state is `Electra` + let sync_committee = Arc::new(state.get_next_sync_committee(spec)?); + *state.current_sync_committee_mut()? = sync_committee.clone(); + *state.next_sync_committee_mut()? = sync_committee; + // Override latest execution payload header. // See https://github.com/ethereum/consensus-specs/blob/dev/specs/capella/beacon-chain.md#testing if let Some(ExecutionPayloadHeader::Electra(header)) = execution_payload_header { diff --git a/consensus/state_processing/src/per_block_processing/block_signature_verifier.rs b/consensus/state_processing/src/per_block_processing/block_signature_verifier.rs index 223d7a4b891..24cb51d7557 100644 --- a/consensus/state_processing/src/per_block_processing/block_signature_verifier.rs +++ b/consensus/state_processing/src/per_block_processing/block_signature_verifier.rs @@ -170,7 +170,6 @@ where self.include_exits(block)?; self.include_sync_aggregate(block)?; self.include_bls_to_execution_changes(block)?; - self.include_consolidations(block)?; Ok(()) } @@ -359,27 +358,6 @@ where Ok(()) } - /// Includes all signatures in `self.block.body.consolidations` for verification. - pub fn include_consolidations>( - &mut self, - block: &'a SignedBeaconBlock, - ) -> Result<()> { - if let Ok(consolidations) = block.message().body().consolidations() { - self.sets.sets.reserve(consolidations.len()); - for consolidation in consolidations { - let set = consolidation_signature_set( - self.state, - self.get_pubkey.clone(), - consolidation, - self.spec, - )?; - - self.sets.push(set); - } - } - Ok(()) - } - /// Verify all the signatures that have been included in `self`, returning `true` if and only if /// all the signatures are valid. /// diff --git a/consensus/state_processing/src/per_block_processing/errors.rs b/consensus/state_processing/src/per_block_processing/errors.rs index cebb10b6071..fdeec6f08c3 100644 --- a/consensus/state_processing/src/per_block_processing/errors.rs +++ b/consensus/state_processing/src/per_block_processing/errors.rs @@ -89,46 +89,6 @@ pub enum BlockProcessingError { found: Hash256, }, WithdrawalCredentialsInvalid, - TooManyPendingConsolidations { - consolidations: usize, - limit: usize, - }, - ConsolidationChurnLimitTooLow { - churn_limit: u64, - minimum: u64, - }, - MatchingSourceTargetConsolidation { - index: u64, - }, - InactiveConsolidationSource { - index: u64, - current_epoch: Epoch, - }, - InactiveConsolidationTarget { - index: u64, - current_epoch: Epoch, - }, - SourceValidatorExiting { - index: u64, - }, - TargetValidatorExiting { - index: u64, - }, - FutureConsolidationEpoch { - current_epoch: Epoch, - consolidation_epoch: Epoch, - }, - NoSourceExecutionWithdrawalCredential { - index: u64, - }, - NoTargetExecutionWithdrawalCredential { - index: u64, - }, - MismatchedWithdrawalCredentials { - source_address: Address, - target_address: Address, - }, - InavlidConsolidationSignature, PendingAttestationInElectra, } diff --git a/consensus/state_processing/src/per_block_processing/process_operations.rs b/consensus/state_processing/src/per_block_processing/process_operations.rs index 17607f7f337..74166f67130 100644 --- a/consensus/state_processing/src/per_block_processing/process_operations.rs +++ b/consensus/state_processing/src/per_block_processing/process_operations.rs @@ -4,7 +4,6 @@ use crate::common::{ slash_validator, }; use crate::per_block_processing::errors::{BlockProcessingError, IntoWithIndex}; -use crate::signature_sets::consolidation_signature_set; use crate::VerifySignatures; use types::consts::altair::{PARTICIPATION_FLAG_WEIGHTS, PROPOSER_WEIGHT, WEIGHT_DENOMINATOR}; use types::typenum::U33; @@ -40,15 +39,16 @@ pub fn process_operations>( } if state.fork_name_unchecked().electra_enabled() { - let requests = block_body.execution_payload()?.withdrawal_requests()?; - if let Some(requests) = requests { - process_execution_layer_withdrawal_requests(state, &requests, spec)?; + state.update_pubkey_cache()?; + if let Some(deposit_requests) = block_body.execution_payload()?.deposit_requests()? { + process_deposit_requests(state, &deposit_requests, spec)?; } - let receipts = block_body.execution_payload()?.deposit_requests()?; - if let Some(receipts) = receipts { - process_deposit_requests(state, &receipts, spec)?; + if let Some(withdrawal_requests) = block_body.execution_payload()?.withdrawal_requests()? { + process_withdrawal_requests(state, &withdrawal_requests, spec)?; + } + if let Some(consolidations) = block_body.execution_payload()?.consolidation_requests()? { + process_consolidation_requests(state, &consolidations, spec)?; } - process_consolidations(state, block_body.consolidations()?, verify_signatures, spec)?; } Ok(()) @@ -371,10 +371,11 @@ pub fn process_deposits( ) -> Result<(), BlockProcessingError> { // [Modified in Electra:EIP6110] // Disable former deposit mechanism once all prior deposits are processed - // - // If `deposit_requests_start_index` does not exist as a field on `state`, electra is disabled - // which means we always want to use the old check, so this field defaults to `u64::MAX`. - let eth1_deposit_index_limit = state.deposit_requests_start_index().unwrap_or(u64::MAX); + let deposit_requests_start_index = state.deposit_requests_start_index().unwrap_or(u64::MAX); + let eth1_deposit_index_limit = std::cmp::min( + deposit_requests_start_index, + state.eth1_data().deposit_count, + ); if state.eth1_deposit_index() < eth1_deposit_index_limit { let expected_deposit_len = std::cmp::min( @@ -528,9 +529,10 @@ pub fn apply_deposit( Ok(()) } -pub fn process_execution_layer_withdrawal_requests( +// Make sure to build the pubkey cache before calling this function +pub fn process_withdrawal_requests( state: &mut BeaconState, - requests: &[ExecutionLayerWithdrawalRequest], + requests: &[WithdrawalRequest], spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { for request in requests { @@ -545,13 +547,11 @@ pub fn process_execution_layer_withdrawal_requests( } // Verify pubkey exists - let index_opt = state.get_validator_index(&request.validator_pubkey)?; - let Some(index) = index_opt else { + let Some(index) = state.pubkey_cache().get(&request.validator_pubkey) else { continue; }; let validator = state.get_validator(index)?; - // Verify withdrawal credentials let has_correct_credential = validator.has_execution_withdrawal_credential(spec); let is_correct_source_address = validator @@ -627,19 +627,19 @@ pub fn process_execution_layer_withdrawal_requests( pub fn process_deposit_requests( state: &mut BeaconState, - receipts: &[DepositRequest], + deposit_requests: &[DepositRequest], spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { - for receipt in receipts { + for request in deposit_requests { // Set deposit receipt start index if state.deposit_requests_start_index()? == spec.unset_deposit_requests_start_index { - *state.deposit_requests_start_index_mut()? = receipt.index + *state.deposit_requests_start_index_mut()? = request.index } let deposit_data = DepositData { - pubkey: receipt.pubkey, - withdrawal_credentials: receipt.withdrawal_credentials, - amount: receipt.amount, - signature: receipt.signature.clone().into(), + pubkey: request.pubkey, + withdrawal_credentials: request.withdrawal_credentials, + amount: request.amount, + signature: request.signature.clone().into(), }; apply_deposit(state, deposit_data, None, false, spec)? } @@ -647,149 +647,96 @@ pub fn process_deposit_requests( Ok(()) } -pub fn process_consolidations( +// Make sure to build the pubkey cache before calling this function +pub fn process_consolidation_requests( state: &mut BeaconState, - consolidations: &[SignedConsolidation], - verify_signatures: VerifySignatures, + consolidation_requests: &[ConsolidationRequest], spec: &ChainSpec, ) -> Result<(), BlockProcessingError> { - if consolidations.is_empty() { - return Ok(()); + for request in consolidation_requests { + process_consolidation_request(state, request, spec)?; } - // If the pending consolidations queue is full, no consolidations are allowed in the block - let pending_consolidations = state.pending_consolidations()?.len(); - let pending_consolidations_limit = E::pending_consolidations_limit(); - block_verify! { - pending_consolidations < pending_consolidations_limit, - BlockProcessingError::TooManyPendingConsolidations { - consolidations: pending_consolidations, - limit: pending_consolidations_limit - } - } + Ok(()) +} - // If there is too little available consolidation churn limit, no consolidations are allowed in the block - let churn_limit = state.get_consolidation_churn_limit(spec)?; - block_verify! { - churn_limit > spec.min_activation_balance, - BlockProcessingError::ConsolidationChurnLimitTooLow { - churn_limit, - minimum: spec.min_activation_balance - } +pub fn process_consolidation_request( + state: &mut BeaconState, + consolidation_request: &ConsolidationRequest, + spec: &ChainSpec, +) -> Result<(), BlockProcessingError> { + // If the pending consolidations queue is full, consolidation requests are ignored + if state.pending_consolidations()?.len() == E::PendingConsolidationsLimit::to_usize() { + return Ok(()); + } + // If there is too little available consolidation churn limit, consolidation requests are ignored + if state.get_consolidation_churn_limit(spec)? <= spec.min_activation_balance { + return Ok(()); } - for signed_consolidation in consolidations { - let consolidation = signed_consolidation.message.clone(); - - // Verify that source != target, so a consolidation cannot be used as an exit. - block_verify! { - consolidation.source_index != consolidation.target_index, - BlockProcessingError::MatchingSourceTargetConsolidation { - index: consolidation.source_index - } - } - - let source_validator = state.get_validator(consolidation.source_index as usize)?; - let target_validator = state.get_validator(consolidation.target_index as usize)?; - - // Verify the source and the target are active - let current_epoch = state.current_epoch(); - block_verify! { - source_validator.is_active_at(current_epoch), - BlockProcessingError::InactiveConsolidationSource{ - index: consolidation.source_index, - current_epoch - } - } - block_verify! { - target_validator.is_active_at(current_epoch), - BlockProcessingError::InactiveConsolidationTarget{ - index: consolidation.target_index, - current_epoch - } - } - - // Verify exits for source and target have not been initiated - block_verify! { - source_validator.exit_epoch == spec.far_future_epoch, - BlockProcessingError::SourceValidatorExiting{ - index: consolidation.source_index, - } - } - block_verify! { - target_validator.exit_epoch == spec.far_future_epoch, - BlockProcessingError::TargetValidatorExiting{ - index: consolidation.target_index, - } - } - - // Consolidations must specify an epoch when they become valid; they are not valid before then - block_verify! { - current_epoch >= consolidation.epoch, - BlockProcessingError::FutureConsolidationEpoch { - current_epoch, - consolidation_epoch: consolidation.epoch - } - } + let Some(source_index) = state + .pubkey_cache() + .get(&consolidation_request.source_pubkey) + else { + // source validator doesn't exist + return Ok(()); + }; + let Some(target_index) = state + .pubkey_cache() + .get(&consolidation_request.target_pubkey) + else { + // target validator doesn't exist + return Ok(()); + }; + // Verify that source != target, so a consolidation cannot be used as an exit. + if source_index == target_index { + return Ok(()); + } - // Verify the source and the target have Execution layer withdrawal credentials - block_verify! { - source_validator.has_execution_withdrawal_credential(spec), - BlockProcessingError::NoSourceExecutionWithdrawalCredential { - index: consolidation.source_index, - } - } - block_verify! { - target_validator.has_execution_withdrawal_credential(spec), - BlockProcessingError::NoTargetExecutionWithdrawalCredential { - index: consolidation.target_index, - } + let source_validator = state.get_validator(source_index)?; + // Verify the source withdrawal credentials + if let Some(withdrawal_address) = source_validator.get_execution_withdrawal_address(spec) { + if withdrawal_address != consolidation_request.source_address { + return Ok(()); } + } else { + // Source doen't have execution withdrawal credentials + return Ok(()); + } - // Verify the same withdrawal address - let source_address = source_validator - .get_execution_withdrawal_address(spec) - .ok_or(BeaconStateError::NonExecutionAddresWithdrawalCredential)?; - let target_address = target_validator - .get_execution_withdrawal_address(spec) - .ok_or(BeaconStateError::NonExecutionAddresWithdrawalCredential)?; - block_verify! { - source_address == target_address, - BlockProcessingError::MismatchedWithdrawalCredentials { - source_address, - target_address - } - } + let target_validator = state.get_validator(target_index)?; + // Verify the target has execution withdrawal credentials + if !target_validator.has_execution_withdrawal_credential(spec) { + return Ok(()); + } - if verify_signatures.is_true() { - let signature_set = consolidation_signature_set( - state, - |i| get_pubkey_from_state(state, i), - signed_consolidation, - spec, - )?; - block_verify! { - signature_set.verify(), - BlockProcessingError::InavlidConsolidationSignature - } - } - let exit_epoch = state.compute_consolidation_epoch_and_update_churn( - source_validator.effective_balance, - spec, - )?; - let source_validator = state.get_validator_mut(consolidation.source_index as usize)?; - // Initiate source validator exit and append pending consolidation - source_validator.exit_epoch = exit_epoch; - source_validator.withdrawable_epoch = source_validator - .exit_epoch - .safe_add(spec.min_validator_withdrawability_delay)?; - state - .pending_consolidations_mut()? - .push(PendingConsolidation { - source_index: consolidation.source_index, - target_index: consolidation.target_index, - })?; + // Verify the source and target are active + let current_epoch = state.current_epoch(); + if !source_validator.is_active_at(current_epoch) + || !target_validator.is_active_at(current_epoch) + { + return Ok(()); + } + // Verify exits for source and target have not been initiated + if source_validator.exit_epoch != spec.far_future_epoch + || target_validator.exit_epoch != spec.far_future_epoch + { + return Ok(()); } + // Initiate source validator exit and append pending consolidation + let source_exit_epoch = state + .compute_consolidation_epoch_and_update_churn(source_validator.effective_balance, spec)?; + let source_validator = state.get_validator_mut(source_index)?; + source_validator.exit_epoch = source_exit_epoch; + source_validator.withdrawable_epoch = + source_exit_epoch.safe_add(spec.min_validator_withdrawability_delay)?; + state + .pending_consolidations_mut()? + .push(PendingConsolidation { + source_index: source_index as u64, + target_index: target_index as u64, + })?; + Ok(()) } diff --git a/consensus/state_processing/src/per_block_processing/signature_sets.rs b/consensus/state_processing/src/per_block_processing/signature_sets.rs index 3c683766adb..2e00ee03418 100644 --- a/consensus/state_processing/src/per_block_processing/signature_sets.rs +++ b/consensus/state_processing/src/per_block_processing/signature_sets.rs @@ -11,8 +11,8 @@ use types::{ BeaconStateError, ChainSpec, DepositData, Domain, Epoch, EthSpec, Fork, Hash256, InconsistentFork, IndexedAttestation, IndexedAttestationRef, ProposerSlashing, PublicKey, PublicKeyBytes, Signature, SignedAggregateAndProof, SignedBeaconBlock, SignedBeaconBlockHeader, - SignedBlsToExecutionChange, SignedConsolidation, SignedContributionAndProof, SignedRoot, - SignedVoluntaryExit, SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned, + SignedBlsToExecutionChange, SignedContributionAndProof, SignedRoot, SignedVoluntaryExit, + SigningData, Slot, SyncAggregate, SyncAggregatorSelectionData, Unsigned, }; pub type Result = std::result::Result; @@ -664,37 +664,3 @@ where message, ))) } - -/// Returns two signature sets, one for the source and one for the target validator -/// in the `SignedConsolidation`. -pub fn consolidation_signature_set<'a, E, F>( - state: &'a BeaconState, - get_pubkey: F, - consolidation: &'a SignedConsolidation, - spec: &'a ChainSpec, -) -> Result> -where - E: EthSpec, - F: Fn(usize) -> Option>, -{ - let source_index = consolidation.message.source_index as usize; - let target_index = consolidation.message.target_index as usize; - - let domain = spec.compute_domain( - Domain::Consolidation, - spec.genesis_fork_version, - state.genesis_validators_root(), - ); - - let message = consolidation.message.signing_root(domain); - let source_pubkey = - get_pubkey(source_index).ok_or(Error::ValidatorUnknown(source_index as u64))?; - let target_pubkey = - get_pubkey(target_index).ok_or(Error::ValidatorUnknown(target_index as u64))?; - - Ok(SignatureSet::multiple_pubkeys( - &consolidation.signature, - vec![source_pubkey, target_pubkey], - message, - )) -} diff --git a/consensus/state_processing/src/per_epoch_processing/single_pass.rs b/consensus/state_processing/src/per_epoch_processing/single_pass.rs index 514cf639360..b604d621e22 100644 --- a/consensus/state_processing/src/per_epoch_processing/single_pass.rs +++ b/consensus/state_processing/src/per_epoch_processing/single_pass.rs @@ -17,8 +17,8 @@ use types::{ }, milhouse::Cow, ActivationQueue, BeaconState, BeaconStateError, ChainSpec, Checkpoint, Epoch, EthSpec, - ExitCache, ForkName, List, ParticipationFlags, ProgressiveBalancesCache, RelativeEpoch, - Unsigned, Validator, + ExitCache, ForkName, List, ParticipationFlags, PendingBalanceDeposit, ProgressiveBalancesCache, + RelativeEpoch, Unsigned, Validator, }; pub struct SinglePassConfig { @@ -91,6 +91,8 @@ struct PendingBalanceDepositsContext { deposit_balance_to_consume: u64, /// Total balance increases for each validator due to pending balance deposits. validator_deposits_to_process: HashMap, + /// The deposits to append to `pending_balance_deposits` after processing all applicable deposits. + deposits_to_postpone: Vec, } struct EffectiveBalancesContext { @@ -342,12 +344,15 @@ pub fn process_epoch_single_pass( // of the `pending_balance_deposits` list. But we may as well preserve the write ordering used // by the spec and do this first. if let Some(ctxt) = pending_balance_deposits_ctxt { - let new_pending_balance_deposits = List::try_from_iter( + let mut new_pending_balance_deposits = List::try_from_iter( state .pending_balance_deposits()? .iter_from(ctxt.next_deposit_index)? .cloned(), )?; + for deposit in ctxt.deposits_to_postpone { + new_pending_balance_deposits.push(deposit)?; + } *state.pending_balance_deposits_mut()? = new_pending_balance_deposits; *state.deposit_balance_to_consume_mut()? = ctxt.deposit_balance_to_consume; } @@ -805,22 +810,57 @@ impl PendingBalanceDepositsContext { let available_for_processing = state .deposit_balance_to_consume()? .safe_add(state.get_activation_exit_churn_limit(spec)?)?; + let current_epoch = state.current_epoch(); let mut processed_amount = 0; let mut next_deposit_index = 0; let mut validator_deposits_to_process = HashMap::new(); + let mut deposits_to_postpone = vec![]; let pending_balance_deposits = state.pending_balance_deposits()?; for deposit in pending_balance_deposits.iter() { - if processed_amount.safe_add(deposit.amount)? > available_for_processing { - break; + // We have to do a bit of indexing into `validators` here, but I can't see any way + // around that without changing the spec. + // + // We need to work out if `validator.exit_epoch` will be set to a non-default value + // *after* changes applied by `process_registry_updates`, which in our implementation + // does not happen until after this (but in the spec happens before). However it's not + // hard to work out: we don't need to know exactly what value the `exit_epoch` will + // take, just whether it is non-default. Nor do we need to know the value of + // `withdrawable_epoch`, because `current_epoch <= withdrawable_epoch` will evaluate to + // `true` both for the actual value & the default placeholder value (`FAR_FUTURE_EPOCH`). + let validator = state.get_validator(deposit.index as usize)?; + let already_exited = validator.exit_epoch < spec.far_future_epoch; + // In the spec process_registry_updates is called before process_pending_balance_deposits + // so we must account for process_registry_updates ejecting the validator for low balance + // and setting the exit_epoch to < far_future_epoch + let will_be_exited = validator.is_active_at(current_epoch) + && validator.effective_balance <= spec.ejection_balance; + if already_exited || will_be_exited { + if state.current_epoch() <= validator.withdrawable_epoch { + deposits_to_postpone.push(deposit.clone()); + } else { + // Deposited balance will never become active. Increase balance but do not + // consume churn. + validator_deposits_to_process + .entry(deposit.index as usize) + .or_insert(0) + .safe_add_assign(deposit.amount)?; + } + } else { + // Deposit does not fit in the churn, no more deposit processing in this epoch. + if processed_amount.safe_add(deposit.amount)? > available_for_processing { + break; + } + // Deposit fits in the churn, process it. Increase balance and consume churn. + validator_deposits_to_process + .entry(deposit.index as usize) + .or_insert(0) + .safe_add_assign(deposit.amount)?; + processed_amount.safe_add_assign(deposit.amount)?; } - validator_deposits_to_process - .entry(deposit.index as usize) - .or_insert(0) - .safe_add_assign(deposit.amount)?; - processed_amount.safe_add_assign(deposit.amount)?; + // Regardless of how the deposit was handled, we move on in the queue. next_deposit_index.safe_add_assign(1)?; } @@ -834,6 +874,7 @@ impl PendingBalanceDepositsContext { next_deposit_index, deposit_balance_to_consume, validator_deposits_to_process, + deposits_to_postpone, }) } } diff --git a/consensus/types/presets/gnosis/electra.yaml b/consensus/types/presets/gnosis/electra.yaml index 38f6960bac8..660ed9b64cf 100644 --- a/consensus/types/presets/gnosis/electra.yaml +++ b/consensus/types/presets/gnosis/electra.yaml @@ -30,7 +30,7 @@ MAX_ATTESTER_SLASHINGS_ELECTRA: 1 # `uint64(2**3)` (= 8) MAX_ATTESTATIONS_ELECTRA: 8 # `uint64(2**0)` (= 1) -MAX_CONSOLIDATIONS: 1 +MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1 # Execution # --------------------------------------------------------------- diff --git a/consensus/types/presets/mainnet/electra.yaml b/consensus/types/presets/mainnet/electra.yaml index 38f6960bac8..660ed9b64cf 100644 --- a/consensus/types/presets/mainnet/electra.yaml +++ b/consensus/types/presets/mainnet/electra.yaml @@ -30,7 +30,7 @@ MAX_ATTESTER_SLASHINGS_ELECTRA: 1 # `uint64(2**3)` (= 8) MAX_ATTESTATIONS_ELECTRA: 8 # `uint64(2**0)` (= 1) -MAX_CONSOLIDATIONS: 1 +MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1 # Execution # --------------------------------------------------------------- diff --git a/consensus/types/presets/minimal/electra.yaml b/consensus/types/presets/minimal/electra.yaml index cf726e004b1..ef1ce494d8e 100644 --- a/consensus/types/presets/minimal/electra.yaml +++ b/consensus/types/presets/minimal/electra.yaml @@ -30,7 +30,7 @@ MAX_ATTESTER_SLASHINGS_ELECTRA: 1 # `uint64(2**3)` (= 8) MAX_ATTESTATIONS_ELECTRA: 8 # `uint64(2**0)` (= 1) -MAX_CONSOLIDATIONS: 1 +MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: 1 # Execution # --------------------------------------------------------------- diff --git a/consensus/types/src/attestation.rs b/consensus/types/src/attestation.rs index 7b53a98caa1..b8aa2560329 100644 --- a/consensus/types/src/attestation.rs +++ b/consensus/types/src/attestation.rs @@ -77,9 +77,9 @@ pub struct Attestation { #[superstruct(only(Electra), partial_getter(rename = "aggregation_bits_electra"))] pub aggregation_bits: BitList, pub data: AttestationData, + pub signature: AggregateSignature, #[superstruct(only(Electra))] pub committee_bits: BitVector, - pub signature: AggregateSignature, } impl Hash for Attestation { diff --git a/consensus/types/src/beacon_block.rs b/consensus/types/src/beacon_block.rs index f67a965955c..300faf32f22 100644 --- a/consensus/types/src/beacon_block.rs +++ b/consensus/types/src/beacon_block.rs @@ -670,7 +670,6 @@ impl> BeaconBlockElectra graffiti: Graffiti::default(), execution_payload: Payload::Electra::default(), blob_kzg_commitments: VariableList::empty(), - consolidations: VariableList::empty(), }, } } @@ -701,7 +700,6 @@ impl> EmptyBlock for BeaconBlockElec execution_payload: Payload::Electra::default(), bls_to_execution_changes: VariableList::empty(), blob_kzg_commitments: VariableList::empty(), - consolidations: VariableList::empty(), }, } } diff --git a/consensus/types/src/beacon_block_body.rs b/consensus/types/src/beacon_block_body.rs index 373e165e0bb..305ef105445 100644 --- a/consensus/types/src/beacon_block_body.rs +++ b/consensus/types/src/beacon_block_body.rs @@ -114,8 +114,6 @@ pub struct BeaconBlockBody = FullPay VariableList, #[superstruct(only(Deneb, Electra))] pub blob_kzg_commitments: KzgCommitments, - #[superstruct(only(Electra))] - pub consolidations: VariableList, #[superstruct(only(Base, Altair))] #[metastruct(exclude_from(fields))] #[ssz(skip_serializing, skip_deserializing)] @@ -664,7 +662,6 @@ impl From>> execution_payload: FullPayloadElectra { execution_payload }, bls_to_execution_changes, blob_kzg_commitments, - consolidations, } = body; ( @@ -683,7 +680,6 @@ impl From>> }, bls_to_execution_changes, blob_kzg_commitments: blob_kzg_commitments.clone(), - consolidations, }, Some(execution_payload), ) @@ -822,7 +818,6 @@ impl BeaconBlockBodyElectra> { execution_payload: FullPayloadElectra { execution_payload }, bls_to_execution_changes, blob_kzg_commitments, - consolidations, } = self; BeaconBlockBodyElectra { @@ -840,7 +835,6 @@ impl BeaconBlockBodyElectra> { }, bls_to_execution_changes: bls_to_execution_changes.clone(), blob_kzg_commitments: blob_kzg_commitments.clone(), - consolidations: consolidations.clone(), } } } diff --git a/consensus/types/src/beacon_state.rs b/consensus/types/src/beacon_state.rs index 054e5dbe271..b8ebe101205 100644 --- a/consensus/types/src/beacon_state.rs +++ b/consensus/types/src/beacon_state.rs @@ -486,11 +486,7 @@ where // Electra #[superstruct(only(Electra), partial_getter(copy))] #[metastruct(exclude_from(tree_lists))] - #[serde( - with = "serde_utils::quoted_u64", - //TODO(electra) remove alias when ef tests are updated - alias = "deposit_receipts_start_index" - )] + #[serde(with = "serde_utils::quoted_u64")] pub deposit_requests_start_index: u64, #[superstruct(only(Electra), partial_getter(copy))] #[metastruct(exclude_from(tree_lists))] @@ -897,6 +893,8 @@ impl BeaconState { return Err(Error::InsufficientValidators); } + let max_effective_balance = spec.max_effective_balance_for_fork(self.fork_name_unchecked()); + let mut i = 0; loop { let shuffled_index = compute_shuffled_index( @@ -912,9 +910,7 @@ impl BeaconState { let random_byte = Self::shuffling_random_byte(i, seed)?; let effective_balance = self.get_effective_balance(candidate_index)?; if effective_balance.safe_mul(MAX_RANDOM_BYTE)? - >= spec - .max_effective_balance - .safe_mul(u64::from(random_byte))? + >= max_effective_balance.safe_mul(u64::from(random_byte))? { return Ok(candidate_index); } @@ -1095,6 +1091,7 @@ impl BeaconState { let active_validator_count = active_validator_indices.len(); let seed = self.get_seed(epoch, Domain::SyncCommittee, spec)?; + let max_effective_balance = spec.max_effective_balance_for_fork(self.fork_name_unchecked()); let mut i = 0; let mut sync_committee_indices = Vec::with_capacity(E::SyncCommitteeSize::to_usize()); @@ -1112,9 +1109,7 @@ impl BeaconState { let random_byte = Self::shuffling_random_byte(i, seed.as_bytes())?; let effective_balance = self.get_validator(candidate_index)?.effective_balance; if effective_balance.safe_mul(MAX_RANDOM_BYTE)? - >= spec - .max_effective_balance - .safe_mul(u64::from(random_byte))? + >= max_effective_balance.safe_mul(u64::from(random_byte))? { sync_committee_indices.push(candidate_index); } diff --git a/consensus/types/src/consolidation.rs b/consensus/types/src/consolidation.rs deleted file mode 100644 index 6cc4aa90f27..00000000000 --- a/consensus/types/src/consolidation.rs +++ /dev/null @@ -1,37 +0,0 @@ -use crate::Epoch; -use crate::{test_utils::TestRandom, SignedRoot}; -use serde::{Deserialize, Serialize}; -use ssz_derive::{Decode, Encode}; -use test_random_derive::TestRandom; -use tree_hash_derive::TreeHash; - -#[derive( - arbitrary::Arbitrary, - Debug, - PartialEq, - Eq, - Hash, - Clone, - Serialize, - Deserialize, - Encode, - Decode, - TreeHash, - TestRandom, -)] -pub struct Consolidation { - #[serde(with = "serde_utils::quoted_u64")] - pub source_index: u64, - #[serde(with = "serde_utils::quoted_u64")] - pub target_index: u64, - pub epoch: Epoch, -} - -impl SignedRoot for Consolidation {} - -#[cfg(test)] -mod tests { - use super::*; - - ssz_and_tree_hash_tests!(Consolidation); -} diff --git a/consensus/types/src/signed_consolidation.rs b/consensus/types/src/consolidation_request.rs similarity index 53% rename from consensus/types/src/signed_consolidation.rs rename to consensus/types/src/consolidation_request.rs index f004ec23bd4..b21f34e7bba 100644 --- a/consensus/types/src/signed_consolidation.rs +++ b/consensus/types/src/consolidation_request.rs @@ -1,5 +1,4 @@ -use crate::test_utils::TestRandom; -use crate::{Consolidation, Signature}; +use crate::{test_utils::TestRandom, Address, PublicKeyBytes, SignedRoot}; use serde::{Deserialize, Serialize}; use ssz_derive::{Decode, Encode}; use test_random_derive::TestRandom; @@ -19,14 +18,17 @@ use tree_hash_derive::TreeHash; TreeHash, TestRandom, )] -pub struct SignedConsolidation { - pub message: Consolidation, - pub signature: Signature, +pub struct ConsolidationRequest { + pub source_address: Address, + pub source_pubkey: PublicKeyBytes, + pub target_pubkey: PublicKeyBytes, } +impl SignedRoot for ConsolidationRequest {} + #[cfg(test)] mod tests { use super::*; - ssz_and_tree_hash_tests!(SignedConsolidation); + ssz_and_tree_hash_tests!(ConsolidationRequest); } diff --git a/consensus/types/src/eth_spec.rs b/consensus/types/src/eth_spec.rs index 15084cb14c4..09ef8e3c1a7 100644 --- a/consensus/types/src/eth_spec.rs +++ b/consensus/types/src/eth_spec.rs @@ -154,7 +154,7 @@ pub trait EthSpec: type PendingBalanceDepositsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq; type PendingPartialWithdrawalsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq; type PendingConsolidationsLimit: Unsigned + Clone + Sync + Send + Debug + PartialEq; - type MaxConsolidations: Unsigned + Clone + Sync + Send + Debug + PartialEq; + type MaxConsolidationRequestsPerPayload: Unsigned + Clone + Sync + Send + Debug + PartialEq; type MaxDepositRequestsPerPayload: Unsigned + Clone + Sync + Send + Debug + PartialEq; type MaxAttesterSlashingsElectra: Unsigned + Clone + Sync + Send + Debug + PartialEq; type MaxAttestationsElectra: Unsigned + Clone + Sync + Send + Debug + PartialEq; @@ -346,9 +346,9 @@ pub trait EthSpec: Self::PendingConsolidationsLimit::to_usize() } - /// Returns the `MAX_CONSOLIDATIONS` constant for this specification. - fn max_consolidations() -> usize { - Self::MaxConsolidations::to_usize() + /// Returns the `MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD` constant for this specification. + fn max_consolidation_requests_per_payload() -> usize { + Self::MaxConsolidationRequestsPerPayload::to_usize() } /// Returns the `MAX_DEPOSIT_REQUESTS_PER_PAYLOAD` constant for this specification. @@ -433,7 +433,7 @@ impl EthSpec for MainnetEthSpec { type PendingBalanceDepositsLimit = U134217728; type PendingPartialWithdrawalsLimit = U134217728; type PendingConsolidationsLimit = U262144; - type MaxConsolidations = U1; + type MaxConsolidationRequestsPerPayload = U1; type MaxDepositRequestsPerPayload = U8192; type MaxAttesterSlashingsElectra = U1; type MaxAttestationsElectra = U8; @@ -501,7 +501,7 @@ impl EthSpec for MinimalEthSpec { MaxBlobsPerBlock, BytesPerFieldElement, PendingBalanceDepositsLimit, - MaxConsolidations, + MaxConsolidationRequestsPerPayload, MaxAttesterSlashingsElectra, MaxAttestationsElectra }); @@ -560,7 +560,7 @@ impl EthSpec for GnosisEthSpec { type PendingBalanceDepositsLimit = U134217728; type PendingPartialWithdrawalsLimit = U134217728; type PendingConsolidationsLimit = U262144; - type MaxConsolidations = U1; + type MaxConsolidationRequestsPerPayload = U1; type MaxDepositRequestsPerPayload = U8192; type MaxAttesterSlashingsElectra = U1; type MaxAttestationsElectra = U8; diff --git a/consensus/types/src/execution_payload.rs b/consensus/types/src/execution_payload.rs index 02300cc1927..90940fbb9b9 100644 --- a/consensus/types/src/execution_payload.rs +++ b/consensus/types/src/execution_payload.rs @@ -16,7 +16,9 @@ pub type Withdrawals = VariableList::MaxWithdrawal pub type DepositRequests = VariableList::MaxDepositRequestsPerPayload>; pub type WithdrawalRequests = - VariableList::MaxWithdrawalRequestsPerPayload>; + VariableList::MaxWithdrawalRequestsPerPayload>; +pub type ConsolidationRequests = + VariableList::MaxConsolidationRequestsPerPayload>; #[superstruct( variants(Bellatrix, Capella, Deneb, Electra), @@ -94,12 +96,12 @@ pub struct ExecutionPayload { #[serde(with = "serde_utils::quoted_u64")] pub excess_blob_gas: u64, #[superstruct(only(Electra))] - //TODO(electra) remove alias once EF tests are updates with correct name - #[serde(alias = "deposit_receipts")] pub deposit_requests: VariableList, #[superstruct(only(Electra))] - pub withdrawal_requests: - VariableList, + pub withdrawal_requests: VariableList, + #[superstruct(only(Electra))] + pub consolidation_requests: + VariableList, } impl<'a, E: EthSpec> ExecutionPayloadRef<'a, E> { diff --git a/consensus/types/src/execution_payload_header.rs b/consensus/types/src/execution_payload_header.rs index 149cc286ae9..28bbfb9c048 100644 --- a/consensus/types/src/execution_payload_header.rs +++ b/consensus/types/src/execution_payload_header.rs @@ -86,11 +86,11 @@ pub struct ExecutionPayloadHeader { #[serde(with = "serde_utils::quoted_u64")] pub excess_blob_gas: u64, #[superstruct(only(Electra), partial_getter(copy))] - //TODO(electra) remove alias once EF tests are updates with correct name - #[serde(alias = "deposit_receipts_root")] pub deposit_requests_root: Hash256, #[superstruct(only(Electra), partial_getter(copy))] pub withdrawal_requests_root: Hash256, + #[superstruct(only(Electra), partial_getter(copy))] + pub consolidation_requests_root: Hash256, } impl ExecutionPayloadHeader { @@ -127,6 +127,15 @@ impl ExecutionPayloadHeader { } } } + + pub fn fork_name_unchecked(&self) -> ForkName { + match self { + ExecutionPayloadHeader::Bellatrix(_) => ForkName::Bellatrix, + ExecutionPayloadHeader::Capella(_) => ForkName::Capella, + ExecutionPayloadHeader::Deneb(_) => ForkName::Deneb, + ExecutionPayloadHeader::Electra(_) => ForkName::Electra, + } + } } impl<'a, E: EthSpec> ExecutionPayloadHeaderRef<'a, E> { @@ -206,6 +215,7 @@ impl ExecutionPayloadHeaderDeneb { excess_blob_gas: self.excess_blob_gas, deposit_requests_root: Hash256::zero(), withdrawal_requests_root: Hash256::zero(), + consolidation_requests_root: Hash256::zero(), } } } @@ -299,6 +309,7 @@ impl<'a, E: EthSpec> From<&'a ExecutionPayloadElectra> for ExecutionPayloadHe excess_blob_gas: payload.excess_blob_gas, deposit_requests_root: payload.deposit_requests.tree_hash_root(), withdrawal_requests_root: payload.withdrawal_requests.tree_hash_root(), + consolidation_requests_root: payload.consolidation_requests.tree_hash_root(), } } } diff --git a/consensus/types/src/lib.rs b/consensus/types/src/lib.rs index 2afd7261102..2b874be4825 100644 --- a/consensus/types/src/lib.rs +++ b/consensus/types/src/lib.rs @@ -27,7 +27,7 @@ pub mod bls_to_execution_change; pub mod builder_bid; pub mod chain_spec; pub mod checkpoint; -pub mod consolidation; +pub mod consolidation_request; pub mod consts; pub mod contribution_and_proof; pub mod deposit; @@ -39,7 +39,6 @@ pub mod enr_fork_id; pub mod eth1_data; pub mod eth_spec; pub mod execution_block_hash; -pub mod execution_layer_withdrawal_request; pub mod execution_payload; pub mod execution_payload_header; pub mod fork; @@ -67,7 +66,6 @@ pub mod signed_aggregate_and_proof; pub mod signed_beacon_block; pub mod signed_beacon_block_header; pub mod signed_bls_to_execution_change; -pub mod signed_consolidation; pub mod signed_contribution_and_proof; pub mod signed_voluntary_exit; pub mod signing_data; @@ -77,6 +75,7 @@ pub mod validator; pub mod validator_subscription; pub mod voluntary_exit; pub mod withdrawal_credentials; +pub mod withdrawal_request; #[macro_use] pub mod slot_epoch_macros; pub mod activation_queue; @@ -146,7 +145,7 @@ pub use crate::checkpoint::Checkpoint; pub use crate::config_and_preset::{ ConfigAndPreset, ConfigAndPresetCapella, ConfigAndPresetDeneb, ConfigAndPresetElectra, }; -pub use crate::consolidation::Consolidation; +pub use crate::consolidation_request::ConsolidationRequest; pub use crate::contribution_and_proof::ContributionAndProof; pub use crate::data_column_sidecar::{ ColumnIndex, DataColumnIdentifier, DataColumnSidecar, DataColumnSidecarList, @@ -163,7 +162,6 @@ pub use crate::eth1_data::Eth1Data; pub use crate::eth_spec::EthSpecId; pub use crate::execution_block_hash::ExecutionBlockHash; pub use crate::execution_block_header::{EncodableExecutionBlockHeader, ExecutionBlockHeader}; -pub use crate::execution_layer_withdrawal_request::ExecutionLayerWithdrawalRequest; pub use crate::execution_payload::{ ExecutionPayload, ExecutionPayloadBellatrix, ExecutionPayloadCapella, ExecutionPayloadDeneb, ExecutionPayloadElectra, ExecutionPayloadRef, Transaction, Transactions, Withdrawals, @@ -235,7 +233,6 @@ pub use crate::signed_beacon_block::{ }; pub use crate::signed_beacon_block_header::SignedBeaconBlockHeader; pub use crate::signed_bls_to_execution_change::SignedBlsToExecutionChange; -pub use crate::signed_consolidation::SignedConsolidation; pub use crate::signed_contribution_and_proof::SignedContributionAndProof; pub use crate::signed_voluntary_exit::SignedVoluntaryExit; pub use crate::signing_data::{SignedRoot, SigningData}; @@ -256,6 +253,7 @@ pub use crate::validator_subscription::ValidatorSubscription; pub use crate::voluntary_exit::VoluntaryExit; pub use crate::withdrawal::Withdrawal; pub use crate::withdrawal_credentials::WithdrawalCredentials; +pub use crate::withdrawal_request::WithdrawalRequest; pub type CommitteeIndex = u64; pub type Hash256 = H256; diff --git a/consensus/types/src/payload.rs b/consensus/types/src/payload.rs index 362cb6d3864..cee8b8cc219 100644 --- a/consensus/types/src/payload.rs +++ b/consensus/types/src/payload.rs @@ -41,13 +41,16 @@ pub trait ExecPayload: Debug + Clone + PartialEq + Hash + TreeHash + fn blob_gas_used(&self) -> Result; fn withdrawal_requests( &self, - ) -> Result< - Option>, - Error, - >; + ) -> Result>, Error>; fn deposit_requests( &self, ) -> Result>, Error>; + fn consolidation_requests( + &self, + ) -> Result< + Option>, + Error, + >; /// Is this a default payload with 0x0 roots for transactions and withdrawals? fn is_default_with_zero_roots(&self) -> bool; @@ -289,10 +292,8 @@ impl ExecPayload for FullPayload { fn withdrawal_requests( &self, - ) -> Result< - Option>, - Error, - > { + ) -> Result>, Error> + { match self { FullPayload::Bellatrix(_) | FullPayload::Capella(_) | FullPayload::Deneb(_) => { Err(Error::IncorrectStateVariant) @@ -316,6 +317,24 @@ impl ExecPayload for FullPayload { } } + fn consolidation_requests( + &self, + ) -> Result< + Option< + VariableList::MaxConsolidationRequestsPerPayload>, + >, + Error, + > { + match self { + FullPayload::Bellatrix(_) | FullPayload::Capella(_) | FullPayload::Deneb(_) => { + Err(Error::IncorrectStateVariant) + } + FullPayload::Electra(inner) => { + Ok(Some(inner.execution_payload.consolidation_requests.clone())) + } + } + } + fn is_default_with_zero_roots<'a>(&'a self) -> bool { map_full_payload_ref!(&'a _, self.to_ref(), move |payload, cons| { cons(payload); @@ -450,10 +469,8 @@ impl<'b, E: EthSpec> ExecPayload for FullPayloadRef<'b, E> { fn withdrawal_requests( &self, - ) -> Result< - Option>, - Error, - > { + ) -> Result>, Error> + { match self { FullPayloadRef::Bellatrix(_) | FullPayloadRef::Capella(_) @@ -477,6 +494,24 @@ impl<'b, E: EthSpec> ExecPayload for FullPayloadRef<'b, E> { } } + fn consolidation_requests( + &self, + ) -> Result< + Option< + VariableList::MaxConsolidationRequestsPerPayload>, + >, + Error, + > { + match self { + FullPayloadRef::Bellatrix(_) + | FullPayloadRef::Capella(_) + | FullPayloadRef::Deneb(_) => Err(Error::IncorrectStateVariant), + FullPayloadRef::Electra(inner) => { + Ok(Some(inner.execution_payload.consolidation_requests.clone())) + } + } + } + fn is_default_with_zero_roots<'a>(&'a self) -> bool { map_full_payload_ref!(&'a _, self, move |payload, cons| { cons(payload); @@ -659,10 +694,8 @@ impl ExecPayload for BlindedPayload { fn withdrawal_requests( &self, - ) -> Result< - Option>, - Error, - > { + ) -> Result>, Error> + { Ok(None) } @@ -672,6 +705,17 @@ impl ExecPayload for BlindedPayload { Ok(None) } + fn consolidation_requests( + &self, + ) -> Result< + Option< + VariableList::MaxConsolidationRequestsPerPayload>, + >, + Error, + > { + Ok(None) + } + fn is_default_with_zero_roots(&self) -> bool { self.to_ref().is_default_with_zero_roots() } @@ -775,10 +819,8 @@ impl<'b, E: EthSpec> ExecPayload for BlindedPayloadRef<'b, E> { fn withdrawal_requests( &self, - ) -> Result< - Option>, - Error, - > { + ) -> Result>, Error> + { Ok(None) } @@ -788,6 +830,17 @@ impl<'b, E: EthSpec> ExecPayload for BlindedPayloadRef<'b, E> { Ok(None) } + fn consolidation_requests( + &self, + ) -> Result< + Option< + VariableList::MaxConsolidationRequestsPerPayload>, + >, + Error, + > { + Ok(None) + } + fn is_default_with_zero_roots<'a>(&'a self) -> bool { map_blinded_payload_ref!(&'b _, self, move |payload, cons| { cons(payload); @@ -816,7 +869,8 @@ macro_rules! impl_exec_payload_common { $g:block, $h:block, $i:block, - $j:block) => { + $j:block, + $k:block) => { impl ExecPayload for $wrapper_type { fn block_type() -> BlockType { BlockType::$block_type_variant @@ -883,7 +937,7 @@ macro_rules! impl_exec_payload_common { fn withdrawal_requests( &self, ) -> Result< - Option>, + Option>, Error, > { let i = $i; @@ -896,6 +950,13 @@ macro_rules! impl_exec_payload_common { let j = $j; j(self) } + + fn consolidation_requests( + &self, + ) -> Result::MaxConsolidationRequestsPerPayload>>, Error> { + let k = $k; + k(self) + } } impl From<$wrapped_type> for $wrapper_type { @@ -943,6 +1004,7 @@ macro_rules! impl_exec_payload_for_fork { c }, { |_| { Ok(None) } }, + { |_| { Ok(None) } }, { |_| { Ok(None) } } ); @@ -1035,12 +1097,7 @@ macro_rules! impl_exec_payload_for_fork { let c: for<'a> fn( &'a $wrapper_type_full, ) -> Result< - Option< - VariableList< - ExecutionLayerWithdrawalRequest, - E::MaxWithdrawalRequestsPerPayload, - >, - >, + Option>, Error, > = |payload: &$wrapper_type_full| { let wrapper_ref_type = FullPayloadRef::$fork_variant(&payload); @@ -1059,6 +1116,23 @@ macro_rules! impl_exec_payload_for_fork { wrapper_ref_type.deposit_requests() }; c + }, + { + let c: for<'a> fn( + &'a $wrapper_type_full, + ) -> Result< + Option< + VariableList< + ConsolidationRequest, + ::MaxConsolidationRequestsPerPayload, + >, + >, + Error, + > = |payload: &$wrapper_type_full| { + let wrapper_ref_type = FullPayloadRef::$fork_variant(&payload); + wrapper_ref_type.consolidation_requests() + }; + c } ); diff --git a/consensus/types/src/preset.rs b/consensus/types/src/preset.rs index b51928d165e..2c576ed332c 100644 --- a/consensus/types/src/preset.rs +++ b/consensus/types/src/preset.rs @@ -246,7 +246,7 @@ pub struct ElectraPreset { #[serde(with = "serde_utils::quoted_u64")] pub pending_consolidations_limit: u64, #[serde(with = "serde_utils::quoted_u64")] - pub max_consolidations: u64, + pub max_consolidation_requests_per_payload: u64, #[serde(with = "serde_utils::quoted_u64")] pub max_deposit_requests_per_payload: u64, #[serde(with = "serde_utils::quoted_u64")] @@ -269,7 +269,8 @@ impl ElectraPreset { pending_balance_deposits_limit: E::pending_balance_deposits_limit() as u64, pending_partial_withdrawals_limit: E::pending_partial_withdrawals_limit() as u64, pending_consolidations_limit: E::pending_consolidations_limit() as u64, - max_consolidations: E::max_consolidations() as u64, + max_consolidation_requests_per_payload: E::max_consolidation_requests_per_payload() + as u64, max_deposit_requests_per_payload: E::max_deposit_requests_per_payload() as u64, max_attester_slashings_electra: E::max_attester_slashings_electra() as u64, max_attestations_electra: E::max_attestations_electra() as u64, diff --git a/consensus/types/src/signed_beacon_block.rs b/consensus/types/src/signed_beacon_block.rs index a22df49ad7b..4d3279a7f77 100644 --- a/consensus/types/src/signed_beacon_block.rs +++ b/consensus/types/src/signed_beacon_block.rs @@ -498,7 +498,6 @@ impl SignedBeaconBlockElectra> { execution_payload: BlindedPayloadElectra { .. }, bls_to_execution_changes, blob_kzg_commitments, - consolidations, }, }, signature, @@ -522,7 +521,6 @@ impl SignedBeaconBlockElectra> { execution_payload: FullPayloadElectra { execution_payload }, bls_to_execution_changes, blob_kzg_commitments, - consolidations, }, }, signature, diff --git a/consensus/types/src/validator.rs b/consensus/types/src/validator.rs index b5e92d1f5d8..4173e18526e 100644 --- a/consensus/types/src/validator.rs +++ b/consensus/types/src/validator.rs @@ -219,6 +219,7 @@ impl Validator { } } + /// TODO(electra): refactor these functions and make it simpler.. this is a mess /// Returns `true` if the validator is partially withdrawable. fn is_partially_withdrawable_validator_capella(&self, balance: u64, spec: &ChainSpec) -> bool { self.has_eth1_withdrawal_credential(spec) diff --git a/consensus/types/src/execution_layer_withdrawal_request.rs b/consensus/types/src/withdrawal_request.rs similarity index 84% rename from consensus/types/src/execution_layer_withdrawal_request.rs rename to consensus/types/src/withdrawal_request.rs index b1d814c2834..2f69e9b1504 100644 --- a/consensus/types/src/execution_layer_withdrawal_request.rs +++ b/consensus/types/src/withdrawal_request.rs @@ -19,7 +19,7 @@ use tree_hash_derive::TreeHash; TreeHash, TestRandom, )] -pub struct ExecutionLayerWithdrawalRequest { +pub struct WithdrawalRequest { pub source_address: Address, pub validator_pubkey: PublicKeyBytes, #[serde(with = "serde_utils::quoted_u64")] @@ -30,5 +30,5 @@ pub struct ExecutionLayerWithdrawalRequest { mod tests { use super::*; - ssz_and_tree_hash_tests!(ExecutionLayerWithdrawalRequest); + ssz_and_tree_hash_tests!(WithdrawalRequest); } diff --git a/testing/ef_tests/Makefile b/testing/ef_tests/Makefile index 5dc3d2a0404..59e08e5d259 100644 --- a/testing/ef_tests/Makefile +++ b/testing/ef_tests/Makefile @@ -1,4 +1,4 @@ -TESTS_TAG := v1.5.0-alpha.2 +TESTS_TAG := v1.5.0-alpha.3 TESTS = general minimal mainnet TARBALLS = $(patsubst %,%-$(TESTS_TAG).tar.gz,$(TESTS)) diff --git a/testing/ef_tests/check_all_files_accessed.py b/testing/ef_tests/check_all_files_accessed.py index f1ab5ad600d..d8f5b3e78dc 100755 --- a/testing/ef_tests/check_all_files_accessed.py +++ b/testing/ef_tests/check_all_files_accessed.py @@ -49,10 +49,7 @@ # TODO(electra) re-enable once https://github.com/sigp/lighthouse/issues/6002 is resolved "tests/.*/electra/ssz_static/LightClientUpdate", "tests/.*/electra/ssz_static/LightClientFinalityUpdate", - "tests/.*/electra/ssz_static/LightClientBootstrap", - # TODO(electra) re-enable as DepositRequest when EF tests are updated - "tests/.*/electra/operations/deposit_receipt", - "tests/.*/electra/ssz_static/DepositReceipt" + "tests/.*/electra/ssz_static/LightClientBootstrap" ] diff --git a/testing/ef_tests/src/cases/operations.rs b/testing/ef_tests/src/cases/operations.rs index 0af2c818271..24184441047 100644 --- a/testing/ef_tests/src/cases/operations.rs +++ b/testing/ef_tests/src/cases/operations.rs @@ -7,7 +7,7 @@ use ssz::Decode; use state_processing::common::update_progressive_balances_cache::initialize_progressive_balances_cache; use state_processing::epoch_cache::initialize_epoch_cache; use state_processing::per_block_processing::process_operations::{ - process_consolidations, process_deposit_requests, process_execution_layer_withdrawal_requests, + process_consolidation_requests, process_deposit_requests, process_withdrawal_requests, }; use state_processing::{ per_block_processing::{ @@ -25,9 +25,9 @@ use std::fmt::Debug; use types::{ Attestation, AttesterSlashing, BeaconBlock, BeaconBlockBody, BeaconBlockBodyBellatrix, BeaconBlockBodyCapella, BeaconBlockBodyDeneb, BeaconBlockBodyElectra, BeaconState, - BlindedPayload, Deposit, DepositRequest, ExecutionLayerWithdrawalRequest, ExecutionPayload, - FullPayload, ProposerSlashing, SignedBlsToExecutionChange, SignedConsolidation, - SignedVoluntaryExit, SyncAggregate, + BlindedPayload, ConsolidationRequest, Deposit, DepositRequest, ExecutionPayload, FullPayload, + ProposerSlashing, SignedBlsToExecutionChange, SignedVoluntaryExit, SyncAggregate, + WithdrawalRequest, }; #[derive(Debug, Clone, Default, Deserialize)] @@ -445,9 +445,9 @@ impl Operation for SignedBlsToExecutionChange { } } -impl Operation for ExecutionLayerWithdrawalRequest { +impl Operation for WithdrawalRequest { fn handler_name() -> String { - "execution_layer_withdrawal_request".into() + "withdrawal_request".into() } fn is_enabled_for_fork(fork_name: ForkName) -> bool { @@ -464,7 +464,8 @@ impl Operation for ExecutionLayerWithdrawalRequest { spec: &ChainSpec, _extra: &Operations, ) -> Result<(), BlockProcessingError> { - process_execution_layer_withdrawal_requests(state, &[self.clone()], spec) + state.update_pubkey_cache()?; + process_withdrawal_requests(state, &[self.clone()], spec) } } @@ -491,9 +492,9 @@ impl Operation for DepositRequest { } } -impl Operation for SignedConsolidation { +impl Operation for ConsolidationRequest { fn handler_name() -> String { - "consolidation".into() + "consolidation_request".into() } fn is_enabled_for_fork(fork_name: ForkName) -> bool { @@ -510,7 +511,8 @@ impl Operation for SignedConsolidation { spec: &ChainSpec, _extra: &Operations, ) -> Result<(), BlockProcessingError> { - process_consolidations(state, &[self.clone()], VerifySignatures::True, spec) + state.update_pubkey_cache()?; + process_consolidation_requests(state, &[self.clone()], spec) } } diff --git a/testing/ef_tests/src/type_name.rs b/testing/ef_tests/src/type_name.rs index d6ef873ead4..c61dfef09cc 100644 --- a/testing/ef_tests/src/type_name.rs +++ b/testing/ef_tests/src/type_name.rs @@ -60,14 +60,14 @@ type_name_generic!(BeaconState); type_name!(BlobIdentifier); type_name_generic!(BlobSidecar); type_name!(Checkpoint); -type_name!(Consolidation); +type_name!(ConsolidationRequest); type_name_generic!(ContributionAndProof); type_name!(Deposit); type_name!(DepositData); type_name!(DepositMessage); type_name!(DepositRequest); type_name!(Eth1Data); -type_name!(ExecutionLayerWithdrawalRequest); +type_name!(WithdrawalRequest); type_name_generic!(ExecutionPayload); type_name_generic!(ExecutionPayloadBellatrix, "ExecutionPayload"); type_name_generic!(ExecutionPayloadCapella, "ExecutionPayload"); @@ -139,7 +139,6 @@ type_name_generic!(SignedAggregateAndProofBase, "SignedAggregateAndProof"); type_name_generic!(SignedAggregateAndProofElectra, "SignedAggregateAndProof"); type_name_generic!(SignedBeaconBlock); type_name!(SignedBeaconBlockHeader); -type_name!(SignedConsolidation); type_name_generic!(SignedContributionAndProof); type_name!(SignedVoluntaryExit); type_name!(SigningData); diff --git a/testing/ef_tests/tests/tests.rs b/testing/ef_tests/tests/tests.rs index 90143850443..7f69521bb67 100644 --- a/testing/ef_tests/tests/tests.rs +++ b/testing/ef_tests/tests/tests.rs @@ -1,7 +1,7 @@ #![cfg(feature = "ef_tests")] use ef_tests::*; -use types::{ExecutionLayerWithdrawalRequest, MainnetEthSpec, MinimalEthSpec, *}; +use types::*; // Check that the hand-computed multiplications on EthSpec are correctly computed. // This test lives here because one is most likely to muck these up during a spec update. @@ -93,24 +93,22 @@ fn operations_withdrawals() { } #[test] -fn operations_execution_layer_withdrawal_reqeusts() { - OperationsHandler::::default().run(); - OperationsHandler::::default().run(); +fn operations_withdrawal_reqeusts() { + OperationsHandler::::default().run(); + OperationsHandler::::default().run(); } #[test] #[cfg(not(feature = "fake_crypto"))] fn operations_deposit_requests() { - //TODO(electra): re-enable mainnet once they update the name for this - // OperationsHandler::::default().run(); - // OperationsHandler::::default().run(); + OperationsHandler::::default().run(); + OperationsHandler::::default().run(); } #[test] fn operations_consolidations() { - OperationsHandler::::default().run(); - //TODO(electra): re-enable mainnet once they make tests for this - //OperationsHandler::::default().run(); + OperationsHandler::::default().run(); + OperationsHandler::::default().run(); } #[test] @@ -243,9 +241,9 @@ mod ssz_static { use types::blob_sidecar::BlobIdentifier; use types::historical_summary::HistoricalSummary; use types::{ - AttesterSlashingBase, AttesterSlashingElectra, Consolidation, - ExecutionLayerWithdrawalRequest, LightClientBootstrapAltair, PendingBalanceDeposit, - PendingPartialWithdrawal, *, + AttesterSlashingBase, AttesterSlashingElectra, ConsolidationRequest, DepositRequest, + LightClientBootstrapAltair, PendingBalanceDeposit, PendingPartialWithdrawal, + WithdrawalRequest, *, }; ssz_static_test!(attestation_data, AttestationData); @@ -631,23 +629,20 @@ mod ssz_static { #[test] fn consolidation() { - SszStaticHandler::::electra_and_later().run(); - SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); } - // TODO(electra) re-enable when EF tests are updated - // #[test] - // fn deposit_request() { - // SszStaticHandler::::electra_and_later().run(); - // SszStaticHandler::::electra_and_later().run(); - // } + #[test] + fn deposit_request() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); + } #[test] - fn execution_layer_withdrawal_request() { - SszStaticHandler::::electra_and_later() - .run(); - SszStaticHandler::::electra_and_later() - .run(); + fn withdrawal_request() { + SszStaticHandler::::electra_and_later().run(); + SszStaticHandler::::electra_and_later().run(); } #[test] @@ -667,12 +662,6 @@ mod ssz_static { SszStaticHandler::::electra_and_later().run(); SszStaticHandler::::electra_and_later().run(); } - - #[test] - fn signed_consolidation() { - SszStaticHandler::::electra_and_later().run(); - SszStaticHandler::::electra_and_later().run(); - } } #[test]