mirror of
https://github.com/sigp/lighthouse.git
synced 2026-03-14 10:22:38 +00:00
* 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 <micsproul@gmail.com> --------- Co-authored-by: Michael Sproul <micsproul@gmail.com> * 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 <seananderson33@GMAIL.com> * 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 commite3ce7fc5ea. * 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 <micsproul@gmail.com> * 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 <sean@sigmaprime.io> * Revert "Get `electra_op_pool` up to date (#5756)" (#5757) This reverts commitab9e58aa3d. * 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 <micsproul@gmail.com> --------- Co-authored-by: Michael Sproul <micsproul@gmail.com> * 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 <seananderson33@GMAIL.com> * 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
1393 lines
46 KiB
Rust
1393 lines
46 KiB
Rust
#![cfg(not(debug_assertions))]
|
|
|
|
use beacon_chain::test_utils::{
|
|
AttestationStrategy, BeaconChainHarness, BlockStrategy, EphemeralHarnessType,
|
|
};
|
|
use beacon_chain::{
|
|
BeaconChain, BeaconChainError, BeaconForkChoiceStore, ChainConfig, ForkChoiceError,
|
|
StateSkipConfig, WhenSlotSkipped,
|
|
};
|
|
use fork_choice::{
|
|
ForkChoiceStore, InvalidAttestation, InvalidBlock, PayloadVerificationStatus, QueuedAttestation,
|
|
};
|
|
use std::fmt;
|
|
use std::sync::Mutex;
|
|
use std::time::Duration;
|
|
use store::MemoryStore;
|
|
use types::{
|
|
test_utils::generate_deterministic_keypair, BeaconBlockRef, BeaconState, ChainSpec, Checkpoint,
|
|
Epoch, EthSpec, ForkName, Hash256, IndexedAttestation, MainnetEthSpec, RelativeEpoch,
|
|
SignedBeaconBlock, Slot, SubnetId,
|
|
};
|
|
|
|
pub type E = MainnetEthSpec;
|
|
|
|
pub const VALIDATOR_COUNT: usize = 64;
|
|
|
|
/// Defines some delay between when an attestation is created and when it is mutated.
|
|
pub enum MutationDelay {
|
|
/// No delay between creation and mutation.
|
|
NoDelay,
|
|
/// Create `n` blocks before mutating the attestation.
|
|
Blocks(usize),
|
|
}
|
|
|
|
/// A helper struct to make testing fork choice more ergonomic and less repetitive.
|
|
struct ForkChoiceTest {
|
|
harness: BeaconChainHarness<EphemeralHarnessType<E>>,
|
|
}
|
|
|
|
/// Allows us to use `unwrap` in some cases.
|
|
impl fmt::Debug for ForkChoiceTest {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
f.debug_struct("ForkChoiceTest").finish()
|
|
}
|
|
}
|
|
|
|
impl ForkChoiceTest {
|
|
/// Creates a new tester.
|
|
pub fn new() -> Self {
|
|
Self::new_with_chain_config(ChainConfig::default())
|
|
}
|
|
|
|
/// Creates a new tester with a custom chain config.
|
|
pub fn new_with_chain_config(chain_config: ChainConfig) -> Self {
|
|
// Run fork choice tests against the latest fork.
|
|
let spec = ForkName::latest().make_genesis_spec(ChainSpec::default());
|
|
let harness = BeaconChainHarness::builder(MainnetEthSpec)
|
|
.spec(spec)
|
|
.chain_config(chain_config)
|
|
.deterministic_keypairs(VALIDATOR_COUNT)
|
|
.fresh_ephemeral_store()
|
|
.mock_execution_layer()
|
|
.build();
|
|
|
|
Self { harness }
|
|
}
|
|
|
|
/// Get a value from the `ForkChoice` instantiation.
|
|
fn get<T, U>(&self, func: T) -> U
|
|
where
|
|
T: Fn(&BeaconForkChoiceStore<E, MemoryStore<E>, MemoryStore<E>>) -> U,
|
|
{
|
|
func(
|
|
self.harness
|
|
.chain
|
|
.canonical_head
|
|
.fork_choice_read_lock()
|
|
.fc_store(),
|
|
)
|
|
}
|
|
|
|
/// Assert the epochs match.
|
|
pub fn assert_finalized_epoch(self, epoch: u64) -> Self {
|
|
assert_eq!(
|
|
self.get(|fc_store| fc_store.finalized_checkpoint().epoch),
|
|
Epoch::new(epoch),
|
|
"finalized_epoch"
|
|
);
|
|
self
|
|
}
|
|
|
|
/// Assert the epochs match.
|
|
pub fn assert_justified_epoch(self, epoch: u64) -> Self {
|
|
assert_eq!(
|
|
self.get(|fc_store| fc_store.justified_checkpoint().epoch),
|
|
Epoch::new(epoch),
|
|
"justified_epoch"
|
|
);
|
|
self
|
|
}
|
|
|
|
/// Assert the given slot is greater than the head slot.
|
|
pub fn assert_finalized_epoch_is_less_than(self, epoch: Epoch) -> Self {
|
|
assert!(self.harness.finalized_checkpoint().epoch < epoch);
|
|
self
|
|
}
|
|
|
|
/// Assert there was a shutdown signal sent by the beacon chain.
|
|
pub fn shutdown_signal_sent(&self) -> bool {
|
|
let mutex = self.harness.shutdown_receiver.clone();
|
|
let mut shutdown_receiver = mutex.lock();
|
|
|
|
shutdown_receiver.close();
|
|
let msg = shutdown_receiver.try_next().unwrap();
|
|
msg.is_some()
|
|
}
|
|
|
|
/// Assert there was a shutdown signal sent by the beacon chain.
|
|
pub fn assert_shutdown_signal_sent(self) -> Self {
|
|
assert!(self.shutdown_signal_sent());
|
|
self
|
|
}
|
|
|
|
/// Assert no shutdown was signal sent by the beacon chain.
|
|
pub fn assert_shutdown_signal_not_sent(self) -> Self {
|
|
assert!(!self.shutdown_signal_sent());
|
|
self
|
|
}
|
|
|
|
/// Inspect the queued attestations in fork choice.
|
|
pub fn inspect_queued_attestations<F>(self, mut func: F) -> Self
|
|
where
|
|
F: FnMut(&[QueuedAttestation]),
|
|
{
|
|
self.harness
|
|
.chain
|
|
.canonical_head
|
|
.fork_choice_write_lock()
|
|
.update_time(self.harness.chain.slot().unwrap())
|
|
.unwrap();
|
|
func(
|
|
self.harness
|
|
.chain
|
|
.canonical_head
|
|
.fork_choice_read_lock()
|
|
.queued_attestations(),
|
|
);
|
|
self
|
|
}
|
|
|
|
/// Skip a slot, without producing a block.
|
|
pub fn skip_slot(self) -> Self {
|
|
self.harness.advance_slot();
|
|
self
|
|
}
|
|
|
|
/// Skips `count` slots, without producing a block.
|
|
pub fn skip_slots(self, count: usize) -> Self {
|
|
for _ in 0..count {
|
|
self.harness.advance_slot();
|
|
}
|
|
self
|
|
}
|
|
|
|
/// Build the chain whilst `predicate` returns `true` and `process_block_result` does not error.
|
|
pub async fn apply_blocks_while<F>(self, mut predicate: F) -> Result<Self, Self>
|
|
where
|
|
F: FnMut(BeaconBlockRef<'_, E>, &BeaconState<E>) -> bool,
|
|
{
|
|
self.harness.advance_slot();
|
|
let mut state = self.harness.get_current_state();
|
|
let validators = self.harness.get_all_validators();
|
|
loop {
|
|
let slot = self.harness.get_current_slot();
|
|
let (block_contents, state_) = self.harness.make_block(state, slot).await;
|
|
state = state_;
|
|
if !predicate(block_contents.0.message(), &state) {
|
|
break;
|
|
}
|
|
let block = block_contents.0.clone();
|
|
if let Ok(block_hash) = self.harness.process_block_result(block_contents).await {
|
|
self.harness.attest_block(
|
|
&state,
|
|
block.state_root(),
|
|
block_hash,
|
|
&block,
|
|
&validators,
|
|
);
|
|
self.harness.advance_slot();
|
|
} else {
|
|
return Err(self);
|
|
}
|
|
}
|
|
|
|
Ok(self)
|
|
}
|
|
|
|
/// Apply `count` blocks to the chain (with attestations).
|
|
pub async fn apply_blocks(self, count: usize) -> Self {
|
|
self.harness.advance_slot();
|
|
self.harness
|
|
.extend_chain(
|
|
count,
|
|
BlockStrategy::OnCanonicalHead,
|
|
AttestationStrategy::AllValidators,
|
|
)
|
|
.await;
|
|
|
|
self
|
|
}
|
|
|
|
/// Slash a validator from the previous epoch committee.
|
|
pub async fn add_previous_epoch_attester_slashing(self) -> Self {
|
|
let state = self.harness.get_current_state();
|
|
let previous_epoch_shuffling = state.get_shuffling(RelativeEpoch::Previous).unwrap();
|
|
let validator_indices = previous_epoch_shuffling
|
|
.iter()
|
|
.map(|idx| *idx as u64)
|
|
.take(1)
|
|
.collect();
|
|
|
|
self.harness
|
|
.add_attester_slashing(validator_indices)
|
|
.unwrap();
|
|
|
|
self
|
|
}
|
|
|
|
/// Slash the proposer of a block in the previous epoch.
|
|
pub async fn add_previous_epoch_proposer_slashing(self, slots_per_epoch: u64) -> Self {
|
|
let previous_epoch_slot = self.harness.get_current_slot() - slots_per_epoch;
|
|
let previous_epoch_block = self
|
|
.harness
|
|
.chain
|
|
.block_at_slot(previous_epoch_slot, WhenSlotSkipped::None)
|
|
.unwrap()
|
|
.unwrap();
|
|
let proposer_index: u64 = previous_epoch_block.message().proposer_index();
|
|
|
|
self.harness.add_proposer_slashing(proposer_index).unwrap();
|
|
|
|
self
|
|
}
|
|
|
|
/// Apply `count` blocks to the chain (without attestations).
|
|
pub async fn apply_blocks_without_new_attestations(self, count: usize) -> Self {
|
|
self.harness.advance_slot();
|
|
self.harness
|
|
.extend_chain(
|
|
count,
|
|
BlockStrategy::OnCanonicalHead,
|
|
AttestationStrategy::SomeValidators(vec![]),
|
|
)
|
|
.await;
|
|
|
|
self
|
|
}
|
|
|
|
/// Moves to the next slot that is *outside* the `SAFE_SLOTS_TO_UPDATE_JUSTIFIED` range.
|
|
///
|
|
/// If the chain is presently in an unsafe period, transition through it and the following safe
|
|
/// period.
|
|
///
|
|
/// Note: the `SAFE_SLOTS_TO_UPDATE_JUSTIFIED` variable has been removed
|
|
/// from the fork choice spec in Q1 2023. We're still leaving references to
|
|
/// it in our tests because (a) it's easier and (b) it allows us to easily
|
|
/// test for the absence of that parameter.
|
|
pub fn move_to_next_unsafe_period(self) -> Self {
|
|
self.move_inside_safe_to_update()
|
|
.move_outside_safe_to_update()
|
|
}
|
|
|
|
/// Moves to the next slot that is *outside* the `SAFE_SLOTS_TO_UPDATE_JUSTIFIED` range.
|
|
pub fn move_outside_safe_to_update(self) -> Self {
|
|
while is_safe_to_update(self.harness.chain.slot().unwrap(), &self.harness.chain.spec) {
|
|
self.harness.advance_slot()
|
|
}
|
|
self
|
|
}
|
|
|
|
/// Moves to the next slot that is *inside* the `SAFE_SLOTS_TO_UPDATE_JUSTIFIED` range.
|
|
pub fn move_inside_safe_to_update(self) -> Self {
|
|
while !is_safe_to_update(self.harness.chain.slot().unwrap(), &self.harness.chain.spec) {
|
|
self.harness.advance_slot()
|
|
}
|
|
self
|
|
}
|
|
|
|
/// Applies a block directly to fork choice, bypassing the beacon chain.
|
|
///
|
|
/// Asserts the block was applied successfully.
|
|
pub async fn apply_block_directly_to_fork_choice<F>(self, mut func: F) -> Self
|
|
where
|
|
F: FnMut(&mut SignedBeaconBlock<E>, &mut BeaconState<E>),
|
|
{
|
|
let state = self
|
|
.harness
|
|
.chain
|
|
.state_at_slot(
|
|
self.harness.get_current_slot() - 1,
|
|
StateSkipConfig::WithStateRoots,
|
|
)
|
|
.unwrap();
|
|
let slot = self.harness.get_current_slot();
|
|
let ((block_arc, _block_blobs), mut state) = self.harness.make_block(state, slot).await;
|
|
let mut block = (*block_arc).clone();
|
|
func(&mut block, &mut state);
|
|
let current_slot = self.harness.get_current_slot();
|
|
self.harness
|
|
.chain
|
|
.canonical_head
|
|
.fork_choice_write_lock()
|
|
.on_block(
|
|
current_slot,
|
|
block.message(),
|
|
block.canonical_root(),
|
|
Duration::from_secs(0),
|
|
&state,
|
|
PayloadVerificationStatus::Verified,
|
|
&self.harness.chain.spec,
|
|
)
|
|
.unwrap();
|
|
self
|
|
}
|
|
|
|
/// Applies a block directly to fork choice, bypassing the beacon chain.
|
|
///
|
|
/// Asserts that an error occurred and allows inspecting it via `comparison_func`.
|
|
pub async fn apply_invalid_block_directly_to_fork_choice<F, G>(
|
|
self,
|
|
mut mutation_func: F,
|
|
mut comparison_func: G,
|
|
) -> Self
|
|
where
|
|
F: FnMut(&mut SignedBeaconBlock<E>, &mut BeaconState<E>),
|
|
G: FnMut(ForkChoiceError),
|
|
{
|
|
let state = self
|
|
.harness
|
|
.chain
|
|
.state_at_slot(
|
|
self.harness.get_current_slot() - 1,
|
|
StateSkipConfig::WithStateRoots,
|
|
)
|
|
.unwrap();
|
|
let slot = self.harness.get_current_slot();
|
|
let ((block_arc, _block_blobs), mut state) = self.harness.make_block(state, slot).await;
|
|
let mut block = (*block_arc).clone();
|
|
mutation_func(&mut block, &mut state);
|
|
let current_slot = self.harness.get_current_slot();
|
|
let err = self
|
|
.harness
|
|
.chain
|
|
.canonical_head
|
|
.fork_choice_write_lock()
|
|
.on_block(
|
|
current_slot,
|
|
block.message(),
|
|
block.canonical_root(),
|
|
Duration::from_secs(0),
|
|
&state,
|
|
PayloadVerificationStatus::Verified,
|
|
&self.harness.chain.spec,
|
|
)
|
|
.expect_err("on_block did not return an error");
|
|
comparison_func(err);
|
|
self
|
|
}
|
|
|
|
/// Compares the justified balances in the `ForkChoiceStore` verses a direct lookup from the
|
|
/// database.
|
|
fn check_justified_balances(&self) {
|
|
let harness = &self.harness;
|
|
let fc = self.harness.chain.canonical_head.fork_choice_read_lock();
|
|
|
|
let state_root = harness
|
|
.chain
|
|
.store
|
|
.get_blinded_block(&fc.fc_store().justified_checkpoint().root)
|
|
.unwrap()
|
|
.unwrap()
|
|
.message()
|
|
.state_root();
|
|
let state = harness
|
|
.chain
|
|
.store
|
|
.get_state(&state_root, None)
|
|
.unwrap()
|
|
.unwrap();
|
|
let balances = state
|
|
.validators()
|
|
.into_iter()
|
|
.map(|v| {
|
|
if v.is_active_at(state.current_epoch()) {
|
|
v.effective_balance
|
|
} else {
|
|
0
|
|
}
|
|
})
|
|
.collect::<Vec<_>>();
|
|
|
|
assert_eq!(
|
|
&balances[..],
|
|
&fc.fc_store().justified_balances().effective_balances,
|
|
"balances should match"
|
|
);
|
|
assert_eq!(
|
|
balances.iter().sum::<u64>(),
|
|
fc.fc_store().justified_balances().total_effective_balance
|
|
);
|
|
}
|
|
|
|
/// Returns an attestation that is valid for some slot in the given `chain`.
|
|
///
|
|
/// Also returns some info about who created it.
|
|
async fn apply_attestation_to_chain<F, G>(
|
|
self,
|
|
delay: MutationDelay,
|
|
mut mutation_func: F,
|
|
mut comparison_func: G,
|
|
) -> Self
|
|
where
|
|
F: FnMut(&mut IndexedAttestation<E>, &BeaconChain<EphemeralHarnessType<E>>),
|
|
G: FnMut(Result<(), BeaconChainError>),
|
|
{
|
|
let head = self.harness.chain.head_snapshot();
|
|
let current_slot = self.harness.chain.slot().expect("should get slot");
|
|
|
|
let mut attestation = self
|
|
.harness
|
|
.chain
|
|
.produce_unaggregated_attestation(current_slot, 0)
|
|
.expect("should not error while producing attestation");
|
|
|
|
let validator_committee_index = 0;
|
|
let validator_index = *head
|
|
.beacon_state
|
|
.get_beacon_committee(
|
|
current_slot,
|
|
attestation
|
|
.committee_index()
|
|
.expect("should get committee index"),
|
|
)
|
|
.expect("should get committees")
|
|
.committee
|
|
.get(validator_committee_index)
|
|
.expect("there should be an attesting validator");
|
|
|
|
let committee_count = head
|
|
.beacon_state
|
|
.get_committee_count_at_slot(current_slot)
|
|
.expect("should not error while getting committee count");
|
|
|
|
let subnet_id = SubnetId::compute_subnet::<E>(
|
|
current_slot,
|
|
0,
|
|
committee_count,
|
|
&self.harness.chain.spec,
|
|
)
|
|
.expect("should compute subnet id");
|
|
|
|
let validator_sk = generate_deterministic_keypair(validator_index).sk;
|
|
|
|
attestation
|
|
.sign(
|
|
&validator_sk,
|
|
validator_committee_index,
|
|
&head.beacon_state.fork(),
|
|
self.harness.chain.genesis_validators_root,
|
|
&self.harness.chain.spec,
|
|
)
|
|
.expect("should sign attestation");
|
|
|
|
let mut verified_attestation = self
|
|
.harness
|
|
.chain
|
|
.verify_unaggregated_attestation_for_gossip(&attestation, Some(subnet_id))
|
|
.expect("precondition: should gossip verify attestation");
|
|
|
|
if let MutationDelay::Blocks(slots) = delay {
|
|
self.harness.advance_slot();
|
|
self.harness
|
|
.extend_chain(
|
|
slots,
|
|
BlockStrategy::OnCanonicalHead,
|
|
AttestationStrategy::SomeValidators(vec![]),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
mutation_func(
|
|
verified_attestation.__indexed_attestation_mut(),
|
|
&self.harness.chain,
|
|
);
|
|
|
|
let result = self
|
|
.harness
|
|
.chain
|
|
.apply_attestation_to_fork_choice(&verified_attestation);
|
|
|
|
comparison_func(result);
|
|
|
|
self
|
|
}
|
|
|
|
/// Check to ensure that we can read the finalized block. This is a regression test.
|
|
pub fn check_finalized_block_is_accessible(self) -> Self {
|
|
self.harness
|
|
.chain
|
|
.canonical_head
|
|
.fork_choice_read_lock()
|
|
.get_block(&self.harness.finalized_checkpoint().root)
|
|
.unwrap();
|
|
|
|
self
|
|
}
|
|
}
|
|
|
|
fn is_safe_to_update(slot: Slot, spec: &ChainSpec) -> bool {
|
|
slot % E::slots_per_epoch() < spec.safe_slots_to_update_justified
|
|
}
|
|
|
|
#[test]
|
|
fn justified_and_finalized_blocks() {
|
|
let tester = ForkChoiceTest::new();
|
|
let fork_choice = tester.harness.chain.canonical_head.fork_choice_read_lock();
|
|
|
|
let justified_checkpoint = fork_choice.justified_checkpoint();
|
|
assert_eq!(justified_checkpoint.epoch, 0);
|
|
assert!(justified_checkpoint.root != Hash256::zero());
|
|
assert!(fork_choice.get_justified_block().is_ok());
|
|
|
|
let finalized_checkpoint = fork_choice.finalized_checkpoint();
|
|
assert_eq!(finalized_checkpoint.epoch, 0);
|
|
assert!(finalized_checkpoint.root != Hash256::zero());
|
|
assert!(fork_choice.get_finalized_block().is_ok());
|
|
}
|
|
|
|
/// - The new justified checkpoint descends from the current.
|
|
/// - Current slot is within `SAFE_SLOTS_TO_UPDATE_JUSTIFIED`
|
|
#[tokio::test]
|
|
async fn justified_checkpoint_updates_with_descendent_inside_safe_slots() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.move_inside_safe_to_update()
|
|
.assert_justified_epoch(0)
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_justified_epoch(2);
|
|
}
|
|
|
|
/// - The new justified checkpoint descends from the current.
|
|
/// - Current slot is **not** within `SAFE_SLOTS_TO_UPDATE_JUSTIFIED`
|
|
/// - This is **not** the first justification since genesis
|
|
#[tokio::test]
|
|
async fn justified_checkpoint_updates_with_descendent_outside_safe_slots() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch <= 2)
|
|
.await
|
|
.unwrap()
|
|
.move_outside_safe_to_update()
|
|
.assert_justified_epoch(2)
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_justified_epoch(3);
|
|
}
|
|
|
|
/// - The new justified checkpoint descends from the current.
|
|
/// - Current slot is **not** within `SAFE_SLOTS_TO_UPDATE_JUSTIFIED`
|
|
/// - This is the first justification since genesis
|
|
#[tokio::test]
|
|
async fn justified_checkpoint_updates_first_justification_outside_safe_to_update() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.move_to_next_unsafe_period()
|
|
.assert_justified_epoch(0)
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_justified_epoch(2);
|
|
}
|
|
|
|
/// - The new justified checkpoint **does not** descend from the current.
|
|
/// - Current slot is within `SAFE_SLOTS_TO_UPDATE_JUSTIFIED`
|
|
/// - Finalized epoch has **not** increased.
|
|
#[tokio::test]
|
|
async fn justified_checkpoint_updates_with_non_descendent_inside_safe_slots_without_finality() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.move_inside_safe_to_update()
|
|
.assert_justified_epoch(2)
|
|
.apply_block_directly_to_fork_choice(|_, state| {
|
|
// The finalized checkpoint should not change.
|
|
state.finalized_checkpoint().epoch = Epoch::new(0);
|
|
|
|
// The justified checkpoint has changed.
|
|
state.current_justified_checkpoint_mut().epoch = Epoch::new(3);
|
|
// The new block should **not** include the current justified block as an ancestor.
|
|
state.current_justified_checkpoint_mut().root = *state
|
|
.get_block_root(Epoch::new(1).start_slot(E::slots_per_epoch()))
|
|
.unwrap();
|
|
})
|
|
.await
|
|
.assert_justified_epoch(3);
|
|
}
|
|
|
|
/// - The new justified checkpoint **does not** descend from the current.
|
|
/// - Current slot is **not** within `SAFE_SLOTS_TO_UPDATE_JUSTIFIED`.
|
|
/// - Finalized epoch has **not** increased.
|
|
#[tokio::test]
|
|
async fn justified_checkpoint_updates_with_non_descendent_outside_safe_slots_without_finality() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.move_to_next_unsafe_period()
|
|
.assert_justified_epoch(2)
|
|
.apply_block_directly_to_fork_choice(|_, state| {
|
|
// The finalized checkpoint should not change.
|
|
state.finalized_checkpoint().epoch = Epoch::new(0);
|
|
|
|
// The justified checkpoint has changed.
|
|
state.current_justified_checkpoint_mut().epoch = Epoch::new(3);
|
|
// The new block should **not** include the current justified block as an ancestor.
|
|
state.current_justified_checkpoint_mut().root = *state
|
|
.get_block_root(Epoch::new(1).start_slot(E::slots_per_epoch()))
|
|
.unwrap();
|
|
})
|
|
.await
|
|
// Now that `SAFE_SLOTS_TO_UPDATE_JUSTIFIED` has been removed, the new
|
|
// block should have updated the justified checkpoint.
|
|
.assert_justified_epoch(3);
|
|
}
|
|
|
|
/// - The new justified checkpoint **does not** descend from the current.
|
|
/// - Current slot is **not** within `SAFE_SLOTS_TO_UPDATE_JUSTIFIED`
|
|
/// - Finalized epoch has increased.
|
|
#[tokio::test]
|
|
async fn justified_checkpoint_updates_with_non_descendent_outside_safe_slots_with_finality() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.move_to_next_unsafe_period()
|
|
.assert_justified_epoch(2)
|
|
.apply_block_directly_to_fork_choice(|_, state| {
|
|
// The finalized checkpoint should change.
|
|
state.finalized_checkpoint_mut().epoch = Epoch::new(1);
|
|
|
|
// The justified checkpoint has changed.
|
|
state.current_justified_checkpoint_mut().epoch = Epoch::new(3);
|
|
// The new block should **not** include the current justified block as an ancestor.
|
|
state.current_justified_checkpoint_mut().root = *state
|
|
.get_block_root(Epoch::new(1).start_slot(E::slots_per_epoch()))
|
|
.unwrap();
|
|
})
|
|
.await
|
|
.assert_justified_epoch(3);
|
|
}
|
|
|
|
/// Check that the balances are obtained correctly.
|
|
#[tokio::test]
|
|
async fn justified_balances() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.current_justified_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_justified_epoch(2)
|
|
.check_justified_balances()
|
|
}
|
|
|
|
macro_rules! assert_invalid_block {
|
|
($err: tt, $($error: pat_param) |+ $( if $guard: expr )?) => {
|
|
assert!(
|
|
matches!(
|
|
$err,
|
|
$( ForkChoiceError::InvalidBlock($error) ) |+ $( if $guard )?
|
|
),
|
|
)
|
|
};
|
|
}
|
|
|
|
/// Specification v0.12.1
|
|
///
|
|
/// assert block.parent_root in store.block_states
|
|
#[tokio::test]
|
|
async fn invalid_block_unknown_parent() {
|
|
let junk = Hash256::from_low_u64_be(42);
|
|
|
|
ForkChoiceTest::new()
|
|
.apply_blocks(2)
|
|
.await
|
|
.apply_invalid_block_directly_to_fork_choice(
|
|
|block, _| {
|
|
*block.message_mut().parent_root_mut() = junk;
|
|
},
|
|
|err| {
|
|
assert_invalid_block!(
|
|
err,
|
|
InvalidBlock::UnknownParent(parent)
|
|
if parent == junk
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1
|
|
///
|
|
/// assert get_current_slot(store) >= block.slot
|
|
#[tokio::test]
|
|
async fn invalid_block_future_slot() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks(2)
|
|
.await
|
|
.apply_invalid_block_directly_to_fork_choice(
|
|
|block, _| {
|
|
*block.message_mut().slot_mut() += 1;
|
|
},
|
|
|err| assert_invalid_block!(err, InvalidBlock::FutureSlot { .. }),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1
|
|
///
|
|
/// assert block.slot > finalized_slot
|
|
#[tokio::test]
|
|
async fn invalid_block_finalized_slot() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.apply_invalid_block_directly_to_fork_choice(
|
|
|block, _| {
|
|
*block.message_mut().slot_mut() =
|
|
Epoch::new(2).start_slot(E::slots_per_epoch()) - 1;
|
|
},
|
|
|err| {
|
|
assert_invalid_block!(
|
|
err,
|
|
InvalidBlock::FinalizedSlot { finalized_slot, .. }
|
|
if finalized_slot == Epoch::new(2).start_slot(E::slots_per_epoch())
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1
|
|
///
|
|
/// assert get_ancestor(store, hash_tree_root(block), finalized_slot) ==
|
|
/// store.finalized_checkpoint().root
|
|
///
|
|
/// Note: we technically don't do this exact check, but an equivalent check. Reference:
|
|
///
|
|
/// https://github.com/ethereum/eth2.0-specs/pull/1884
|
|
#[tokio::test]
|
|
async fn invalid_block_finalized_descendant() {
|
|
let invalid_ancestor = Mutex::new(Hash256::zero());
|
|
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(2)
|
|
.apply_invalid_block_directly_to_fork_choice(
|
|
|block, state| {
|
|
*block.message_mut().parent_root_mut() = *state
|
|
.get_block_root(Epoch::new(1).start_slot(E::slots_per_epoch()))
|
|
.unwrap();
|
|
*invalid_ancestor.lock().unwrap() = block.parent_root();
|
|
},
|
|
|err| {
|
|
assert_invalid_block!(
|
|
err,
|
|
InvalidBlock::NotFinalizedDescendant { block_ancestor, .. }
|
|
if block_ancestor == Some(*invalid_ancestor.lock().unwrap())
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
macro_rules! assert_invalid_attestation {
|
|
($err: tt, $($error: pat_param) |+ $( if $guard: expr )?) => {
|
|
assert!(
|
|
matches!(
|
|
$err,
|
|
$( Err(BeaconChainError::ForkChoiceError(ForkChoiceError::InvalidAttestation($error))) ) |+ $( if $guard )?
|
|
),
|
|
"{:?}",
|
|
$err
|
|
)
|
|
};
|
|
}
|
|
|
|
/// Ensure we can process a valid attestation.
|
|
#[tokio::test]
|
|
async fn valid_attestation() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|_, _| {},
|
|
|result| assert!(result.is_ok()),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// This test is not in the specification, however we reject an attestation with an empty
|
|
/// aggregation bitfield since it has no purpose beyond wasting our time.
|
|
#[tokio::test]
|
|
async fn invalid_attestation_empty_bitfield() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _| match attestation {
|
|
IndexedAttestation::Base(ref mut att) => {
|
|
att.attesting_indices = vec![].into();
|
|
}
|
|
IndexedAttestation::Electra(ref mut att) => {
|
|
att.attesting_indices = vec![].into();
|
|
}
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(result, InvalidAttestation::EmptyAggregationBitfield)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert target.epoch in [expected_current_epoch, previous_epoch]
|
|
///
|
|
/// (tests epoch after current epoch)
|
|
#[tokio::test]
|
|
async fn invalid_attestation_future_epoch() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _| {
|
|
attestation.data_mut().target.epoch = Epoch::new(2);
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::FutureEpoch { attestation_epoch, current_epoch }
|
|
if attestation_epoch == Epoch::new(2) && current_epoch == Epoch::new(0)
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert target.epoch in [expected_current_epoch, previous_epoch]
|
|
///
|
|
/// (tests epoch prior to previous epoch)
|
|
#[tokio::test]
|
|
async fn invalid_attestation_past_epoch() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(E::slots_per_epoch() as usize * 3 + 1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _| {
|
|
attestation.data_mut().target.epoch = Epoch::new(0);
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::PastEpoch { attestation_epoch, current_epoch }
|
|
if attestation_epoch == Epoch::new(0) && current_epoch == Epoch::new(3)
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert target.epoch == compute_epoch_at_slot(attestation.data.slot)
|
|
#[tokio::test]
|
|
async fn invalid_attestation_target_epoch() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(E::slots_per_epoch() as usize + 1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _| {
|
|
attestation.data_mut().slot = Slot::new(1);
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::BadTargetEpoch { target, slot }
|
|
if target == Epoch::new(1) && slot == Slot::new(1)
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert target.root in store.blocks
|
|
#[tokio::test]
|
|
async fn invalid_attestation_unknown_target_root() {
|
|
let junk = Hash256::from_low_u64_be(42);
|
|
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _| {
|
|
attestation.data_mut().target.root = junk;
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::UnknownTargetRoot(root)
|
|
if root == junk
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert attestation.data.beacon_block_root in store.blocks
|
|
#[tokio::test]
|
|
async fn invalid_attestation_unknown_beacon_block_root() {
|
|
let junk = Hash256::from_low_u64_be(42);
|
|
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _| {
|
|
attestation.data_mut().beacon_block_root = junk;
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::UnknownHeadBlock { beacon_block_root }
|
|
if beacon_block_root == junk
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert store.blocks[attestation.data.beacon_block_root].slot <= attestation.data.slot
|
|
#[tokio::test]
|
|
async fn invalid_attestation_future_block() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::Blocks(1),
|
|
|attestation, chain| {
|
|
attestation.data_mut().beacon_block_root = chain
|
|
.block_at_slot(chain.slot().unwrap(), WhenSlotSkipped::Prev)
|
|
.unwrap()
|
|
.unwrap()
|
|
.canonical_root();
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::AttestsToFutureBlock { block, attestation }
|
|
if block == 2 && attestation == 1
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert target.root == get_ancestor(store, attestation.data.beacon_block_root, target_slot)
|
|
#[tokio::test]
|
|
async fn invalid_attestation_inconsistent_ffg_vote() {
|
|
let local_opt = Mutex::new(None);
|
|
let attestation_opt = Mutex::new(None);
|
|
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, chain| {
|
|
attestation.data_mut().target.root = chain
|
|
.block_at_slot(Slot::new(1), WhenSlotSkipped::Prev)
|
|
.unwrap()
|
|
.unwrap()
|
|
.canonical_root();
|
|
|
|
*attestation_opt.lock().unwrap() = Some(attestation.data().target.root);
|
|
*local_opt.lock().unwrap() = Some(
|
|
chain
|
|
.block_at_slot(Slot::new(0), WhenSlotSkipped::Prev)
|
|
.unwrap()
|
|
.unwrap()
|
|
.canonical_root(),
|
|
);
|
|
},
|
|
|result| {
|
|
assert_invalid_attestation!(
|
|
result,
|
|
InvalidAttestation::InvalidTarget { attestation, local }
|
|
if attestation == attestation_opt.lock().unwrap().unwrap()
|
|
&& local == local_opt.lock().unwrap().unwrap()
|
|
)
|
|
},
|
|
)
|
|
.await;
|
|
}
|
|
|
|
/// Specification v0.12.1:
|
|
///
|
|
/// assert get_current_slot(store) >= attestation.data.slot + 1
|
|
#[tokio::test]
|
|
async fn invalid_attestation_delayed_slot() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_without_new_attestations(1)
|
|
.await
|
|
.inspect_queued_attestations(|queue| assert_eq!(queue.len(), 0))
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|_, _| {},
|
|
|result| assert!(result.is_ok()),
|
|
)
|
|
.await
|
|
.inspect_queued_attestations(|queue| assert_eq!(queue.len(), 1))
|
|
.skip_slot()
|
|
.inspect_queued_attestations(|queue| assert_eq!(queue.len(), 0));
|
|
}
|
|
|
|
/// Tests that the correct target root is used when the attested-to block is in a prior epoch to
|
|
/// the attestation.
|
|
#[tokio::test]
|
|
async fn valid_attestation_skip_across_epoch() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks(E::slots_per_epoch() as usize - 1)
|
|
.await
|
|
.skip_slots(2)
|
|
.apply_attestation_to_chain(
|
|
MutationDelay::NoDelay,
|
|
|attestation, _chain| {
|
|
assert_eq!(
|
|
attestation.data().target.root,
|
|
attestation.data().beacon_block_root
|
|
)
|
|
},
|
|
|result| result.unwrap(),
|
|
)
|
|
.await;
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn can_read_finalized_block() {
|
|
ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.check_finalized_block_is_accessible();
|
|
}
|
|
|
|
#[test]
|
|
#[should_panic]
|
|
fn weak_subjectivity_fail_on_startup() {
|
|
let epoch = Epoch::new(0);
|
|
let root = Hash256::from_low_u64_le(1);
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(Checkpoint { epoch, root }),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
ForkChoiceTest::new_with_chain_config(chain_config);
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_pass_on_startup() {
|
|
let epoch = Epoch::new(0);
|
|
let root = Hash256::zero();
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(Checkpoint { epoch, root }),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
ForkChoiceTest::new_with_chain_config(chain_config)
|
|
.apply_blocks(E::slots_per_epoch() as usize)
|
|
.await
|
|
.assert_shutdown_signal_not_sent();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_check_passes() {
|
|
let setup_harness = ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(2);
|
|
|
|
let checkpoint = setup_harness.harness.finalized_checkpoint();
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(checkpoint),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
ForkChoiceTest::new_with_chain_config(chain_config.clone())
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(2)
|
|
.assert_shutdown_signal_not_sent();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_check_fails_early_epoch() {
|
|
let setup_harness = ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(2);
|
|
|
|
let mut checkpoint = setup_harness.harness.finalized_checkpoint();
|
|
|
|
checkpoint.epoch -= 1;
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(checkpoint),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
ForkChoiceTest::new_with_chain_config(chain_config.clone())
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 3)
|
|
.await
|
|
.unwrap_err()
|
|
.assert_finalized_epoch_is_less_than(checkpoint.epoch)
|
|
.assert_shutdown_signal_sent();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_check_fails_late_epoch() {
|
|
let setup_harness = ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(2);
|
|
|
|
let mut checkpoint = setup_harness.harness.finalized_checkpoint();
|
|
|
|
checkpoint.epoch += 1;
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(checkpoint),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
ForkChoiceTest::new_with_chain_config(chain_config.clone())
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 4)
|
|
.await
|
|
.unwrap_err()
|
|
.assert_finalized_epoch_is_less_than(checkpoint.epoch)
|
|
.assert_shutdown_signal_sent();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_check_fails_incorrect_root() {
|
|
let setup_harness = ForkChoiceTest::new()
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(2);
|
|
|
|
let mut checkpoint = setup_harness.harness.finalized_checkpoint();
|
|
|
|
checkpoint.root = Hash256::zero();
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(checkpoint),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
ForkChoiceTest::new_with_chain_config(chain_config.clone())
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 3)
|
|
.await
|
|
.unwrap_err()
|
|
.assert_finalized_epoch_is_less_than(checkpoint.epoch)
|
|
.assert_shutdown_signal_sent();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_check_epoch_boundary_is_skip_slot() {
|
|
let setup_harness = ForkChoiceTest::new()
|
|
// first two epochs
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap();
|
|
|
|
// get the head, it will become the finalized root of epoch 4
|
|
let checkpoint_root = setup_harness.harness.head_block_root();
|
|
|
|
setup_harness
|
|
// epoch 3 will be entirely skip slots
|
|
.skip_slots(E::slots_per_epoch() as usize)
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 5)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(5);
|
|
|
|
// the checkpoint at epoch 4 should become the root of last block of epoch 2
|
|
let checkpoint = Checkpoint {
|
|
epoch: Epoch::new(4),
|
|
root: checkpoint_root,
|
|
};
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(checkpoint),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
// recreate the chain exactly
|
|
ForkChoiceTest::new_with_chain_config(chain_config.clone())
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.skip_slots(E::slots_per_epoch() as usize)
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 5)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(5)
|
|
.assert_shutdown_signal_not_sent();
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn weak_subjectivity_check_epoch_boundary_is_skip_slot_failure() {
|
|
let setup_harness = ForkChoiceTest::new()
|
|
// first two epochs
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap();
|
|
|
|
// get the head, it will become the finalized root of epoch 4
|
|
let checkpoint_root = setup_harness.harness.head_block_root();
|
|
|
|
setup_harness
|
|
// epoch 3 will be entirely skip slots
|
|
.skip_slots(E::slots_per_epoch() as usize)
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 5)
|
|
.await
|
|
.unwrap()
|
|
.apply_blocks(1)
|
|
.await
|
|
.assert_finalized_epoch(5);
|
|
|
|
// Invalid checkpoint (epoch too early)
|
|
let checkpoint = Checkpoint {
|
|
epoch: Epoch::new(1),
|
|
root: checkpoint_root,
|
|
};
|
|
|
|
let chain_config = ChainConfig {
|
|
weak_subjectivity_checkpoint: Some(checkpoint),
|
|
..ChainConfig::default()
|
|
};
|
|
|
|
// recreate the chain exactly
|
|
ForkChoiceTest::new_with_chain_config(chain_config.clone())
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
.skip_slots(E::slots_per_epoch() as usize)
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch < 6)
|
|
.await
|
|
.unwrap_err()
|
|
.assert_finalized_epoch_is_less_than(checkpoint.epoch)
|
|
.assert_shutdown_signal_sent();
|
|
}
|
|
|
|
/// Checks that `ProgressiveBalancesCache` is updated correctly after an attester slashing event,
|
|
/// where the slashed validator is a target attester in previous / current epoch.
|
|
#[tokio::test]
|
|
async fn progressive_balances_cache_attester_slashing() {
|
|
ForkChoiceTest::new()
|
|
// first two epochs
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
// Note: This test may fail if the shuffling used changes, right now it re-runs with
|
|
// deterministic shuffling. A shuffling change my cause the slashed proposer to propose
|
|
// again in the next epoch, which results in a block processing failure
|
|
// (`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(2)
|
|
.await
|
|
.add_previous_epoch_attester_slashing()
|
|
.await
|
|
// expect fork choice to import blocks successfully after a previous epoch attester is
|
|
// slashed, i.e. the slashed attester's balance is correctly excluded from
|
|
// the previous epoch total balance in `ProgressiveBalancesCache`.
|
|
.apply_blocks(1)
|
|
.await
|
|
// expect fork choice to import another epoch of blocks successfully - the slashed
|
|
// attester's balance should be excluded from the current epoch total balance in
|
|
// `ProgressiveBalancesCache` as well.
|
|
.apply_blocks(MainnetEthSpec::slots_per_epoch() as usize)
|
|
.await;
|
|
}
|
|
|
|
/// Checks that `ProgressiveBalancesCache` is updated correctly after a proposer slashing event,
|
|
/// where the slashed validator is a target attester in previous / current epoch.
|
|
#[tokio::test]
|
|
async fn progressive_balances_cache_proposer_slashing() {
|
|
ForkChoiceTest::new()
|
|
// first two epochs
|
|
.apply_blocks_while(|_, state| state.finalized_checkpoint().epoch == 0)
|
|
.await
|
|
.unwrap()
|
|
// Note: This test may fail if the shuffling used changes, right now it re-runs with
|
|
// deterministic shuffling. A shuffling change may cause the slashed proposer to propose
|
|
// again in the next epoch, which results in a block processing failure
|
|
// (`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_attester_slashing`.
|
|
.apply_blocks(2)
|
|
.await
|
|
.add_previous_epoch_proposer_slashing(MainnetEthSpec::slots_per_epoch())
|
|
.await
|
|
// expect fork choice to import blocks successfully after a previous epoch proposer is
|
|
// slashed, i.e. the slashed proposer's balance is correctly excluded from
|
|
// the previous epoch total balance in `ProgressiveBalancesCache`.
|
|
.apply_blocks(1)
|
|
.await
|
|
// expect fork choice to import another epoch of blocks successfully - the slashed
|
|
// proposer's balance should be excluded from the current epoch total balance in
|
|
// `ProgressiveBalancesCache` as well.
|
|
.apply_blocks(MainnetEthSpec::slots_per_epoch() as usize)
|
|
.await;
|
|
}
|