mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-29 06:37:17 +00:00
e744d1a07e
* Optimize Shuffled Indices Cache (#2728) * Refactor Deposit Contract Test Setup (#2731) * add new package * fix all tests * lint * change hash function (#2732) * Remove Deprecated Validator Protobuf (#2727) * Remove deprecated validator protos * Fix to comments * Fix most of skipped tests (#2735) * Cache Active Validator Indices, Count, and Balances (#2737) * Optimize Base Reward Calculation (#2753) * benchmark process epoch * revert prof.out * Add some optimizations * beware where we use ActiveValidatorIndices... * revert extra file * gaz * quick commit to get feedback * revert extra file * started fixing tests * fixed broken TestProcessCrosslink_NoUpdate * gaz * cache randao seed * fixed all the tests * fmt and lint * spacing * Added todo * lint * revert binary file * started regression test * basic tests done * using a fifo for active indices cache * using a fifo for active count cache * using a fifo for total balance cache * using a fifo for active balance cache * using a fifo for start shard cache * using a fifo for seed cache * gaz * clean up * fixing tests * fixed all the core tests * fixed all the tests!!! * lint * comment * rm'ed commented code * cache size to 1000 should be good enough * optimized base reward * revert binary file * Added comments to calculate adjusted quotient outside * removed deprecated configs (#2755) * Optimize Process Eth1 Data Vote (#2754) * Cleanup and Docs update (#2756) * Add graffiti and update generate seed (#2759) * Benchmark Process Block with Attestations (#2758) * Tidying up Godoc for Core Package (#2762) * Clean up Old RPC Endpoints (#2763) * Update RPC end point for Proposer (#2767) * add RequestBlock * run mockgen * implemented RequestBlock * updated proto definitions * updated tests * updated validator attest tests * done * comment * todo issue * removed unused proto * Update attesting indices v0.6 (#2449) * sort participants slice * add bitfield functions and tests * added BitfieldBit test * add AttestationParticipantsNew * revert AttestationParticipants to its previous change * add tests * remove verifybitfieldnew * fix tests and remove multiple tests * remove duplicate test * change magic number into ceildiv8 * Implement Justification and finalization Processing (#2448) * Add convert to indexed (#2519) * sort participants slice * add bitfield functions and tests * added BitfieldBit test * add AttestationParticipantsNew * revert AttestationParticipants to its previous change * add tests * remove verifybitfieldnew * fix tests and remove multiple tests * remove duplicate test * start work * convert attestation to indexed attestations * fix test for convert index * remove calling getter * add more tests * remove underscore * changes name to signature (#2535) * update registry updates func (#2521) * update registry updates func * added tests and moved to epoch processing * fixed naming issues * Update Committee Helpers to v0.6.0 (#2398) * Update Committee Helper Part 2 (#2592) * Implement Process Slashings for 0.6 (#2523) * Update Proposer/Attester Slashings and Slashing Helpers (#2603) * Implement Final Updates 0.6 (#2562) * ValidatorStatus Estimating Activation RPC Server (#2469) * fix spacing * working on position in queue * fmt * spacing * feedback * tests * rename * Only Perform Initial Sync With a Single Peer (#2471) * fix spacing * use send instead of broadcast in initial sync * Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472) * fix spacing * fix time estimates * correct slot estimation * naming * Update beacon-chain/rpc/validator_server.go Co-Authored-By: rauljordan <raul@prysmaticlabs.com> * SSZ web api for decoding input data (#2473) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * standardize slot numbers (#2475) * Add CORS for ssz api (#2476) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * needed CORS * Allow Client to Retrieve Multiple Validator Statuses (#2474) * multiple validator statuses * gazelle * context * fixing bugs * remove old way of checking * fix logging * make activation queue more accurate * fix rpc test * add test * fix remaining tests * lint * comment * review comments * Update Prysm README (#2477) * README updated * readme updates * no err throw (#2479) * Fix Status Nil Pointer Error (#2480) * no err throw * nil errors * 3.175 (#2482) * Better Error Message if Failing to Exit Initial Sync (#2483) * no err throw * nil errors * better error on init sync * Only Log Active Balances (#2485) * only log active balance * dont need () * change logging (#2487) * fix chainstart waiting on rpc server (#2488) * shift ticker to after activation (#2489) * Add drain script (#2418) * Add drain script * Fix script to drain contracts from newest to oldest * Add README * remove comments * Only after block 400k, look up by deposit event * issue warn log on disconnecting peer instead of error (#2491) * Display Only Active Validator Data (#2490) * Fix Validator Status Field in RPC Server (#2492) * fix status of key * status test fix * fmt * Estimate the Time Till Follow Distance Is Completed (#2486) * use estimation instead * fix test * fixing another test * fix tests and preston's comments * remove unused var * fix condition * Revert "fix condition" This reverts commit dee0e3112c01f68f30a2e50cd4eb35f29f672e1d. * dont return error * add production config for testnet release (#2493) * Lookup Validator Index in State in Status Check (#2494) * state lookup * refactor duplicate code * refactor with mapping * fix broken tests * finish refactor * merged master * updated EpochCommitteeCount and fixed tests * implemented ShardDelta * test for ShardDelta * implemented EpochStartShard * added epoch out of bound test * test for accurate start shard * lint * implemented process_final_updates * move to the top of the file * add comment back * gaz * Test for process final updates * fixed tests * fixed all the tests * Update Reward Helper v0.6 (#2470) * added BaseReward * added rewards helper * added test for BaseReward * extra space * move exported function above * update to new spec (#2614) * Update Block Processing Voluntary Exits (#2609) * Update processEth1Data for v0.6 (#2516) * Clean up Helper Functions Part 1 (#2612) * Finalize helper functions for 0.6 (#2632) * Process Beacon Chain Transfers v0.6 (#2642) * add transfers * beacon transfer operations complete * full cov * transfer testing * finished tests * Update beacon-chain/core/blocks/block_operations_test.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * Update beacon-chain/core/blocks/block_operations.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * Implement Process Crosslink From 0.6 (#2460) * Process Block Eth1 Data v0.6 (#2645) * Get attestation data slot v0.6 (#2593) * attestation.go is ready, tests not * ready for review * fixing linter issues * modified Crosslink and AttestationData proto fields to spec 2.0,marked deprecated fields * gazelle * fixed tests * fixed error * error msg * Process Block Deposits v0.6 (#2647) * imports fixes * deposits tests pass * wrapped up gazelle * spacing * Implement Crosslink Delta Rewards for 0.6 (#2517) * update process crosslink and update existing tests * added a test case to cover no crosslink changes * more test * preston's feedback * spellings * ValidatorStatus Estimating Activation RPC Server (#2469) * fix spacing * working on position in queue * fmt * spacing * feedback * tests * rename * Only Perform Initial Sync With a Single Peer (#2471) * fix spacing * use send instead of broadcast in initial sync * Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472) * fix spacing * fix time estimates * correct slot estimation * naming * Update beacon-chain/rpc/validator_server.go Co-Authored-By: rauljordan <raul@prysmaticlabs.com> * SSZ web api for decoding input data (#2473) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * standardize slot numbers (#2475) * Add CORS for ssz api (#2476) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * needed CORS * Allow Client to Retrieve Multiple Validator Statuses (#2474) * multiple validator statuses * gazelle * context * fixing bugs * remove old way of checking * fix logging * make activation queue more accurate * fix rpc test * add test * fix remaining tests * lint * comment * review comments * Update Prysm README (#2477) * README updated * readme updates * no err throw (#2479) * Fix Status Nil Pointer Error (#2480) * no err throw * nil errors * 3.175 (#2482) * Better Error Message if Failing to Exit Initial Sync (#2483) * no err throw * nil errors * better error on init sync * Only Log Active Balances (#2485) * only log active balance * dont need () * change logging (#2487) * fix chainstart waiting on rpc server (#2488) * shift ticker to after activation (#2489) * Add drain script (#2418) * Add drain script * Fix script to drain contracts from newest to oldest * Add README * remove comments * Only after block 400k, look up by deposit event * issue warn log on disconnecting peer instead of error (#2491) * Display Only Active Validator Data (#2490) * Fix Validator Status Field in RPC Server (#2492) * fix status of key * status test fix * fmt * Estimate the Time Till Follow Distance Is Completed (#2486) * use estimation instead * fix test * fixing another test * fix tests and preston's comments * remove unused var * fix condition * Revert "fix condition" This reverts commit dee0e3112c01f68f30a2e50cd4eb35f29f672e1d. * dont return error * add production config for testnet release (#2493) * Lookup Validator Index in State in Status Check (#2494) * state lookup * refactor duplicate code * refactor with mapping * fix broken tests * finish refactor * merged master * Starting, I need get_epoch_start_shard * updated EpochCommitteeCount and fixed tests * implemented ShardDelta * test for ShardDelta * implemented EpochStartShard * added epoch out of bound test * test for accurate start shard * lint * need to use changes from latest crosslinks * added BaseReward and totalActiveBalance * added test for base reward * merged master * all tests passing * start testing * done * add ProcessBlockHeader v0.6 (#2534) * add ProcessBlockHeader * function has all its dependancies in place * arange the basic ok test * gazzele and skip test update * skip wrong sig test * fmt imports and change requests * goimports fmt * map for struct fields to be location independent * reorder protobuf fields * added tests * gazzle fix * few change requests fixes * revert changes in types.proto * revert changes in types * fix tests * fix lint * fmt imports * fix gazelle * fix var naming * pb update * var naming * tarance change request fixes * fix test * Add Process Registry for Epoch Processing (#2668) * update update-process-registry * added back the old tests * fmt * gaz * Follow up on process block header v0.6 (#2666) * Putting Crosslink Delta Back (#2654) * update process crosslink and update existing tests * added a test case to cover no crosslink changes * more test * preston's feedback * spellings * ValidatorStatus Estimating Activation RPC Server (#2469) * fix spacing * working on position in queue * fmt * spacing * feedback * tests * rename * Only Perform Initial Sync With a Single Peer (#2471) * fix spacing * use send instead of broadcast in initial sync * Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472) * fix spacing * fix time estimates * correct slot estimation * naming * Update beacon-chain/rpc/validator_server.go Co-Authored-By: rauljordan <raul@prysmaticlabs.com> * SSZ web api for decoding input data (#2473) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * standardize slot numbers (#2475) * Add CORS for ssz api (#2476) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * needed CORS * Allow Client to Retrieve Multiple Validator Statuses (#2474) * multiple validator statuses * gazelle * context * fixing bugs * remove old way of checking * fix logging * make activation queue more accurate * fix rpc test * add test * fix remaining tests * lint * comment * review comments * Update Prysm README (#2477) * README updated * readme updates * no err throw (#2479) * Fix Status Nil Pointer Error (#2480) * no err throw * nil errors * 3.175 (#2482) * Better Error Message if Failing to Exit Initial Sync (#2483) * no err throw * nil errors * better error on init sync * Only Log Active Balances (#2485) * only log active balance * dont need () * change logging (#2487) * fix chainstart waiting on rpc server (#2488) * shift ticker to after activation (#2489) * Add drain script (#2418) * Add drain script * Fix script to drain contracts from newest to oldest * Add README * remove comments * Only after block 400k, look up by deposit event * issue warn log on disconnecting peer instead of error (#2491) * Display Only Active Validator Data (#2490) * Fix Validator Status Field in RPC Server (#2492) * fix status of key * status test fix * fmt * Estimate the Time Till Follow Distance Is Completed (#2486) * use estimation instead * fix test * fixing another test * fix tests and preston's comments * remove unused var * fix condition * Revert "fix condition" This reverts commit dee0e3112c01f68f30a2e50cd4eb35f29f672e1d. * dont return error * add production config for testnet release (#2493) * Lookup Validator Index in State in Status Check (#2494) * state lookup * refactor duplicate code * refactor with mapping * fix broken tests * finish refactor * merged master * Starting, I need get_epoch_start_shard * updated EpochCommitteeCount and fixed tests * implemented ShardDelta * test for ShardDelta * implemented EpochStartShard * added epoch out of bound test * test for accurate start shard * lint * need to use changes from latest crosslinks * added BaseReward and totalActiveBalance * added test for base reward * merged master * all tests passing * start testing * done * fixed tests * addressed shay's feedback * Implement Attestation Delta for v0.6 (#2646) * update process crosslink and update existing tests * added a test case to cover no crosslink changes * more test * preston's feedback * spellings * ValidatorStatus Estimating Activation RPC Server (#2469) * fix spacing * working on position in queue * fmt * spacing * feedback * tests * rename * Only Perform Initial Sync With a Single Peer (#2471) * fix spacing * use send instead of broadcast in initial sync * Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472) * fix spacing * fix time estimates * correct slot estimation * naming * Update beacon-chain/rpc/validator_server.go Co-Authored-By: rauljordan <raul@prysmaticlabs.com> * SSZ web api for decoding input data (#2473) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * standardize slot numbers (#2475) * Add CORS for ssz api (#2476) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * needed CORS * Allow Client to Retrieve Multiple Validator Statuses (#2474) * multiple validator statuses * gazelle * context * fixing bugs * remove old way of checking * fix logging * make activation queue more accurate * fix rpc test * add test * fix remaining tests * lint * comment * review comments * Update Prysm README (#2477) * README updated * readme updates * no err throw (#2479) * Fix Status Nil Pointer Error (#2480) * no err throw * nil errors * 3.175 (#2482) * Better Error Message if Failing to Exit Initial Sync (#2483) * no err throw * nil errors * better error on init sync * Only Log Active Balances (#2485) * only log active balance * dont need () * change logging (#2487) * fix chainstart waiting on rpc server (#2488) * shift ticker to after activation (#2489) * Add drain script (#2418) * Add drain script * Fix script to drain contracts from newest to oldest * Add README * remove comments * Only after block 400k, look up by deposit event * issue warn log on disconnecting peer instead of error (#2491) * Display Only Active Validator Data (#2490) * Fix Validator Status Field in RPC Server (#2492) * fix status of key * status test fix * fmt * Estimate the Time Till Follow Distance Is Completed (#2486) * use estimation instead * fix test * fixing another test * fix tests and preston's comments * remove unused var * fix condition * Revert "fix condition" This reverts commit dee0e3112c01f68f30a2e50cd4eb35f29f672e1d. * dont return error * add production config for testnet release (#2493) * Lookup Validator Index in State in Status Check (#2494) * state lookup * refactor duplicate code * refactor with mapping * fix broken tests * finish refactor * merged master * Starting, I need get_epoch_start_shard * updated EpochCommitteeCount and fixed tests * implemented ShardDelta * test for ShardDelta * implemented EpochStartShard * added epoch out of bound test * test for accurate start shard * lint * need to use changes from latest crosslinks * added BaseReward and totalActiveBalance * added test for base reward * implemented process_attestation_delta * comments * comments * merged master * all tests passing * start testing * done * merged master * fixed tests * tests, more to come * tests done * lint * spaces over tabs * addressed shay's feedback * merged master * Implement process_rewards_and_penalties for 0.6 (#2665) * update process crosslink and update existing tests * added a test case to cover no crosslink changes * more test * preston's feedback * spellings * ValidatorStatus Estimating Activation RPC Server (#2469) * fix spacing * working on position in queue * fmt * spacing * feedback * tests * rename * Only Perform Initial Sync With a Single Peer (#2471) * fix spacing * use send instead of broadcast in initial sync * Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472) * fix spacing * fix time estimates * correct slot estimation * naming * Update beacon-chain/rpc/validator_server.go Co-Authored-By: rauljordan <raul@prysmaticlabs.com> * SSZ web api for decoding input data (#2473) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * standardize slot numbers (#2475) * Add CORS for ssz api (#2476) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * needed CORS * Allow Client to Retrieve Multiple Validator Statuses (#2474) * multiple validator statuses * gazelle * context * fixing bugs * remove old way of checking * fix logging * make activation queue more accurate * fix rpc test * add test * fix remaining tests * lint * comment * review comments * Update Prysm README (#2477) * README updated * readme updates * no err throw (#2479) * Fix Status Nil Pointer Error (#2480) * no err throw * nil errors * 3.175 (#2482) * Better Error Message if Failing to Exit Initial Sync (#2483) * no err throw * nil errors * better error on init sync * Only Log Active Balances (#2485) * only log active balance * dont need () * change logging (#2487) * fix chainstart waiting on rpc server (#2488) * shift ticker to after activation (#2489) * Add drain script (#2418) * Add drain script * Fix script to drain contracts from newest to oldest * Add README * remove comments * Only after block 400k, look up by deposit event * issue warn log on disconnecting peer instead of error (#2491) * Display Only Active Validator Data (#2490) * Fix Validator Status Field in RPC Server (#2492) * fix status of key * status test fix * fmt * Estimate the Time Till Follow Distance Is Completed (#2486) * use estimation instead * fix test * fixing another test * fix tests and preston's comments * remove unused var * fix condition * Revert "fix condition" This reverts commit dee0e3112c01f68f30a2e50cd4eb35f29f672e1d. * dont return error * add production config for testnet release (#2493) * Lookup Validator Index in State in Status Check (#2494) * state lookup * refactor duplicate code * refactor with mapping * fix broken tests * finish refactor * merged master * Starting, I need get_epoch_start_shard * updated EpochCommitteeCount and fixed tests * implemented ShardDelta * test for ShardDelta * implemented EpochStartShard * added epoch out of bound test * test for accurate start shard * lint * need to use changes from latest crosslinks * added BaseReward and totalActiveBalance * added test for base reward * implemented process_attestation_delta * comments * comments * merged master * all tests passing * start testing * done * merged master * fixed tests * tests, more to come * tests done * lint * spaces over tabs * addressed shay's feedback * starting but need to merge a few things... * tests * fmt * Update Slot Processing and State Transition v0.6 (#2664) * edit state transition to add slot processing logic, reorder logic * fix build * lint * tests passing * spacing * tests pass * imports * passing tests * Implement Process Epoch for 0.6 (#2675) * can't find process j f functons * implemented process_epoch * tests done * lint * nishant's feedback * stupid goland replace * goimports * Update CommitteeAssignment (#2693) * cleaned up skipped tests for core processing (#2697) * Process Block Attestations v0.6 (#2650) * attestation.go is ready, tests not * ready for review * fixing linter issues * modified Crosslink and AttestationData proto fields to spec 2.0,marked deprecated fields * gazelle * fixed tests * fixed error * add att processing: * process atts * error msg * finish process attestations logic * spacing * ssz move * inclusion delay failure passing * more attestation tests * more att tests passing * more tests * ffg data mismatching test * ffg tests complete * gofmt * fix testing to match attestation updates * ssz * lint * Fixed Skipped Tests for RPC Server (#2712) * Remove Obsolete Deposit Proto Objects (#2673) * remove deposit data * remove deposit input * fix references * remove deposit helpers * fix all refs * gaz * rgene proto * fix all tests * remove deposit data deprecated field * fix remaining references * fix all tests * fix lint * regen proto * fix test * Remove Deprecated Protobuf State Fields (#2713) * Remove Deprecated Protobuf Crosslink/Slashing/Block Fields (#2714) * Remove Deprecated Beacon Block Proto Fields (#2717) * Remove Deprecated Attestation Proto Fields (#2723) * Cache Shuffled Validator Indices (#2682) * YAML shuffle tests for v0.6 (#2667) * new shuffle tests * added comment for exported function * fix format and print * added config files handling * gazelle fix * shuffle test debugging * added shuffle list and benchmark * hash function addition from nishant code * gazelle fix * remove unused function * few minor changes * add test to test protos optimization * test a bigger list * remove commented code * small changes * fix spec test and test indices to pass * remove empty line * abstraction of repeated code and comment arrangement * terence change requests * fix new test * add small comment for better readability * change from unshuflle to shuffle * comment * better comment * fix all tests * Remove Latest Block (#2721) * lint * remove latest block * lint * add proto * fix build * Fix Deposit Trie (#2686) * remove deposit data * remove deposit input * fix references * remove deposit helpers * fix all refs * gaz * rgene proto * fix all tests * remove deposit data deprecated field * fix remaining references * fix all tests * fix lint * new tests with contract * gaz * more tests * fixed bugs * new test * finally fixed it * gaz * fix test * Remove Committee Cache (#2729) * Benchmark Compute Committee (#2698) * Fixed Skipped Attestation Tests (#2730) * Optimize Shuffled Indices Cache (#2728) * Refactor Deposit Contract Test Setup (#2731) * add new package * fix all tests * lint * change hash function (#2732) * Remove Deprecated Validator Protobuf (#2727) * Remove deprecated validator protos * Fix to comments * Fix most of skipped tests (#2735) * Optimize Base Reward Calculation (#2753) * benchmark process epoch * revert prof.out * Add some optimizations * beware where we use ActiveValidatorIndices... * revert extra file * gaz * quick commit to get feedback * revert extra file * started fixing tests * fixed broken TestProcessCrosslink_NoUpdate * gaz * cache randao seed * fixed all the tests * fmt and lint * spacing * Added todo * lint * revert binary file * started regression test * basic tests done * using a fifo for active indices cache * using a fifo for active count cache * using a fifo for total balance cache * using a fifo for active balance cache * using a fifo for start shard cache * using a fifo for seed cache * gaz * clean up * fixing tests * fixed all the core tests * fixed all the tests!!! * lint * comment * rm'ed commented code * cache size to 1000 should be good enough * optimized base reward * revert binary file * Added comments to calculate adjusted quotient outside * removed deprecated configs (#2755) * Optimize Process Eth1 Data Vote (#2754) * Cleanup and Docs update (#2756) * Add graffiti and update generate seed (#2759) * Benchmark Process Block with Attestations (#2758) * Tidying up Godoc for Core Package (#2762) * Clean up Old RPC Endpoints (#2763) * Update RPC end point for Proposer (#2767) * add RequestBlock * run mockgen * implemented RequestBlock * updated proto definitions * updated tests * updated validator attest tests * done * comment * todo issue * removed unused proto * Cache Active Validator Indices, Count, and Balances (#2737) * Update Deposit Contract (#2648) * lint * add new contract * change version * remove log * generating abi and binary files * fix tests * update to current version * new changes * add new hash function * save hashed nodes * add more things * new method * add update to trie * new stuff * gaz * more stuff * finally fixed build * remove deposit data * Revert "remove deposit data" This reverts commit 9085409e91be0c94550af10290eaad72ad40a6de. * more changes * lint and gaz * lint * Update Shard Helpers for 0.6 (#2497) * ValidatorStatus Estimating Activation RPC Server (#2469) * fix spacing * working on position in queue * fmt * spacing * feedback * tests * rename * Only Perform Initial Sync With a Single Peer (#2471) * fix spacing * use send instead of broadcast in initial sync * Fix Estimation of Deposit Inclusion Slot in ValidatorActivationStatus (#2472) * fix spacing * fix time estimates * correct slot estimation * naming * Update beacon-chain/rpc/validator_server.go Co-Authored-By: rauljordan <raul@prysmaticlabs.com> * SSZ web api for decoding input data (#2473) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * standardize slot numbers (#2475) * Add CORS for ssz api (#2476) * first pass ssz server for decoding deposit input data * fix decoding * revert viz change on helper * add image target * use /api prefix, add deployment for cluster * fix lint * needed CORS * Allow Client to Retrieve Multiple Validator Statuses (#2474) * multiple validator statuses * gazelle * context * fixing bugs * remove old way of checking * fix logging * make activation queue more accurate * fix rpc test * add test * fix remaining tests * lint * comment * review comments * Update Prysm README (#2477) * README updated * readme updates * no err throw (#2479) * Fix Status Nil Pointer Error (#2480) * no err throw * nil errors * 3.175 (#2482) * Better Error Message if Failing to Exit Initial Sync (#2483) * no err throw * nil errors * better error on init sync * Only Log Active Balances (#2485) * only log active balance * dont need () * change logging (#2487) * fix chainstart waiting on rpc server (#2488) * shift ticker to after activation (#2489) * Add drain script (#2418) * Add drain script * Fix script to drain contracts from newest to oldest * Add README * remove comments * Only after block 400k, look up by deposit event * issue warn log on disconnecting peer instead of error (#2491) * Display Only Active Validator Data (#2490) * Fix Validator Status Field in RPC Server (#2492) * fix status of key * status test fix * fmt * Estimate the Time Till Follow Distance Is Completed (#2486) * use estimation instead * fix test * fixing another test * fix tests and preston's comments * remove unused var * fix condition * Revert "fix condition" This reverts commit dee0e3112c01f68f30a2e50cd4eb35f29f672e1d. * dont return error * add production config for testnet release (#2493) * Lookup Validator Index in State in Status Check (#2494) * state lookup * refactor duplicate code * refactor with mapping * fix broken tests * finish refactor * merged master * updated EpochCommitteeCount and fixed tests * implemented ShardDelta * test for ShardDelta * implemented EpochStartShard * added epoch out of bound test * test for accurate start shard * lint * Update Genesis State Function to v0.6 (#2465) * add pseudocode * make changes * fix all tests * fix tests * lint * regen protos and mocks * regenerated protos * started fixing core * all core tests passing! * removed shared/forkutils * started fixing blockchain package * lint * updating rpc package * add back deleted stuff * add back deleted stuff that was deleted accidentally * add back protos and mocks * fix errors * fix genesis issue * fix genesis issue for slot ticker * fix all genesis errors * fix build files * temp change for go-ssz * fix test * Revert "temp change for go-ssz" This reverts commit 3411cb9d6d519cb521181486debc3b21603c8873. * update to latest go-ssz * unstaged changes * Update Attester Server RPC Calls (#2773) * Update config and function parameters to v0.7 (#2791) * Minor Updates to 0.7 (#2795) * Refactor Deposit Flow and Cleanup Tests (#2788) * More WIP on cleaning deposit flow * Fix tests * Cleanup and imports * run gazelle * Move deposit to block_operations * gazelle * Update beacon-chain/core/blocks/block_operations.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * Fix docs * Remove unneeded calculations * Fix tests * Fix tests finally (?) * Optimize Committee Assignment RPC (#2787) * Update BlockRoot to BlockHash (#2816) * Fix Final Missing Items in Block Processing v0.6 (#2710) * override config successfully * passes processing * add signing root helper * blockchain tests pass * tests blocked by signing root * lint * fix references * fix protos * proper use of signing root * only few failing tests now * fix final test * tests passing * lint and imports * rem unused * Update beacon-chain/core/blocks/block_operations.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * lint * Update beacon-chain/attestation/service_test.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * Update beacon-chain/db/block_test.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * rename to hash tree root * rename decode to unmarshal * fix * use latest ssz * all tests passing * lint * fmt * Add Config YAML for Spec Tests (#2818) * Align Protobuf Type Names (#2825) * gofmt * Revert "Align Protobuf Type Names (#2825)" (#2827) This reverts commit 882d067144c674bbf4eeee00404acaa0a9b1fd33. * Update Domain Related Functions (#2832) * Add Functions for Compressed and Uncompressed HashG2 With Domain (#2833) * add tests * gaz * lint * Revert "Add Functions for Compressed and Uncompressed HashG2 With Domain (#2833)" (#2835) This reverts commit 7fb2ebf3f12f043d7bd12f43500dc2bd133df573. * Add ConvertToPb to package testutil (#2838) * Block Processing Bug Fixes (#2836) * Update types PB with Size Tags (#2840) * Epoch processing spec tests (#2814) * Remove Deposit Index (#2851) * Shuffle tests revisited (#2829) * first commit * remove old files, add log * remove duplicate yaml testing code * reduce visability * nishant feedback changes * skip TestFromYaml_Pass * added tags to bazel build * gazelle fix * remove unused vars * adda back config * remove config handling * remove unused var * gazelle fix * SSZ compatibility test for protobufs (#2839) * update workspace spec sha * remove yamls from branch * BLS spec tests (#2826) (#2856) * bls spec tests * add more bls tests * use ioutil instead of bazel runfiles * dont read bytes * skip tests that overflow uint64 * manually fix input data * add tests * lint and gaz * add all new changes * some refactoring, cleanup, remove new API methods that only exist for tests * gaz * Remove yamls, skip test * Slot processing spec test (#2813) * eth1data rpc endpoint (#2733) * eth1data rpc endpoint * first version * comment added * gazelle fix * new function to go once over the deposit array * fix tests * export DepositContainer * terence feedback * move structure decleration * binary search * fix block into Block * preston feedback * keep slice sorted to remove overhead in retrival * merge changes * feedback * update to the latest go-ssz * revert change * chnages to fit new ssz * revert merge reversion * go fmt goimprts duplicate string * exception for lint unused doesParentExist * feedback changes * latesteth1data to eth1data * goimports and stop exposing Eth1Data * revert unneeded change * remove exposure of DepositContainer * feedback and fixes * fix workspace duplicate dependancy * greatest number of deposits at current height * add count votes function * change method name * revert back to latesteth1data * latesteth1data * preston feedback * seperate function add tests fix bug * stop exposing voteCountMap * eth1data comment fix * preston feedback * fix tests * new proto files * workspace to default version of ssz * new ssz * chnage test size * marshalled marshaled * Attesting Indices Fix (#2862) * add change * fix one test * fix all tests * add test * clear cache * removed old chaintest, simulated backend and state generator (#2863) * Block Processing Sanity Spec Tests (#2817) * update PrevEpoch * add new changes * shift to blocks package * add more changes * new changes * updated pb with size tags * add new changes * fix errors * uncomment code * more changes * add new changes * rename and lint * gaz * more changes * proccess slot SigningRoot instead of HashTreeRoot * ensure yaml generated structs work * block sanity all passing * minimal and mainnet all pass * remove commented code * fix one test * fix all tests * fix again * no state comparison * matching spec * change target viz * comments gazelle * clear caches before test cases * latest attempts * clean up test format * remove debugging log, remove yaml * unskip attestation * remove skip, check post state, diff state diffs * handle err * add bug fixes * fixed one more bug * fixed churn limit bug * change hashProto to HashTreeRoot * all tests pass :) * fix all tests * gaz * add regression tests * fix test bug * Mutation testing fixes for beacon-chain/core/helpers/attestation.go (#2868) * mutation testing for attestation.go * new line * lint * revert fmt.Errorf deletion * gofmt * Add some fixes for mutation testing on blocks.go (#2869) * Fix sizes * gaz * Spec freeze release candidate spectests * Align Protobuf Type Names (#2872) * Removes some deprecated fields from protobuf (#2877) * search and replace checkpoints * fix tests, except spec tests * Update Configs for Freeze (#2876) * update configs * updated minimal configs * almost there * all tests passing except for spec tests * better comment for MinGenesisTime * done, ready for review * rm seconds per day * feedback * Mutation testing fixes for beacon-chain/core/helpers/committee.go (#2870) * Add some fixes for mutation testing on blocks.go * working on mutation testing fo committee.go * gofmt * goimports * update readme target * update latest sha for spec tests * fix build * Update State Transition Function (#2867) * Change Base Reward Factor (#2888) * Update Freeze Spec Simplification Section - part 1 (#2893) * finished changes to attesting_indices * removed index_count <= 2**40 requirement * lint * reverted index_count <= 2**40 check * added short cut len(a) > len(b) * Update justification bits (#2894) * updated all the helper pseudocodes (#2895) * Make Constants Explicit and Minor Cleanups (#2898) * Rename outdated configs, make constants explicitly delcared * Remove activate_validator, not needed * Remove GenesisSlot and GenesisEpoch * Remove unused import * Move Block Operation Length Checks to ProcessOperations (#2900) * Move block operation length checks to ProcessOperations * Write tests for each length check in ProcessOperations * Remove unneeded test * Move checks to a new function * Move duplicate check back into ProcessOperations * reorder proto fields (#2902) * Slashing Penalty Calculation Change (#2889) * lint * change config val * add max helper * changes to slashing and process slashing, add a min function for integers * gaz * fix failing tests * fix test * fixed all tests * Change Yaml tag * lint * remove gc hack * fix test * gaz * preston's comments * change failing field * fix and regen proto * lint * Implement Compact Committee Root (#2897) * add tags * add function * add new code * add function * add all new changes * lint * add tests * fix tests * fix more tests * fix all outstanding tests * gaz * Update beacon-chain/core/helpers/committee.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * comment * Remove deprecated fields from attestation data (#2892) * fix broken tests * remove comment * fixes * Update Deposit Contract (#2903) * update to new contract * fix references * fix tests * fix some more tests * fix local deposit trie * gaz * shays review * more changes * update WORKSPACE to use 0.8 spec tests * Perform Mutesting in Helpers Package (#2912) * Perform mutesting on validator * Mutesting in helpers package * Mutested eth1data * s/volundary/voluntary (#2914) * Update BLS Domain (#2916) * change from integer to byte slice * add test * fix func for bytes4 * Fix Spec tests (#2907) * fix panics * handle failed transitions * remove log * fix to protos * new changes * remove i * change ssz commit * new changes * update epoch tests * fix epoch testing * fix shuffle tests * fix test * Perform Mutesting in Epoch and State Packages (#2913) * done with updates (#2890) * Add Max Size Tag for Protobuf Fields (#2908) * No more space between ssz-size numbers * Regen pb.go * Fixed a few incorrect proto fields (#2926) * Update Validator Workflow (#2906) * Justification spec tests (#2896) * update go-ssz * Fix SSZ Compatibility Test (#2924) * figuring out how to seqeeze in multiple fields in a tag for pb * Added max tags and regenerated pb.go * updated to new standard * New bitfield types in proto (#2915) * Cast bytes to correct bitfield, failing tests now though * Add forked gogo/protobuf until https://github.com/gogo/protobuf/pull/582 * remove newline * use proper override for gogo-protobuf * fix a few tags * forgot to include custody bits and Slashable not used * Update yaml struct to use pb * Update workspace to use latest ssz * All tests fail * Use the latest go-ssz commit * All pass except for state (too long to taste) * Update test.proto * Added rest of the tests * use 1 justification bits * fix tag test, apply @rauljordan's suggestion * add IsEmpty and use ssz struct * delete unused file * Update zero hash to sha256().digest() (#2932) * update zero hash * change zero hash to conform with spec * goimports * add test for zero hash * Revert "Update zero hash to sha256().digest() (#2932)" (#2933) This reverts commit b926ae0667b18aef3f7e0e8ec8a9b3e98b3d2ccc. * Fix compress validator (#2936) * fix compress validator * update go-ssz * build without the bytes test * try minimal * Block operations spec tests (#2828) * update PrevEpoch * debugging proposer slashing tests * fmt * add deposit tests * Added skeleton for attestation minimal test * remove bazel runfiles thing * add deposits * proposer slashing test is done * comment * complete test, some failing cases * sig verify on * refactor slightly to support mainnet and minimal * included mainnet stuff * Add block header tests * volunary exit done * transfer done * new changes * fix all tests * update domain functions * fmt * fixed lint * fixed all the tests * fixed a transfer bug * finished attester slashing tests and fixed a few bugs * started fixing... * cleaned up exit and proposr slashing tests * attester slashing passing * refactored deposit tests * remove yamls, update ssz * Added todo for invalid sig * gazelle * deposits test done! * transfer tests done and pass! * fix attesting indices bug * temporarily disabled signature verification * cleaned up most of the block ops, except for att * update committee AttestingIndices * oops, i dont know how or why i changed this file * fixed all the rpc tests * 6 more failing packages * test max transfer in state package * replace hashproto with treehash in package blockchain * gazelle * fix test * fix test again * fixed transition test, 2 more left * expect an error in attestation tests * Handle panic when no votes in aggregate attestation * clear cache * Add differ, add logging, tests pass yay * remove todo, add tag * fixed TestReceiveBlock_RemovesPendingDeposits * TestAttestationMinimal/success_since_max_epochs_per_crosslink fails now... * handle panics * Transfer tests were disabled in https://github.com/ethereum/eth2.0-specs/pull/1238 * more fixes after merge, updating block_operations.yaml.go to match yaml * figuring out how to seqeeze in multiple fields in a tag for pb * Added max tags and regenerated pb.go * updated to new standard * New bitfield types in proto (#2915) * Cast bytes to correct bitfield, failing tests now though * Add forked gogo/protobuf until https://github.com/gogo/protobuf/pull/582 * remove newline * fix references and test panic * change to proto objects from custom types * fix panics in tests * use proper override for gogo-protobuf * fix a few tags * fix tests * forgot to include custody bits and Slashable not used * fix tests * sort again * Update yaml struct to use pb * Update workspace to use latest ssz * All tests fail * Use the latest go-ssz commit * All pass except for state (too long to taste) * Update test.proto * Added rest of the tests * use 1 justification bits * minor fixes * wrong proto.Equal * fix tag test, apply @rauljordan's suggestion * add IsEmpty and use ssz struct * inverted logic * update zero hash * change zero hash to conform with spec * goimports * add test for zero hash * Revert "Update zero hash to sha256().digest() (#2932)" This reverts commit b926ae0667b18aef3f7e0e8ec8a9b3e98b3d2ccc. * update ssz, fix import, shard big test * checkpoint * fix compress validator * update go-ssz * missing import * missing import * tests now pass * been a good day * update test size * fix lint * imports and remove unused const * update bazel jobs flag * update bazel jobs flag * satisfy deprecation warning * Add ssz regression tests for investigation of test failures in PR #2828 (#2935) * Adding regression tests for investigation * add another example * goimports * add quick comment about test case 0 * Epoch Process Slashings Spec Tests (#2930) * updated justification bits, tests passing OK * regen pb.go, clarify bit operations * justification and finalization tests; failing * Add wrapper, so we call the correct method * checkpoint * Update tar ref * TestSlashingsMinimal/small_penalty still failing * Use bigint instead of () and float * Revert a bad merge from workspace * Fmt * add note about https://github.com/ethereum/eth2.0-specs/issues/1284 * improve tests * gaz * Perform Mutesting In core/state Package (#2923) * Perform mutesting on validator * Mutesting in helpers package * Mutested eth1data * Perform mutesting in epoch and state packages * Fix voluntary exits test * Fix typo * Fix comments * Fix formatting * Fix error message * Handle missing errors * Handle all errors * Perform Mutesting In State Package * Fix block roots size * Remove comment * Fix error * add backend service * Add ssz compatibility tests for signing root (#2931) * Added tests for signing root * imports * fix lint on travis * fix bes flag * Final updates spec tests (#2901) * set up tests * need to reorder pbs * figuring out how to seqeeze in multiple fields in a tag for pb * Added max tags and regenerated pb.go * updated to new standard * New bitfield types in proto (#2915) * Cast bytes to correct bitfield, failing tests now though * Add forked gogo/protobuf until https://github.com/gogo/protobuf/pull/582 * remove newline * use proper override for gogo-protobuf * fix a few tags * forgot to include custody bits and Slashable not used * playing with tags idea, can revert this commit later * fixes after merge * reset caches before test * all epoch tests pass * gazelle * Genesis trigger (#2905) * genesis change * integrate changes * bodyroot * remove unused code * HasChainStarted * added isValidGenesisState to ProcessLog * state fix * fix gazelle * uint64 timestamp * SetupInitialDeposits adds proof * remove unneeded parts of test * deposithash * merkleproof from spec utils * Revert "merkleproof from spec utils" This reverts commit 1b0a124352e7b62e3c3220fb0d64e295b474b430. * fix test failures * chain started and hashtree root in tests * simple eth2genesistime * eth2 genesis time * fix zero time * add comment * remove eth1data and feedback * fix build issues * main changes: add fields and methods to track active validator count * gaz * fix test * fix more tests * improve test utils * shift spec method to state package, improve test setup * fixed log processing tests * remove log * gaz * fix invalid metric * use better tag names, not latest * Remove Block Signing Root (#2945) * replace with hash tree root * Revert "replace with hash tree root" This reverts commit 77d8f16a160e42f3c3d598df66c30a66657de1bf. * replace with signing root instead * remove one more ref * Create Test Runner for Genesis State Spec Tests (#2940) * genesis change * integrate changes * bodyroot * remove unused code * HasChainStarted * added isValidGenesisState to ProcessLog * state fix * fix gazelle * uint64 timestamp * SetupInitialDeposits adds proof * remove unneeded parts of test * deposithash * merkleproof from spec utils * Revert "merkleproof from spec utils" This reverts commit 1b0a124352e7b62e3c3220fb0d64e295b474b430. * fix test failures * chain started and hashtree root in tests * simple eth2genesistime * eth2 genesis time * fix zero time * add comment * remove eth1data and feedback * fix build issues * main changes: add fields and methods to track active validator count * gaz * fix test * fix more tests * improve test utils * Start genesis spec tests * shift spec method to state package, improve test setup * Add Genesis validity spec test * Bazel * fixed log processing tests * remove log * gaz * fix invalid metric * use json tags * fix up latest changes * Fix most of test errors * Attempts to see whats wrong with genesis validity * Fix merge * skip minimal * fix state test * new commit * fix nishant comment * gaz * Static check on branch spec-v0.6 (#2946) * Ran staticcheck and fixed the important complains * commit * commit * Create Test Runner for Genesis State Spec Tests (#2940) * genesis change * integrate changes * bodyroot * remove unused code * HasChainStarted * added isValidGenesisState to ProcessLog * state fix * fix gazelle * uint64 timestamp * SetupInitialDeposits adds proof * remove unneeded parts of test * deposithash * merkleproof from spec utils * Revert "merkleproof from spec utils" This reverts commit 1b0a124352e7b62e3c3220fb0d64e295b474b430. * fix test failures * chain started and hashtree root in tests * simple eth2genesistime * eth2 genesis time * fix zero time * add comment * remove eth1data and feedback * fix build issues * main changes: add fields and methods to track active validator count * gaz * fix test * fix more tests * improve test utils * Start genesis spec tests * shift spec method to state package, improve test setup * Add Genesis validity spec test * Bazel * fixed log processing tests * remove log * gaz * fix invalid metric * use json tags * fix up latest changes * Fix most of test errors * Attempts to see whats wrong with genesis validity * Fix merge * skip minimal * fix state test * new commit * fix nishant comment * gaz * Add Back Eth1Data After Bad Merge (#2953) * eth1data rpc endpoint * first version * comment added * gazelle fix * new function to go once over the deposit array * fix tests * export DepositContainer * terence feedback * move structure decleration * binary search * fix block into Block * preston feedback * keep slice sorted to remove overhead in retrival * merge changes * feedback * update to the latest go-ssz * revert change * chnages to fit new ssz * revert merge reversion * go fmt goimprts duplicate string * exception for lint unused doesParentExist * feedback changes * latesteth1data to eth1data * goimports and stop exposing Eth1Data * revert unneeded change * remove exposure of DepositContainer * feedback and fixes * fix workspace duplicate dependancy * greatest number of deposits at current height * add count votes function * change method name * revert back to latesteth1data * latesteth1data * preston feedback * seperate function add tests fix bug * stop exposing voteCountMap * eth1data comment fix * preston feedback * fix tests * new proto files * workspace to default version of ssz * new ssz * chnage test size * marshalled marshaled * everything passing again * add skip reason * cleanup deposit contract slightly * remove unused chainstart param (#2957) * fix breakages from #2957 (#2958) * fix breakages from #2957 * oops * Fix deposit input data (#2956) * fix deposit input data * fix deposit input data * gaz and build fix * Add Tests for Genesis Deposits Caching (#2952) * remove old method and replace with an improved one * add new files * gaz * add test * added all these tests * gaz * Apply suggestions from code review Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * fix merkle proof error * fix config * Minor fixes for runtime (#2960) * Minor fixes for runtime * use comments * goimports * revert beacon-chain/core/state/state.go and fix comment for lint * fix test too * Minor runtime fixes (#2961) * Add support for bundling binaries and fix ARM64 builds (#2970) * Add support for bundling binaries and fix ARM64 builds * Fix exports * ignore manual targets wrt vis check * fix graknlabs * update spec tests (#2979) * hotfix until https://github.com/graknlabs/bazel-distribution/pull/169 * Overflow slashing calculation fix (#2977) * Runtime Fixes (#2736) * first batch of fixes * add log * more fixes * another bug fixed * update deposit contract and other fixes * remove logs * new changes * fixes * fix build * remove config * more fixes * add more changes * add back todo * make compute state root work * remove commented out and fix condition * fix commented code * fix config * gaz * remove flag * remove init * new fixes * fix test * one more fix * fix all tests * change back config * fix one more bug * remove logging bool * Only build test targets when running bazel test //... * Align prysm to spec v0.8.1 (#2978) * Bazel problem * Update zero hash representation to be clear (cosmetic) * Update minor cosmetic fixes * Fixed lookahead off by 1 * Update randao.go * update ssz * test failures fixed * test fixes * fix up workspace * lint * fixed errs * Updated pubkey loggings (#2983) * Fix proposer assignment (#2984) * add jvm limits * add jvm limits * Removed logging from state transition functions (#2980) * Match spec on proposer index division (#2985) * Match spec on proposer index division * gaz * fixes * Fix Default Eth1Data (#2982) * fix bug * Update beacon-chain/core/state/transition.go Co-Authored-By: Raul Jordan <raul@prysmaticlabs.com> * more fixes * reg test * Set ejection balance to 1.6 (#2987) * improve block processing log (#2990) * Fix HistoricalRootsLimit (#2989) * fix historical lenght * fix genesis state initialization and test * fix genesis state initialization and test * fix genesis state initialization and test * fix genesis state initialization and test * hack config until https://github.com/prysmaticlabs/prysm/issues/2993 * More Runtime Fixes (#2986) * local changes * add val sig * attester fix * one more fix * fixed all tests * rem validator issue * fix finality issue (#2994) * Fix validator prev balance calculation (#2992) * attester fix * one more fix * fixed all tests * Fix validator prev balances calculation * go fmt * 48 bytes * Fix Querier to handle Deposit Logs Race (#2999) * fix sync issue * fix build * add regression test * add var for magic number * Fix eth1data and deposits (#2996) * Work in progress, eth1data works, deposits are included at the appropriate time, and activation happens at the correct time * revert blockInfo being public * git tests to build, not yet pass though * add tests * some commentary * fix comment * goimports * fmt and remove unused method * Update rules go (#2975) * update rules_go * Fix some cross compile builds stuff * add missing deps * update to 0.19.1 * Update Protobufs to Match Ethereum APIs (#2998) * add beacon block and attestation files * add all types * include all new proto type definitions * add add all proto definitions * fix all comments to say 48 bytes * include latest changes * readd common * no swag * add build file * deps issue * right package names * address feedback, maintain parity between upstream ethereumapis * delete pb * bad gens * Update "Testing Prysm" readme section (#3000) Resolves invalid url link to golangci-lint. * Update badge to version 0.8.1 * elaborate on test skip * revert shared/p2p/options.go * make travis happy with goimports * Update beacon-chain/core/blocks/block.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com>
1180 lines
46 KiB
Go
1180 lines
46 KiB
Go
package blocks
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"errors"
|
|
"fmt"
|
|
"reflect"
|
|
"sort"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
"github.com/prysmaticlabs/go-ssz"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/cache"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/state/stateutils"
|
|
v "github.com/prysmaticlabs/prysm/beacon-chain/core/validators"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/hashutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"github.com/prysmaticlabs/prysm/shared/sliceutil"
|
|
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
|
)
|
|
|
|
var eth1DataCache = cache.NewEth1DataVoteCache()
|
|
|
|
// VerifyProposerSignature uses BLS signature verification to ensure
|
|
// the correct proposer created an incoming beacon block during state
|
|
// transition processing.
|
|
//
|
|
// WIP - this is stubbed out until BLS is integrated into Prysm.
|
|
func VerifyProposerSignature(
|
|
_ *pb.BeaconBlock,
|
|
) error {
|
|
return nil
|
|
}
|
|
|
|
// ProcessEth1DataInBlock is an operation performed on each
|
|
// beacon block to ensure the ETH1 data votes are processed
|
|
// into the beacon state.
|
|
//
|
|
// Official spec definition:
|
|
// def process_eth1_data(state: BeaconState, body: BeaconBlockBody) -> None:
|
|
// state.eth1_data_votes.append(body.eth1_data)
|
|
// if state.eth1_data_votes.count(body.eth1_data) * 2 > SLOTS_PER_ETH1_VOTING_PERIOD:
|
|
// state.latest_eth1_data = body.eth1_data
|
|
func ProcessEth1DataInBlock(beaconState *pb.BeaconState, block *pb.BeaconBlock) (*pb.BeaconState, error) {
|
|
beaconState.Eth1DataVotes = append(beaconState.Eth1DataVotes, block.Body.Eth1Data)
|
|
|
|
hasSupport, err := Eth1DataHasEnoughSupport(beaconState, block.Body.Eth1Data)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if hasSupport {
|
|
beaconState.Eth1Data = block.Body.Eth1Data
|
|
}
|
|
|
|
return beaconState, nil
|
|
}
|
|
|
|
// Eth1DataHasEnoughSupport returns true when the given eth1data has more than 50% votes in the
|
|
// eth1 voting period. A vote is cast by including eth1data in a block and part of state processing
|
|
// appends eth1data to the state in the Eth1DataVotes list. Iterating through this list checks the
|
|
// votes to see if they match the eth1data.
|
|
func Eth1DataHasEnoughSupport(beaconState *pb.BeaconState, data *pb.Eth1Data) (bool, error) {
|
|
voteCount, err := eth1DataCache.Eth1DataVote(data.DepositRoot)
|
|
if err != nil {
|
|
return false, fmt.Errorf("could not retrieve eth1 data vote cache: %v", err)
|
|
}
|
|
|
|
if voteCount == 0 {
|
|
for _, vote := range beaconState.Eth1DataVotes {
|
|
if proto.Equal(vote, data) {
|
|
voteCount++
|
|
}
|
|
}
|
|
} else {
|
|
voteCount++
|
|
}
|
|
|
|
if err := eth1DataCache.AddEth1DataVote(&cache.Eth1DataVote{
|
|
DepositRoot: data.DepositRoot,
|
|
VoteCount: voteCount,
|
|
}); err != nil {
|
|
return false, fmt.Errorf("could not save eth1 data vote cache: %v", err)
|
|
}
|
|
|
|
// If 50+% majority converged on the same eth1data, then it has enough support to update the
|
|
// state.
|
|
return voteCount*2 > params.BeaconConfig().SlotsPerEth1VotingPeriod, nil
|
|
}
|
|
|
|
// ProcessBlockHeader validates a block by its header.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
// def process_block_header(state: BeaconState, block: BeaconBlock) -> None:
|
|
// # Verify that the slots match
|
|
// assert block.slot == state.slot
|
|
// # Verify that the parent matches
|
|
// assert block.parent_root == signing_root(state.latest_block_header)
|
|
// # Save current block as the new latest block
|
|
// state.latest_block_header = BeaconBlockHeader(
|
|
// slot=block.slot,
|
|
// parent_root=block.parent_root,
|
|
// # state_root: zeroed, overwritten in the next `process_slot` call
|
|
// body_root=hash_tree_root(block.body),
|
|
// # signature is always zeroed
|
|
// )
|
|
// # Verify proposer is not slashed
|
|
// proposer = state.validators[get_beacon_proposer_index(state)]
|
|
// assert not proposer.slashed
|
|
// # Verify proposer signature
|
|
// assert bls_verify(proposer.pubkey, signing_root(block), block.signature, get_domain(state, DOMAIN_BEACON_PROPOSER))
|
|
func ProcessBlockHeader(
|
|
beaconState *pb.BeaconState,
|
|
block *pb.BeaconBlock,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
if beaconState.Slot != block.Slot {
|
|
return nil, fmt.Errorf("state slot: %d is different then block slot: %d", beaconState.Slot, block.Slot)
|
|
}
|
|
|
|
parentRoot, err := ssz.SigningRoot(beaconState.LatestBlockHeader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if !bytes.Equal(block.ParentRoot, parentRoot[:]) {
|
|
return nil, fmt.Errorf(
|
|
"parent root %#x does not match the latest block header signing root in state %#x",
|
|
block.ParentRoot, parentRoot)
|
|
}
|
|
|
|
bodyRoot, err := ssz.HashTreeRoot(block.Body)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
emptySig := make([]byte, 96)
|
|
beaconState.LatestBlockHeader = &pb.BeaconBlockHeader{
|
|
Slot: block.Slot,
|
|
ParentRoot: block.ParentRoot,
|
|
StateRoot: params.BeaconConfig().ZeroHash[:],
|
|
BodyRoot: bodyRoot[:],
|
|
Signature: emptySig,
|
|
}
|
|
// Verify proposer is not slashed.
|
|
idx, err := helpers.BeaconProposerIndex(beaconState)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
proposer := beaconState.Validators[idx]
|
|
if proposer.Slashed {
|
|
return nil, fmt.Errorf("proposer at index %d was previously slashed", idx)
|
|
}
|
|
if verifySignatures {
|
|
pub, err := bls.PublicKeyFromBytes(proposer.Pubkey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not deserialize proposer public key: %v", err)
|
|
}
|
|
domain := helpers.Domain(beaconState, helpers.SlotToEpoch(block.Slot), params.BeaconConfig().DomainBeaconProposer)
|
|
sig, err := bls.SignatureFromBytes(block.Signature)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not convert bytes to signature: %v", err)
|
|
}
|
|
root, err := ssz.SigningRoot(block)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not sign root for header: %v", err)
|
|
}
|
|
if !sig.Verify(root[:], pub, domain) {
|
|
return nil, fmt.Errorf("block signature did not verify")
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
// ProcessRandao checks the block proposer's
|
|
// randao commitment and generates a new randao mix to update
|
|
// in the beacon state's latest randao mixes slice.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_randao(state: BeaconState, body: BeaconBlockBody) -> None:
|
|
// proposer = state.validator_registry[get_beacon_proposer_index(state)]
|
|
// # Verify that the provided randao value is valid
|
|
// assert bls_verify(
|
|
// proposer.pubkey,
|
|
// hash_tree_root(get_current_epoch(state)),
|
|
// body.randao_reveal,
|
|
// get_domain(state, DOMAIN_RANDAO),
|
|
// )
|
|
// # Mix it in
|
|
// state.latest_randao_mixes[get_current_epoch(state) % LATEST_RANDAO_MIXES_LENGTH] = (
|
|
// xor(get_randao_mix(state, get_current_epoch(state)),
|
|
// hash(body.randao_reveal))
|
|
// )
|
|
func ProcessRandao(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
if verifySignatures {
|
|
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get beacon proposer index: %v", err)
|
|
}
|
|
|
|
if err := verifyBlockRandao(beaconState, body, proposerIdx); err != nil {
|
|
return nil, fmt.Errorf("could not verify block randao: %v", err)
|
|
}
|
|
}
|
|
// If block randao passed verification, we XOR the state's latest randao mix with the block's
|
|
// randao and update the state's corresponding latest randao mix value.
|
|
latestMixesLength := params.BeaconConfig().EpochsPerHistoricalVector
|
|
currentEpoch := helpers.CurrentEpoch(beaconState)
|
|
latestMixSlice := beaconState.RandaoMixes[currentEpoch%latestMixesLength]
|
|
blockRandaoReveal := hashutil.Hash(body.RandaoReveal)
|
|
for i, x := range blockRandaoReveal {
|
|
latestMixSlice[i] ^= x
|
|
}
|
|
beaconState.RandaoMixes[currentEpoch%latestMixesLength] = latestMixSlice
|
|
return beaconState, nil
|
|
}
|
|
|
|
// Verify that bls_verify(proposer.pubkey, hash_tree_root(get_current_epoch(state)),
|
|
// block.body.randao_reveal, domain=get_domain(state.fork, get_current_epoch(state), DOMAIN_RANDAO))
|
|
func verifyBlockRandao(beaconState *pb.BeaconState, body *pb.BeaconBlockBody, proposerIdx uint64) error {
|
|
proposer := beaconState.Validators[proposerIdx]
|
|
pub, err := bls.PublicKeyFromBytes(proposer.Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize proposer public key: %v", err)
|
|
}
|
|
currentEpoch := helpers.CurrentEpoch(beaconState)
|
|
buf := make([]byte, 32)
|
|
binary.LittleEndian.PutUint64(buf, currentEpoch)
|
|
domain := helpers.Domain(beaconState, currentEpoch, params.BeaconConfig().DomainRandao)
|
|
sig, err := bls.SignatureFromBytes(body.RandaoReveal)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize block randao reveal: %v", err)
|
|
}
|
|
|
|
if !sig.Verify(buf, pub, domain) {
|
|
return fmt.Errorf("block randao reveal signature did not verify")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ProcessProposerSlashings is one of the operations performed
|
|
// on each processed beacon block to slash proposers based on
|
|
// slashing conditions if any slashable events occurred.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_proposer_slashing(state: BeaconState, proposer_slashing: ProposerSlashing) -> None:
|
|
// """
|
|
// Process ``ProposerSlashing`` operation.
|
|
// """
|
|
// proposer = state.validator_registry[proposer_slashing.proposer_index]
|
|
// # Verify that the epoch is the same
|
|
// assert slot_to_epoch(proposer_slashing.header_1.slot) == slot_to_epoch(proposer_slashing.header_2.slot)
|
|
// # But the headers are different
|
|
// assert proposer_slashing.header_1 != proposer_slashing.header_2
|
|
// # Check proposer is slashable
|
|
// assert is_slashable_validator(proposer, get_current_epoch(state))
|
|
// # Signatures are valid
|
|
// for header in (proposer_slashing.header_1, proposer_slashing.header_2):
|
|
// domain = get_domain(state, DOMAIN_BEACON_PROPOSER, slot_to_epoch(header.slot))
|
|
// assert bls_verify(proposer.pubkey, signing_root(header), header.signature, domain)
|
|
//
|
|
// slash_validator(state, proposer_slashing.proposer_index)
|
|
func ProcessProposerSlashings(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
var err error
|
|
for idx, slashing := range body.ProposerSlashings {
|
|
if int(slashing.ProposerIndex) >= len(beaconState.Validators) {
|
|
return nil, fmt.Errorf("invalid proposer index given in slashing %d", slashing.ProposerIndex)
|
|
}
|
|
proposer := beaconState.Validators[slashing.ProposerIndex]
|
|
if err = verifyProposerSlashing(beaconState, proposer, slashing, verifySignatures); err != nil {
|
|
return nil, fmt.Errorf("could not verify proposer slashing %d: %v", idx, err)
|
|
}
|
|
beaconState, err = v.SlashValidator(
|
|
beaconState, slashing.ProposerIndex, 0, /* proposer is whistleblower */
|
|
)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not slash proposer index %d: %v",
|
|
slashing.ProposerIndex, err)
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
func verifyProposerSlashing(
|
|
beaconState *pb.BeaconState,
|
|
proposer *pb.Validator,
|
|
slashing *pb.ProposerSlashing,
|
|
verifySignatures bool,
|
|
) error {
|
|
headerEpoch1 := helpers.SlotToEpoch(slashing.Header_1.Slot)
|
|
headerEpoch2 := helpers.SlotToEpoch(slashing.Header_2.Slot)
|
|
if headerEpoch1 != headerEpoch2 {
|
|
return fmt.Errorf("mismatched header epochs, received %d == %d", headerEpoch1, headerEpoch2)
|
|
}
|
|
if proto.Equal(slashing.Header_1, slashing.Header_2) {
|
|
return errors.New("expected slashing headers to differ")
|
|
}
|
|
if !helpers.IsSlashableValidator(proposer, helpers.CurrentEpoch(beaconState)) {
|
|
return fmt.Errorf("validator with key %#x is not slashable", proposer.Pubkey)
|
|
}
|
|
|
|
if verifySignatures {
|
|
pub, err := bls.PublicKeyFromBytes(proposer.Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize proposer public key: %v", err)
|
|
}
|
|
headers := append([]*pb.BeaconBlockHeader{slashing.Header_1}, slashing.Header_2)
|
|
for _, header := range headers {
|
|
domain := helpers.Domain(beaconState, helpers.SlotToEpoch(header.Slot), params.BeaconConfig().DomainBeaconProposer)
|
|
sig, err := bls.SignatureFromBytes(header.Signature)
|
|
if err != nil {
|
|
return fmt.Errorf("could not convert bytes to signature: %v", err)
|
|
}
|
|
root, err := ssz.SigningRoot(header)
|
|
if err != nil {
|
|
return fmt.Errorf("could not sign root for header: %v", err)
|
|
}
|
|
if !sig.Verify(root[:], pub, domain) {
|
|
return fmt.Errorf("proposer slashing signature did not verify")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ProcessAttesterSlashings is one of the operations performed
|
|
// on each processed beacon block to slash attesters based on
|
|
// Casper FFG slashing conditions if any slashable events occurred.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_attester_slashing(state: BeaconState, attester_slashing: AttesterSlashing) -> None:
|
|
// """
|
|
// Process ``AttesterSlashing`` operation.
|
|
// """
|
|
// attestation_1 = attester_slashing.attestation_1
|
|
// attestation_2 = attester_slashing.attestation_2
|
|
// assert is_slashable_attestation_data(attestation_1.data, attestation_2.data)
|
|
// validate_indexed_attestation(state, attestation_1)
|
|
// validate_indexed_attestation(state, attestation_2)
|
|
//
|
|
// slashed_any = False
|
|
// attesting_indices_1 = attestation_1.custody_bit_0_indices + attestation_1.custody_bit_1_indices
|
|
// attesting_indices_2 = attestation_2.custody_bit_0_indices + attestation_2.custody_bit_1_indices
|
|
// for index in sorted(set(attesting_indices_1).intersection(attesting_indices_2)):
|
|
// if is_slashable_validator(state.validators[index], get_current_epoch(state)):
|
|
// slash_validator(state, index)
|
|
// slashed_any = True
|
|
// assert slashed_any
|
|
func ProcessAttesterSlashings(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
for idx, slashing := range body.AttesterSlashings {
|
|
if err := verifyAttesterSlashing(beaconState, slashing, verifySignatures); err != nil {
|
|
return nil, fmt.Errorf("could not verify attester slashing #%d: %v", idx, err)
|
|
}
|
|
slashableIndices := slashableAttesterIndices(slashing)
|
|
sort.SliceStable(slashableIndices, func(i, j int) bool {
|
|
return slashableIndices[i] < slashableIndices[j]
|
|
})
|
|
currentEpoch := helpers.CurrentEpoch(beaconState)
|
|
var err error
|
|
var slashedAny bool
|
|
for _, validatorIndex := range slashableIndices {
|
|
if helpers.IsSlashableValidator(beaconState.Validators[validatorIndex], currentEpoch) {
|
|
beaconState, err = v.SlashValidator(beaconState, validatorIndex, 0)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not slash validator index %d: %v",
|
|
validatorIndex, err)
|
|
}
|
|
slashedAny = true
|
|
}
|
|
}
|
|
if !slashedAny {
|
|
return nil, errors.New("unable to slash any validator despite confirmed attester slashing")
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
func verifyAttesterSlashing(beaconState *pb.BeaconState, slashing *pb.AttesterSlashing, verifySignatures bool) error {
|
|
att1 := slashing.Attestation_1
|
|
att2 := slashing.Attestation_2
|
|
data1 := att1.Data
|
|
data2 := att2.Data
|
|
if !IsSlashableAttestationData(data1, data2) {
|
|
return errors.New("attestations are not slashable")
|
|
}
|
|
if err := VerifyIndexedAttestation(beaconState, att1, verifySignatures); err != nil {
|
|
return fmt.Errorf("could not validate indexed attestation: %v", err)
|
|
}
|
|
if err := VerifyIndexedAttestation(beaconState, att2, verifySignatures); err != nil {
|
|
return fmt.Errorf("could not validate indexed attestation: %v", err)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// IsSlashableAttestationData verifies a slashing against the Casper Proof of Stake FFG rules.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def is_slashable_attestation_data(data_1: AttestationData, data_2: AttestationData) -> bool:
|
|
// """
|
|
// Check if ``data_1`` and ``data_2`` are slashable according to Casper FFG rules.
|
|
// """
|
|
// return (
|
|
// # Double vote
|
|
// (data_1 != data_2 and data_1.target.epoch == data_2.target.epoch) or
|
|
// # Surround vote
|
|
// (data_1.source.epoch < data_2.source.epoch and data_2.target.epoch < data_1.target.epoch)
|
|
// )
|
|
func IsSlashableAttestationData(data1 *pb.AttestationData, data2 *pb.AttestationData) bool {
|
|
isDoubleVote := !proto.Equal(data1, data2) && data1.Target.Epoch == data2.Target.Epoch
|
|
isSurroundVote := data1.Source.Epoch < data2.Source.Epoch && data2.Target.Epoch < data1.Target.Epoch
|
|
return isDoubleVote || isSurroundVote
|
|
}
|
|
|
|
func slashableAttesterIndices(slashing *pb.AttesterSlashing) []uint64 {
|
|
att1 := slashing.Attestation_1
|
|
att2 := slashing.Attestation_1
|
|
indices1 := append(att1.CustodyBit_0Indices, att1.CustodyBit_1Indices...)
|
|
indices2 := append(att2.CustodyBit_0Indices, att2.CustodyBit_1Indices...)
|
|
return sliceutil.IntersectionUint64(indices1, indices2)
|
|
}
|
|
|
|
// ProcessAttestations applies processing operations to a block's inner attestation
|
|
// records. This function returns a list of pending attestations which can then be
|
|
// appended to the BeaconState's latest attestations.
|
|
func ProcessAttestations(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
var err error
|
|
for idx, attestation := range body.Attestations {
|
|
beaconState, err = ProcessAttestation(beaconState, attestation, verifySignatures)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not verify attestation at index %d in block: %v", idx, err)
|
|
}
|
|
}
|
|
|
|
return beaconState, nil
|
|
}
|
|
|
|
// ProcessAttestation verifies an input attestation can pass through processing using the given beacon state.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_attestation(state: BeaconState, attestation: Attestation) -> None:
|
|
// """
|
|
// Process ``Attestation`` operation.
|
|
// """
|
|
// data = attestation.data
|
|
// attestation_slot = get_attestation_data_slot(state, data)
|
|
// assert attestation_slot + MIN_ATTESTATION_INCLUSION_DELAY <= state.slot <= attestation_slot + SLOTS_PER_EPOCH
|
|
//
|
|
// pending_attestation = PendingAttestation(
|
|
// data=data,
|
|
// aggregation_bitfield=attestation.aggregation_bitfield,
|
|
// inclusion_delay=state.slot - attestation_slot,
|
|
// proposer_index=get_beacon_proposer_index(state),
|
|
// )
|
|
//
|
|
// assert data.target_epoch in (get_previous_epoch(state), get_current_epoch(state))
|
|
// if data.target_epoch == get_current_epoch(state):
|
|
// ffg_data = (state.current_justified_epoch, state.current_justified_root, get_current_epoch(state))
|
|
// parent_crosslink = state.current_crosslinks[data.crosslink.shard]
|
|
// state.current_epoch_attestations.append(pending_attestation)
|
|
// else:
|
|
// ffg_data = (state.previous_justified_epoch, state.previous_justified_root, get_previous_epoch(state))
|
|
// parent_crosslink = state.previous_crosslinks[data.crosslink.shard]
|
|
// state.previous_epoch_attestations.append(pending_attestation)
|
|
//
|
|
// # Check FFG data, crosslink data, and signature
|
|
// assert ffg_data == (data.source_epoch, data.source_root, data.target_epoch)
|
|
// assert data.crosslink.start_epoch == parent_crosslink.end_epoch
|
|
// assert data.crosslink.end_epoch == min(data.target_epoch, parent_crosslink.end_epoch + MAX_EPOCHS_PER_CROSSLINK)
|
|
// assert data.crosslink.parent_root == hash_tree_root(parent_crosslink)
|
|
// assert data.crosslink.data_root == Bytes32() # [to be removed in phase 1]
|
|
// validate_indexed_attestation(state, convert_to_indexed(state, attestation))
|
|
func ProcessAttestation(beaconState *pb.BeaconState, att *pb.Attestation, verifySignatures bool) (*pb.BeaconState, error) {
|
|
data := att.Data
|
|
attestationSlot, err := helpers.AttestationDataSlot(beaconState, data)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get attestation slot: %v", err)
|
|
}
|
|
minInclusionCheck := attestationSlot+params.BeaconConfig().MinAttestationInclusionDelay <= beaconState.Slot
|
|
epochInclusionCheck := beaconState.Slot <= attestationSlot+params.BeaconConfig().SlotsPerEpoch
|
|
if !minInclusionCheck {
|
|
return nil, fmt.Errorf(
|
|
"attestation slot %d + inclusion delay %d > state slot %d",
|
|
attestationSlot,
|
|
params.BeaconConfig().MinAttestationInclusionDelay,
|
|
beaconState.Slot,
|
|
)
|
|
}
|
|
if !epochInclusionCheck {
|
|
return nil, fmt.Errorf(
|
|
"state slot %d > attestation slot %d + SLOTS_PER_EPOCH %d",
|
|
beaconState.Slot,
|
|
attestationSlot,
|
|
params.BeaconConfig().SlotsPerEpoch,
|
|
)
|
|
}
|
|
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
pendingAtt := &pb.PendingAttestation{
|
|
Data: data,
|
|
AggregationBits: att.AggregationBits,
|
|
InclusionDelay: beaconState.Slot - attestationSlot,
|
|
ProposerIndex: proposerIndex,
|
|
}
|
|
|
|
if !(data.Target.Epoch == helpers.PrevEpoch(beaconState) || data.Target.Epoch == helpers.CurrentEpoch(beaconState)) {
|
|
return nil, fmt.Errorf(
|
|
"expected target epoch %d == %d or %d",
|
|
data.Target.Epoch,
|
|
helpers.PrevEpoch(beaconState),
|
|
helpers.CurrentEpoch(beaconState),
|
|
)
|
|
}
|
|
|
|
var ffgSourceEpoch uint64
|
|
var ffgSourceRoot []byte
|
|
var ffgTargetEpoch uint64
|
|
var parentCrosslink *pb.Crosslink
|
|
if data.Target.Epoch == helpers.CurrentEpoch(beaconState) {
|
|
ffgSourceEpoch = beaconState.CurrentJustifiedCheckpoint.Epoch
|
|
ffgSourceRoot = beaconState.CurrentJustifiedCheckpoint.Root
|
|
ffgTargetEpoch = helpers.CurrentEpoch(beaconState)
|
|
crosslinkShard := data.Crosslink.Shard
|
|
if int(crosslinkShard) >= len(beaconState.CurrentCrosslinks) {
|
|
return nil, fmt.Errorf("invalid shard given in attestation: %d", crosslinkShard)
|
|
}
|
|
|
|
parentCrosslink = beaconState.CurrentCrosslinks[crosslinkShard]
|
|
beaconState.CurrentEpochAttestations = append(beaconState.CurrentEpochAttestations, pendingAtt)
|
|
} else {
|
|
ffgSourceEpoch = beaconState.PreviousJustifiedCheckpoint.Epoch
|
|
ffgSourceRoot = beaconState.PreviousJustifiedCheckpoint.Root
|
|
ffgTargetEpoch = helpers.PrevEpoch(beaconState)
|
|
crosslinkShard := data.Crosslink.Shard
|
|
if int(crosslinkShard) >= len(beaconState.PreviousCrosslinks) {
|
|
return nil, fmt.Errorf("invalid shard given in attestation: %d", crosslinkShard)
|
|
}
|
|
parentCrosslink = beaconState.PreviousCrosslinks[crosslinkShard]
|
|
beaconState.PreviousEpochAttestations = append(beaconState.PreviousEpochAttestations, pendingAtt)
|
|
}
|
|
if data.Source.Epoch != ffgSourceEpoch {
|
|
return nil, fmt.Errorf("expected source epoch %d, received %d", ffgSourceEpoch, data.Source.Epoch)
|
|
}
|
|
if !bytes.Equal(data.Source.Root, ffgSourceRoot) {
|
|
return nil, fmt.Errorf("expected source root %#x, received %#x", ffgSourceRoot, data.Source.Root)
|
|
}
|
|
if data.Target.Epoch != ffgTargetEpoch {
|
|
return nil, fmt.Errorf("expected target epoch %d, received %d", ffgTargetEpoch, data.Target.Epoch)
|
|
}
|
|
endEpoch := parentCrosslink.EndEpoch + params.BeaconConfig().MaxEpochsPerCrosslink
|
|
if data.Target.Epoch < endEpoch {
|
|
endEpoch = data.Target.Epoch
|
|
}
|
|
if data.Crosslink.StartEpoch != parentCrosslink.EndEpoch {
|
|
return nil, fmt.Errorf("expected crosslink start epoch %d, received %d",
|
|
parentCrosslink.EndEpoch, data.Crosslink.StartEpoch)
|
|
}
|
|
if data.Crosslink.EndEpoch != endEpoch {
|
|
return nil, fmt.Errorf("expected crosslink end epoch %d, received %d",
|
|
endEpoch, data.Crosslink.EndEpoch)
|
|
}
|
|
crosslinkParentRoot, err := ssz.HashTreeRoot(parentCrosslink)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not tree hash parent crosslink: %v", err)
|
|
}
|
|
if !bytes.Equal(data.Crosslink.ParentRoot, crosslinkParentRoot[:]) {
|
|
return nil, fmt.Errorf(
|
|
"mismatched parent crosslink root, expected %#x, received %#x",
|
|
crosslinkParentRoot,
|
|
data.Crosslink.ParentRoot,
|
|
)
|
|
}
|
|
// To be removed in Phase 1
|
|
if !bytes.Equal(data.Crosslink.DataRoot, params.BeaconConfig().ZeroHash[:]) {
|
|
return nil, fmt.Errorf("expected data root %#x == ZERO_HASH", data.Crosslink.DataRoot)
|
|
}
|
|
indexedAtt, err := ConvertToIndexed(beaconState, att)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not convert to indexed attestation: %v", err)
|
|
}
|
|
if err := VerifyIndexedAttestation(beaconState, indexedAtt, verifySignatures); err != nil {
|
|
return nil, fmt.Errorf("could not verify indexed attestation: %v", err)
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
// ConvertToIndexed converts attestation to (almost) indexed-verifiable form.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def convert_to_indexed(state: BeaconState, attestation: Attestation) -> IndexedAttestation:
|
|
// """
|
|
// Convert ``attestation`` to (almost) indexed-verifiable form.
|
|
// """
|
|
// attesting_indices = get_attesting_indices(state, attestation.data, attestation.aggregation_bitfield)
|
|
// custody_bit_1_indices = get_attesting_indices(state, attestation.data, attestation.custody_bitfield)
|
|
// assert custody_bit_1_indices.issubset(attesting_indices)
|
|
// custody_bit_0_indices = attesting_indices.difference(custody_bit_1_indices)
|
|
//
|
|
// return IndexedAttestation(
|
|
// custody_bit_0_indices=sorted(custody_bit_0_indices),
|
|
// custody_bit_1_indices=sorted(custody_bit_1_indices),
|
|
// data=attestation.data,
|
|
// signature=attestation.signature,
|
|
// )
|
|
func ConvertToIndexed(state *pb.BeaconState, attestation *pb.Attestation) (*pb.IndexedAttestation, error) {
|
|
attIndices, err := helpers.AttestingIndices(state, attestation.Data, attestation.AggregationBits)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not get attesting indices: %v", err)
|
|
}
|
|
cb1i, err := helpers.AttestingIndices(state, attestation.Data, attestation.CustodyBits)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !sliceutil.SubsetUint64(cb1i, attIndices) {
|
|
return nil, fmt.Errorf("%v is not a subset of %v", cb1i, attIndices)
|
|
}
|
|
cb1Map := make(map[uint64]bool)
|
|
for _, idx := range cb1i {
|
|
cb1Map[idx] = true
|
|
}
|
|
cb0i := []uint64{}
|
|
for _, idx := range attIndices {
|
|
if !cb1Map[idx] {
|
|
cb0i = append(cb0i, idx)
|
|
}
|
|
}
|
|
sort.Slice(cb0i, func(i, j int) bool {
|
|
return cb0i[i] < cb0i[j]
|
|
})
|
|
|
|
sort.Slice(cb1i, func(i, j int) bool {
|
|
return cb1i[i] < cb1i[j]
|
|
})
|
|
inAtt := &pb.IndexedAttestation{
|
|
Data: attestation.Data,
|
|
Signature: attestation.Signature,
|
|
CustodyBit_0Indices: cb0i,
|
|
CustodyBit_1Indices: cb1i,
|
|
}
|
|
return inAtt, nil
|
|
}
|
|
|
|
// VerifyIndexedAttestation determines the validity of an indexed attestation.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def is_valid_indexed_attestation(state: BeaconState, indexed_attestation: IndexedAttestation) -> bool:
|
|
// """
|
|
// Check if ``indexed_attestation`` has valid indices and signature.
|
|
// """
|
|
// bit_0_indices = indexed_attestation.custody_bit_0_indices
|
|
// bit_1_indices = indexed_attestation.custody_bit_1_indices
|
|
//
|
|
// # Verify no index has custody bit equal to 1 [to be removed in phase 1]
|
|
// if not len(bit_1_indices) == 0:
|
|
// return False
|
|
// # Verify max number of indices
|
|
// if not len(bit_0_indices) + len(bit_1_indices) <= MAX_VALIDATORS_PER_COMMITTEE:
|
|
// return False
|
|
// # Verify index sets are disjoint
|
|
// if not len(set(bit_0_indices).intersection(bit_1_indices)) == 0:
|
|
// return False
|
|
// # Verify indices are sorted
|
|
// if not (bit_0_indices == sorted(bit_0_indices) and bit_1_indices == sorted(bit_1_indices)):
|
|
// return False
|
|
// # Verify aggregate signature
|
|
// if not bls_verify_multiple(
|
|
// pubkeys=[
|
|
// bls_aggregate_pubkeys([state.validators[i].pubkey for i in bit_0_indices]),
|
|
// bls_aggregate_pubkeys([state.validators[i].pubkey for i in bit_1_indices]),
|
|
// ],
|
|
// message_hashes=[
|
|
// hash_tree_root(AttestationDataAndCustodyBit(data=indexed_attestation.data, custody_bit=0b0)),
|
|
// hash_tree_root(AttestationDataAndCustodyBit(data=indexed_attestation.data, custody_bit=0b1)),
|
|
// ],
|
|
// signature=indexed_attestation.signature,
|
|
// domain=get_domain(state, DOMAIN_ATTESTATION, indexed_attestation.data.target.epoch),
|
|
// ):
|
|
// return False
|
|
// return True
|
|
func VerifyIndexedAttestation(beaconState *pb.BeaconState, indexedAtt *pb.IndexedAttestation, verifySignatures bool) error {
|
|
custodyBit0Indices := indexedAtt.CustodyBit_0Indices
|
|
custodyBit1Indices := indexedAtt.CustodyBit_1Indices
|
|
|
|
// To be removed in phase 1
|
|
if len(custodyBit1Indices) != 0 {
|
|
return fmt.Errorf("expected no bit 1 indices, received %v", len(custodyBit1Indices))
|
|
}
|
|
|
|
maxIndices := params.BeaconConfig().MaxValidatorsPerCommittee
|
|
totalIndicesLength := uint64(len(custodyBit0Indices) + len(custodyBit1Indices))
|
|
if totalIndicesLength > maxIndices {
|
|
return fmt.Errorf("over max number of allowed indices per attestation: %d", totalIndicesLength)
|
|
}
|
|
custodyBitIntersection := sliceutil.IntersectionUint64(custodyBit0Indices, custodyBit1Indices)
|
|
if len(custodyBitIntersection) != 0 {
|
|
return fmt.Errorf("expected disjoint indices intersection, received %v", custodyBitIntersection)
|
|
}
|
|
|
|
copiedBit0Indices := make([]uint64, len(custodyBit0Indices))
|
|
copy(copiedBit0Indices, custodyBit0Indices)
|
|
|
|
sort.SliceStable(copiedBit0Indices, func(i, j int) bool {
|
|
return copiedBit0Indices[i] < copiedBit0Indices[j]
|
|
})
|
|
if !reflect.DeepEqual(copiedBit0Indices, custodyBit0Indices) {
|
|
return fmt.Errorf("custody Bit0 indices are not sorted, wanted %v but got %v", copiedBit0Indices, custodyBit0Indices)
|
|
}
|
|
|
|
copiedBit1Indices := make([]uint64, len(custodyBit1Indices))
|
|
copy(copiedBit1Indices, custodyBit1Indices)
|
|
|
|
sort.SliceStable(copiedBit1Indices, func(i, j int) bool {
|
|
return copiedBit1Indices[i] < copiedBit1Indices[j]
|
|
})
|
|
if len(custodyBit1Indices) > 0 && !reflect.DeepEqual(copiedBit1Indices, custodyBit1Indices) {
|
|
return fmt.Errorf("custody Bit1 indices are not sorted, wanted %v but got %v", copiedBit1Indices, custodyBit1Indices)
|
|
}
|
|
|
|
if verifySignatures {
|
|
domain := helpers.Domain(beaconState, indexedAtt.Data.Target.Epoch, params.BeaconConfig().DomainAttestation)
|
|
var pubkeys []*bls.PublicKey
|
|
if len(custodyBit0Indices) > 0 {
|
|
pubkey, err := bls.PublicKeyFromBytes(beaconState.Validators[custodyBit0Indices[0]].Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
for _, i := range custodyBit0Indices[1:] {
|
|
pk, err := bls.PublicKeyFromBytes(beaconState.Validators[i].Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
pubkey.Aggregate(pk)
|
|
}
|
|
pubkeys = append(pubkeys, pubkey)
|
|
}
|
|
if len(custodyBit1Indices) > 0 {
|
|
pubkey, err := bls.PublicKeyFromBytes(beaconState.Validators[custodyBit1Indices[0]].Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
for _, i := range custodyBit1Indices[1:] {
|
|
pk, err := bls.PublicKeyFromBytes(beaconState.Validators[i].Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
pubkey.Aggregate(pk)
|
|
}
|
|
pubkeys = append(pubkeys, pubkey)
|
|
}
|
|
|
|
cus0 := &pb.AttestationDataAndCustodyBit{Data: indexedAtt.Data, CustodyBit: false}
|
|
cus1 := &pb.AttestationDataAndCustodyBit{Data: indexedAtt.Data, CustodyBit: true}
|
|
cus0Root, err := ssz.HashTreeRoot(cus0)
|
|
if err != nil {
|
|
return fmt.Errorf("could not tree hash att data and custody bit 0: %v", err)
|
|
}
|
|
cus1Root, err := ssz.HashTreeRoot(cus1)
|
|
if err != nil {
|
|
return fmt.Errorf("could not tree hash att data and custody bit 1: %v", err)
|
|
}
|
|
msgs := append(cus0Root[:], cus1Root[:]...)
|
|
|
|
sig, err := bls.SignatureFromBytes(indexedAtt.Signature)
|
|
if err != nil {
|
|
return fmt.Errorf("could not convert bytes to signature: %v", err)
|
|
}
|
|
|
|
hasVotes := len(custodyBit0Indices) > 0 || len(custodyBit1Indices) > 0
|
|
|
|
if hasVotes && !sig.VerifyAggregate(pubkeys, msgs, domain) {
|
|
return fmt.Errorf("attestation aggregation signature did not verify")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ProcessDeposits is one of the operations performed on each processed
|
|
// beacon block to verify queued validators from the Ethereum 1.0 Deposit Contract
|
|
// into the beacon chain.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// For each deposit in block.body.deposits:
|
|
// process_deposit(state, deposit)
|
|
func ProcessDeposits(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
var err error
|
|
deposits := body.Deposits
|
|
|
|
valIndexMap := stateutils.ValidatorIndexMap(beaconState)
|
|
for _, deposit := range deposits {
|
|
beaconState, err = ProcessDeposit(beaconState, deposit, valIndexMap, verifySignatures, true)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not process deposit from %#x: %v", bytesutil.Trunc(deposit.Data.Pubkey), err)
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
// ProcessDeposit takes in a deposit object and inserts it
|
|
// into the registry as a new validator or balance change.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
|
// """
|
|
// Process an Eth1 deposit, registering a validator or increasing its balance.
|
|
// """
|
|
// # Verify the Merkle branch
|
|
// assert verify_merkle_branch(
|
|
// leaf=hash_tree_root(deposit.data),
|
|
// proof=deposit.proof,
|
|
// depth=DEPOSIT_CONTRACT_TREE_DEPTH,
|
|
// index=deposit.index,
|
|
// root=state.latest_eth1_data.deposit_root,
|
|
// )
|
|
//
|
|
// # Deposits must be processed in order
|
|
// assert deposit.index == state.deposit_index
|
|
// state.deposit_index += 1
|
|
//
|
|
// pubkey = deposit.data.pubkey
|
|
// amount = deposit.data.amount
|
|
// validator_pubkeys = [v.pubkey for v in state.validator_registry]
|
|
// if pubkey not in validator_pubkeys:
|
|
// # Verify the deposit signature (proof of possession).
|
|
// # Invalid signatures are allowed by the deposit contract, and hence included on-chain, but must not be processed.
|
|
// if not bls_verify(pubkey, signing_root(deposit.data), deposit.data.signature, get_domain(state, DOMAIN_DEPOSIT)):
|
|
// return
|
|
//
|
|
// # Add validator and balance entries
|
|
// state.validator_registry.append(Validator(
|
|
// pubkey=pubkey,
|
|
// withdrawal_credentials=deposit.data.withdrawal_credentials,
|
|
// activation_eligibility_epoch=FAR_FUTURE_EPOCH,
|
|
// activation_epoch=FAR_FUTURE_EPOCH,
|
|
// exit_epoch=FAR_FUTURE_EPOCH,
|
|
// withdrawable_epoch=FAR_FUTURE_EPOCH,
|
|
// effective_balance=min(amount - amount % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE)
|
|
// ))
|
|
// state.balances.append(amount)
|
|
// else:
|
|
// # Increase balance by deposit amount
|
|
// index = validator_pubkeys.index(pubkey)
|
|
// increase_balance(state, index, amount)
|
|
func ProcessDeposit(
|
|
beaconState *pb.BeaconState,
|
|
deposit *pb.Deposit,
|
|
valIndexMap map[[32]byte]int,
|
|
verifySignatures bool,
|
|
verifyTree bool,
|
|
) (*pb.BeaconState, error) {
|
|
if err := verifyDeposit(beaconState, deposit, verifyTree); err != nil {
|
|
return nil, fmt.Errorf("could not verify deposit from #%x: %v", bytesutil.Trunc(deposit.Data.Pubkey), err)
|
|
}
|
|
beaconState.Eth1DepositIndex++
|
|
pubKey := deposit.Data.Pubkey
|
|
amount := deposit.Data.Amount
|
|
index, ok := valIndexMap[bytesutil.ToBytes32(pubKey)]
|
|
if !ok {
|
|
if verifySignatures {
|
|
pub, err := bls.PublicKeyFromBytes(pubKey)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
domain := helpers.Domain(beaconState, helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainDeposit)
|
|
sig, err := bls.SignatureFromBytes(deposit.Data.Signature)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not convert bytes to signature: %v", err)
|
|
}
|
|
root, err := ssz.SigningRoot(deposit.Data)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not determine signing root for deposit data: %v", err)
|
|
}
|
|
if !sig.Verify(root[:], pub, domain) {
|
|
return nil, fmt.Errorf("deposit signature did not verify")
|
|
}
|
|
}
|
|
effectiveBalance := amount - (amount % params.BeaconConfig().EffectiveBalanceIncrement)
|
|
if params.BeaconConfig().MaxEffectiveBalance < effectiveBalance {
|
|
effectiveBalance = params.BeaconConfig().MaxEffectiveBalance
|
|
}
|
|
beaconState.Validators = append(beaconState.Validators, &pb.Validator{
|
|
Pubkey: pubKey,
|
|
WithdrawalCredentials: deposit.Data.WithdrawalCredentials,
|
|
ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
ActivationEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
EffectiveBalance: effectiveBalance,
|
|
})
|
|
beaconState.Balances = append(beaconState.Balances, amount)
|
|
} else {
|
|
beaconState = helpers.IncreaseBalance(beaconState, uint64(index), amount)
|
|
}
|
|
|
|
return beaconState, nil
|
|
}
|
|
|
|
func verifyDeposit(beaconState *pb.BeaconState, deposit *pb.Deposit, verifyTree bool) error {
|
|
if verifyTree {
|
|
// Verify Merkle proof of deposit and deposit trie root.
|
|
receiptRoot := beaconState.Eth1Data.DepositRoot
|
|
leaf, err := hashutil.DepositHash(deposit.Data)
|
|
if err != nil {
|
|
return fmt.Errorf("could not tree hash deposit data: %v", err)
|
|
}
|
|
if ok := trieutil.VerifyMerkleProof(
|
|
receiptRoot,
|
|
leaf[:],
|
|
int(beaconState.Eth1DepositIndex),
|
|
deposit.Proof,
|
|
); !ok {
|
|
return fmt.Errorf(
|
|
"deposit merkle branch of deposit root did not verify for root: %#x",
|
|
receiptRoot,
|
|
)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// ProcessVoluntaryExits is one of the operations performed
|
|
// on each processed beacon block to determine which validators
|
|
// should exit the state's validator registry.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_voluntary_exit(state: BeaconState, exit: VoluntaryExit) -> None:
|
|
// """
|
|
// Process ``VoluntaryExit`` operation.
|
|
// """
|
|
// validator = state.validator_registry[exit.validator_index]
|
|
// # Verify the validator is active
|
|
// assert is_active_validator(validator, get_current_epoch(state))
|
|
// # Verify the validator has not yet exited
|
|
// assert validator.exit_epoch == FAR_FUTURE_EPOCH
|
|
// # Exits must specify an epoch when they become valid; they are not valid before then
|
|
// assert get_current_epoch(state) >= exit.epoch
|
|
// # Verify the validator has been active long enough
|
|
// assert get_current_epoch(state) >= validator.activation_epoch + PERSISTENT_COMMITTEE_PERIOD
|
|
// # Verify signature
|
|
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, exit.epoch)
|
|
// assert bls_verify(validator.pubkey, signing_root(exit), exit.signature, domain)
|
|
// # Initiate exit
|
|
// initiate_validator_exit(state, exit.validator_index)
|
|
func ProcessVoluntaryExits(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
var err error
|
|
exits := body.VoluntaryExits
|
|
|
|
for idx, exit := range exits {
|
|
if err := verifyExit(beaconState, exit, verifySignatures); err != nil {
|
|
return nil, fmt.Errorf("could not verify exit #%d: %v", idx, err)
|
|
}
|
|
beaconState, err = v.InitiateValidatorExit(beaconState, exit.ValidatorIndex)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
func verifyExit(beaconState *pb.BeaconState, exit *pb.VoluntaryExit, verifySignatures bool) error {
|
|
if int(exit.ValidatorIndex) >= len(beaconState.Validators) {
|
|
return fmt.Errorf("validator index out of bound %d > %d", exit.ValidatorIndex, len(beaconState.Validators))
|
|
}
|
|
|
|
validator := beaconState.Validators[exit.ValidatorIndex]
|
|
currentEpoch := helpers.CurrentEpoch(beaconState)
|
|
// Verify the validator is active.
|
|
if !helpers.IsActiveValidator(validator, currentEpoch) {
|
|
return errors.New("non-active validator cannot exit")
|
|
}
|
|
// Verify the validator has not yet exited.
|
|
if validator.ExitEpoch != params.BeaconConfig().FarFutureEpoch {
|
|
return fmt.Errorf("validator has already exited at epoch: %v", validator.ExitEpoch)
|
|
}
|
|
// Exits must specify an epoch when they become valid; they are not valid before then.
|
|
if currentEpoch < exit.Epoch {
|
|
return fmt.Errorf("expected current epoch >= exit epoch, received %d < %d", currentEpoch, exit.Epoch)
|
|
}
|
|
// Verify the validator has been active long enough.
|
|
if currentEpoch < validator.ActivationEpoch+params.BeaconConfig().PersistentCommitteePeriod {
|
|
return fmt.Errorf(
|
|
"validator has not been active long enough to exit, wanted epoch %d >= %d",
|
|
currentEpoch,
|
|
validator.ActivationEpoch+params.BeaconConfig().PersistentCommitteePeriod,
|
|
)
|
|
}
|
|
if verifySignatures {
|
|
pub, err := bls.PublicKeyFromBytes(validator.Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
domain := helpers.Domain(beaconState, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit)
|
|
sig, err := bls.SignatureFromBytes(exit.Signature)
|
|
if err != nil {
|
|
return fmt.Errorf("could not convert bytes to signature: %v", err)
|
|
}
|
|
root, err := ssz.SigningRoot(exit)
|
|
if err != nil {
|
|
return fmt.Errorf("could not sign root for header: %v", err)
|
|
}
|
|
if !sig.Verify(root[:], pub, domain) {
|
|
return fmt.Errorf("voluntary exit signature did not verify")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ProcessTransfers is one of the operations performed
|
|
// on each processed beacon block to determine transfers between beacon chain balances.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_transfer(state: BeaconState, transfer: Transfer) -> None:
|
|
// """
|
|
// Process ``Transfer`` operation.
|
|
// """
|
|
// # Verify the balance the covers amount and fee (with overflow protection)
|
|
// assert state.balances[transfer.sender] >= max(transfer.amount + transfer.fee, transfer.amount, transfer.fee)
|
|
// # A transfer is valid in only one slot
|
|
// assert state.slot == transfer.slot
|
|
// # Sender must satisfy at least one of the following conditions in the parenthesis:
|
|
// assert (
|
|
// # * Has not been activated
|
|
// state.validator_registry[transfer.sender].activation_eligibility_epoch == FAR_FUTURE_EPOCH or
|
|
// # * Is withdrawable
|
|
// get_current_epoch(state) >= state.validator_registry[transfer.sender].withdrawable_epoch or
|
|
// # * Balance after transfer is more than the effective balance threshold
|
|
// transfer.amount + transfer.fee + MAX_EFFECTIVE_BALANCE <= state.balances[transfer.sender]
|
|
// )
|
|
// # Verify that the pubkey is valid
|
|
// assert (
|
|
// state.validator_registry[transfer.sender].withdrawal_credentials ==
|
|
// int_to_bytes(BLS_WITHDRAWAL_PREFIX, length=1) + hash(transfer.pubkey)[1:]
|
|
// )
|
|
// # Verify that the signature is valid
|
|
// assert bls_verify(transfer.pubkey, signing_root(transfer), transfer.signature, get_domain(state, DOMAIN_TRANSFER))
|
|
// # Process the transfer
|
|
// decrease_balance(state, transfer.sender, transfer.amount + transfer.fee)
|
|
// increase_balance(state, transfer.recipient, transfer.amount)
|
|
// increase_balance(state, get_beacon_proposer_index(state), transfer.fee)
|
|
// # Verify balances are not dust
|
|
// assert not (0 < state.balances[transfer.sender] < MIN_DEPOSIT_AMOUNT)
|
|
// assert not (0 < state.balances[transfer.recipient] < MIN_DEPOSIT_AMOUNT)
|
|
func ProcessTransfers(
|
|
beaconState *pb.BeaconState,
|
|
body *pb.BeaconBlockBody,
|
|
verifySignatures bool,
|
|
) (*pb.BeaconState, error) {
|
|
transfers := body.Transfers
|
|
|
|
for idx, transfer := range transfers {
|
|
if err := verifyTransfer(beaconState, transfer, verifySignatures); err != nil {
|
|
return nil, fmt.Errorf("could not verify transfer %d: %v", idx, err)
|
|
}
|
|
// Process the transfer between accounts.
|
|
beaconState = helpers.DecreaseBalance(beaconState, transfer.Sender, transfer.Amount+transfer.Fee)
|
|
beaconState = helpers.IncreaseBalance(beaconState, transfer.Recipient, transfer.Amount)
|
|
proposerIndex, err := helpers.BeaconProposerIndex(beaconState)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("could not determine beacon proposer index: %v", err)
|
|
}
|
|
beaconState = helpers.IncreaseBalance(beaconState, proposerIndex, transfer.Fee)
|
|
|
|
// Finally, we verify balances will not go below the mininum.
|
|
if beaconState.Balances[transfer.Sender] < params.BeaconConfig().MinDepositAmount &&
|
|
0 < beaconState.Balances[transfer.Sender] {
|
|
return nil, fmt.Errorf(
|
|
"sender balance below critical level: %v",
|
|
beaconState.Balances[transfer.Sender],
|
|
)
|
|
}
|
|
if beaconState.Balances[transfer.Recipient] < params.BeaconConfig().MinDepositAmount &&
|
|
0 < beaconState.Balances[transfer.Recipient] {
|
|
return nil, fmt.Errorf(
|
|
"recipient balance below critical level: %v",
|
|
beaconState.Balances[transfer.Recipient],
|
|
)
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
func verifyTransfer(beaconState *pb.BeaconState, transfer *pb.Transfer, verifySignatures bool) error {
|
|
if transfer.Sender > uint64(len(beaconState.Validators)) {
|
|
return errors.New("transfer sender index out of bounds in validator registry")
|
|
}
|
|
|
|
maxVal := transfer.Fee
|
|
if transfer.Amount > maxVal {
|
|
maxVal = transfer.Amount
|
|
}
|
|
if transfer.Amount+transfer.Fee > maxVal {
|
|
maxVal = transfer.Amount + transfer.Fee
|
|
}
|
|
sender := beaconState.Validators[transfer.Sender]
|
|
senderBalance := beaconState.Balances[transfer.Sender]
|
|
// Verify the balance the covers amount and fee (with overflow protection).
|
|
if senderBalance < maxVal {
|
|
return fmt.Errorf("expected sender balance %d >= %d", senderBalance, maxVal)
|
|
}
|
|
// A transfer is valid in only one slot.
|
|
if beaconState.Slot != transfer.Slot {
|
|
return fmt.Errorf("expected beacon state slot %d == transfer slot %d", beaconState.Slot, transfer.Slot)
|
|
}
|
|
|
|
// Sender must be not yet eligible for activation, withdrawn, or transfer balance over MAX_EFFECTIVE_BALANCE.
|
|
senderNotActivationEligible := sender.ActivationEligibilityEpoch == params.BeaconConfig().FarFutureEpoch
|
|
senderNotWithdrawn := helpers.CurrentEpoch(beaconState) >= sender.WithdrawableEpoch
|
|
underMaxTransfer := transfer.Amount+transfer.Fee+params.BeaconConfig().MaxEffectiveBalance <= senderBalance
|
|
|
|
if !(senderNotActivationEligible || senderNotWithdrawn || underMaxTransfer) {
|
|
return fmt.Errorf(
|
|
"expected activation eligiblity: false or withdrawn: false or over max transfer: false, received %v %v %v",
|
|
senderNotActivationEligible,
|
|
senderNotWithdrawn,
|
|
underMaxTransfer,
|
|
)
|
|
}
|
|
// Verify that the pubkey is valid.
|
|
buf := []byte{params.BeaconConfig().BLSWithdrawalPrefixByte}
|
|
hashed := hashutil.Hash(transfer.Pubkey)
|
|
buf = append(buf, hashed[:][1:]...)
|
|
if !bytes.Equal(sender.WithdrawalCredentials, buf) {
|
|
return fmt.Errorf("invalid public key, expected %v, received %v", buf, sender.WithdrawalCredentials)
|
|
}
|
|
if verifySignatures {
|
|
pub, err := bls.PublicKeyFromBytes(transfer.Pubkey)
|
|
if err != nil {
|
|
return fmt.Errorf("could not deserialize validator public key: %v", err)
|
|
}
|
|
domain := helpers.Domain(beaconState, helpers.CurrentEpoch(beaconState), params.BeaconConfig().DomainTransfer)
|
|
sig, err := bls.SignatureFromBytes(transfer.Signature)
|
|
if err != nil {
|
|
return fmt.Errorf("could not convert bytes to signature: %v", err)
|
|
}
|
|
root, err := ssz.SigningRoot(transfer)
|
|
if err != nil {
|
|
return fmt.Errorf("could not sign root for header: %v", err)
|
|
}
|
|
if !sig.Verify(root[:], pub, domain) {
|
|
return fmt.Errorf("transfer signature did not verify")
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// ClearEth1DataVoteCache clears the eth1 data vote count cache.
|
|
func ClearEth1DataVoteCache() {
|
|
eth1DataCache = cache.NewEth1DataVoteCache()
|
|
}
|