mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 21:08:10 -05:00
* Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * add in new patch and workspace * update cloners * Handle rewards overflow (#5122) * Refactoring of initial sync (#5096) * implements blocks queue * refactors updateCounter method * fixes deadlock on stop w/o start * refactors updateSchedulerState * more tests on schduler * parseFetchResponse tests * wraps up tests for blocks queue * eod commit * fixes data race in round robin * revamps fetcher * fixes race conditions + livelocks + deadlocks * less verbose output * fixes data race, by isolating critical sections * minor refactoring: resolves blocking calls * implements init-sync queue * udpate fetch/send buffers in blocks fetcher * blockState enum-like type alias * refactors common code into releaseTicket() * better gc * linter * minor fix to round robin * moves original round robin into its own package * adds enableInitSyncQueue flag * fixes issue with init-sync service selection * Update beacon-chain/sync/initial-sync/round_robin.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * initsyncv1 -> initsyncold * adds span Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> * Handle rewards overflow * Revert "Refactoring of initial sync (#5096)" This reverts commit3ec2a0f9e0. Co-authored-by: Victor Farazdagi <simple.square@gmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * updated block operations * updated validator client * Merge refs/heads/master into v0.10.1 * updated block operations test * skip benchmark test * updated transition test * updated db kv tests * updated ops tests * updated ops tests * updated slashing tests * updated rpc tests * updated state utils * updated test utils and miscs * Temp skips minimal spec tests * Fixed proposer slashing test * Gaz * Skip 2 more minimal tests * Skip 2 more minimal tests * Update readme * gaz * Conflict * Fix import and not use * Update workspace for new spec test * Fix workspace * Merge refs/heads/master into v0.10.1 * Update workspace with new ethapi commit * Unblock a few tests * Merge refs/heads/master into v0.10.1 * fixed block op test * gaz * Merge refs/heads/master into v0.10.1 * Skip gen state test (test setup issue * Updated hysteresis config * Updated epoch processing for new hyteresis * Updated tests * regen proto beacon * update state util for state root * update state types * update getter and setters * update compute domain and get domain and tests * update validators * Add forkdata proto * Updated compute domain api, moved it to helper pkg * Merge refs/heads/master into v0.10.1 * Fixed all core tests * Fixed all the sync tests * Fixed all the rpc tests * Merge refs/heads/master into v0.10.1 * Merge refs/heads/master into v0.10.1 * Fixed conflict * Fixed conflict * Conflict fix * visibility * Fixed validator tests * Fixing test util * Fixed rest of non spec tests * Fixed a bug proposer index wasn't included * gaz * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Updated eth1 data voting period to epoch based * Fixed failed tests * fix bug * fix error * Fixed more misc tests * Add new SignedAggregateAndProof to pass spec test * Update minimalConfig.PersistentCommitteePeriod * allow to rebuild trie * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Skip e2e tests * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Align aggregator action with v0.11 (#5146) * Remove Head Root from Beacon Block by Range Request (#5165) * make proto changes * remove head root * Merge branch 'master' of https://github.com/prysmaticlabs/geth-sharding into v0.11 * add back herumi's library * Update ethapi in workspace, started fixing test. Hand off to Nishant * fix build * All tests passing * Align finalized slot check with v0.11 (#5166) * Merge branch 'master' into v0.11 * Add DoS resistance for v0.11 (#5158) * Add Fork Digest Helper (#5173) * Extend DoS prevention to rest of operation objects (#5174) * Update mapping * Add caches * Update seen block in validation pipeline * Update seen att in validation pipeline * Update seen att in validation pipeline * Fixed rest of tests * Gazelle * Better writes * Lint * Preston's feedback * Switched to LRU cache and fixed tests * Gazelle * Fix test * Update proposer slashing * Update proposer slashing * Fixed a block test * Update exit * Update atteser slashing * Raul's feedback Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Add remote keymanager (#5133) * Add remote keymanager * Add generic signRoot() helper * Add tests for remote keymanager * NewRemote -> NewRemoteWallet * signRoot -> signOject, to increase reuse * Fix end-to-end compile error Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> * Add Snappy Framing to the Encoder (#5172) * change to framing * more fixes * fix everything * add stricter limits * preston feedback Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: rauljordan <raul@prysmaticlabs.com> * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Move Subnet Functionality to its Own File (#5179) * move subnets to their own file * fix build fail * build * Update beacon-chain/p2p/discovery_test.go Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Sync with master * Verify proposer signature in sync (#5206) * Fix Signed Attestation In Sync (#5207) * Add Eth2 Fork ENR Functionality (#5181) * add fork entry enr * add in fork * add the required fork entry to node * add and retrieve fork entry * await state initialized * utilize new structure * more progress, utilizing a config map instead * send the genesis validators root via the event feed * struct method for discovery * fix broken builds * fixed up more tsts using state feed initializer * fix up most tests * only one more failing test * almost done with tests * p2p tests all pass * config fix * fix blockchain test * gaz * add in todo * lint * add compare func * ensure fork ENR versions match between peers * add in test for discovery * test name * tests complete * tests done * done * comments * fix all flakes * addressed comments * build using ssz gen * marshal record * use custom ssz * deduplicate import * fix build * add enr proto * p2p tests done Co-authored-by: nisdas <nishdas93@gmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Verify aggregator signature in sync (#5208) * Add Fork Digest For Gossip Topics (#5191) * update for the day * fix remaining failing test * fix one more test * change message * Apply suggestions from code review Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * terence's review * implement fork digest' * align digest to interface' * passed all tests * spawn in goroutine Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * Fix Incorrect Attester Slashing Method (#5229) * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Remove keystore keymanager from validator (#5236) * Remove keystore keymanager from validator * Update dependency * Update validator/flags/flags.go * Update validator/flags/flags.go Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com> * fix broadcaster * update metrics with fork digest for p2p (#5251) * update metrics with fork digest for p2p * update p2p metrics * update metrics using att values * wrapped up * fix bug Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Fix incorrect domain type comments (#5250) * Fix incorrect domain type comments * resolve conflicts * fix broken broadcast test * fix tests * include protocol suffix * fix confs * lint * fix test * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Merge branch 'master' of github.com:prysmaticlabs/prysm into v0.11 * resolve broken slasher test' * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Merge branch 'master' into v0.11 * fix config override * Remove deprecated parameters (#5249) * Avoid div by zero in extreme balance case (#5273) * Return effective balance increment instead of 1 * Update to new spec tests v0.11.1 * Revert "Regen historical states for `new-state-mgmt` compatibility (#5261)" This reverts commitdf9a534826. Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Revert "Remove deprecated parameters (#5249)" (#5276) This reverts commit7d17c9ac34. * Verify block proposer index before gossip (#5274) * Update pipeline * Update tests Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Add in Proposer Index to Custom HTR (#5269) * fix test * Update beacon-chain/state/stateutil/blocks_test.go Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Resolve Flakey P2P Tests (#5285) * double time for flakey test * fix test flakeyness in p2p: * flakey * time tolerance * greater tolerance * Merge branch 'master' into v0.11 * release resources correctly (#5287) * Merge refs/heads/master into v0.11 * Enable NOISE Handshake by Default v0.11 (#5272) * noise handshakes by default * fix build * noisy noise everywhere * deprecated noisy noise flag with more noise * add secio as fallback Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: nisdas <nishdas93@gmail.com> * Merge refs/heads/master into v0.11 * new ports * fix broken build * Make `new-state-mgmt` canonical (#5289) * Invert the flags * Update checking messages * Fixed all db tests * Fixed rest of the block chain tests * Fix chain race tests * Fixed rpc tests * Disable soudns better... * Merge branch 'v0.11' into invert-new-state-mgmt * Merge refs/heads/v0.11 into invert-new-state-mgmt * Fix export * Merge branch 'invert-new-state-mgmt' of github.com:prysmaticlabs/prysm into invert-new-state-mgmt * Fix conflict tests * Gazelle * Merge refs/heads/v0.11 into invert-new-state-mgmt * Merge refs/heads/v0.11 into invert-new-state-mgmt * Merge branch 'master' into v0.11 * resolve flakeyness * Merge refs/heads/master into v0.11 * Merge refs/heads/master into v0.11 * Detect Proposer Slashing Implementation (#5139) * detect blocks * detect blocks * use stub * use stub * use stub * todo * fix test * add tests and utils * fix imports * fix imports * fix comment * todo * proposerIndex * fix broken test * formatting and simplified if * Update slasher/detection/service.go * Update slasher/detection/testing/utils.go Co-Authored-By: terence tsao <terence@prysmaticlabs.com> * fixed up final comments * better naming * Update slasher/detection/service.go * Update slasher/detection/service.go * Update slasher/detection/service.go Co-Authored-By: Ivan Martinez <ivanthegreatdev@gmail.com> * no more named args Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com> * Merge branch 'master' of https://github.com/prysmaticlabs/geth-sharding into v0.11 * Add Metadata And Ping RPC methods (#5271) * add new proto files * add flag and helper * add initializer * imports * add ping method * add receive/send ping request * add ping test * refactor rpc methods and add ping test * finish adding all tests * fix up tests * Apply suggestions from code review * lint * imports * lint * Update beacon-chain/p2p/service.go * Update shared/cmd/flags.go Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> * Merge branch 'master' of https://github.com/prysmaticlabs/geth-sharding into v0.11 * Updates for remote keymanager (#5260) * Merge branch 'spec-v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Merge remote-tracking branch 'origin' into v0.11 * Update to slash by slot instead of epoch (#5297) * change to slash by slot instead of epoch * gaz * fix test * fix test * fix infinite loop on error parse * Sync with master * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Update proposer protection to v0.11 (#5292) * Complete most of changes * Fix other tests * Test progress * Tests * Finish tests * update pbs * Fix mocked tests * Gazelle * pt 2 * Fix * Fixes * Fix tests wit hwrong copying * Merge refs/heads/master into v0.11 * Merge refs/heads/master into v0.11 * Implement `SubscribeCommitteeSubnet` method (#5299) * Add client implementation * Update workspace * Update server * Update service * Gaz * Mocks * Fixed validator tests * Add round tirp tests * Fixed subnet test * Comment * Update committee cache * Comment * Update RPC * Fixed test * Nishant's comment * Gaz * Refresh ENR is for epoch * Needs to be append * Merge refs/heads/master into v0.11 * resolve confs * Validator subscribe subnet to next epoch (#5312) * Alert to subscribe to next epoch * Fixed tests * Comments * Fixed tests * Update validator/client/validator.go Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Revert "Revert "Remove deprecated parameters (#5249)" (#5276)" (#5277) This reverts commit47e5a2cf96. * Aggregate on demand for v0.11 (#5302) * Add client implementation * Update workspace * Update server * Update service * Gaz * Mocks * Fixed validator tests * Add round tirp tests * Fixed subnet test * Wait 1/3 on validator side * Lint * Comment * Update committee cache * Comment * Update RPC * Fixed test * Nishant's comment * Gaz * Refresh ENR is for epoch * Needs to be append * Fixed duplication * Tests * Skip e2e * Update beacon-chain/rpc/validator/aggregator.go Co-Authored-By: shayzluf <thezluf@gmail.com> * Apply suggestions from code review Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: shayzluf <thezluf@gmail.com> Co-authored-by: Raul Jordan <raul@prysmaticlabs.com> * Refactor Dynamic Subscriptions (#5318) * clean up * comment * metrics * fix Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Merge refs/heads/master into v0.11 * Fix listindexed attestations and detect historic attestations (#5321) * fix list indexed attestations * fix tests * goimports * names * Add check for slot == 0 (#5322) * Change attester protection to return default if DB is empty (#5323) * Change how default values are set * Remove unused imports * Remove wasteful db call * Fix db tests * Fix db test * Merge refs/heads/master into v0.11 * fix it (#5326) * V0.11 run time fixes to use interop config (#5324) * Started testing * Bunch of fixes * use-interop * Sync with v0.11 * Conflict * Uncomment wait for activation * Move pending block queue from subscriber to validator pipeline * Merge branch 'v0.11' into use-interop-config * passing tests * Merge refs/heads/v0.11 into use-interop-config * Merge refs/heads/v0.11 into use-interop-config * Merge refs/heads/master into v0.11 * Merge refs/heads/master into v0.11 * Merge refs/heads/master into v0.11 * Nil Checks in Process Attestation v0.11 (#5331) * Started testing * Bunch of fixes * use-interop * Sync with v0.11 * Uncomment wait for activation * Move pending block queue from subscriber to validator pipeline * passing tests * nil checks to prevent panics * lint Co-authored-by: terence tsao <terence@prysmaticlabs.com> * Validator batch subscribe subnets (#5332) * Update both beacon node and validator * Comments * Tests * Lint Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Validator smarter subscribe (#5334) * Fix incorrect proposer index calculation (#5336) * Use correct parent state * Fixed test Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * enhance error * enhance error * Update P2P Service to Handle Local Metadata (#5319) * add metadata to ENR * add new methods * glue everything * fix all tests and refs * add tests * add more tests * Apply suggestions from code review * fix method * raul's review * gaz * fix test setup * fix all tests * better naming * fix broken test * validate nil Co-authored-by: rauljordan <raul@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Revert "Revert "Revert "Remove deprecated parameters (#5249)" (#5276)" (#5277)" (#5343) This reverts commite5aef1686e. * Wait for Genesis Event to Start P2P (#5303) * use event feed for state initialized events * add in handler for tests * wait till genesis for p2p * Apply suggestions from code review Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Merge refs/heads/master into v0.11 * Avoid duplicated aggregation request (#5346) * Avoid duplicated aggregation request * Test and lock * Gaz * Fix Validate For Metadata (#5348) * return true * shay's review Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Multiple Proposer Slots Allowed Per Epoch for Validators (#5344) * allow multiple proposer slots * multi propose * proposer indices to slots map * remove deprecated comm assign * Apply suggestions from code review * resolve broken tests, add logic in validator client * fix val tests Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Networking Fixes (#5349) * close stream later * add ping method * add method * lint * More efficient aggregation on demand (#5354) * Return Nil Error if Pre-Genesis in P2P Service Healthz Check (#5355) * pregenesis healthz check: * optimal * right order * Update beacon-chain/p2p/service.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update beacon-chain/p2p/service.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * no comment Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> * Release DiscoveryV5 for Testnet Restart (#5357) * release discv5 * fix build * Fix Overflow in Status Check (#5361) * fix overflow * Apply suggestions from code review * Merge branch 'master' of github.com:prysmaticlabs/prysm into v0.11 * fix after merge * Merge refs/heads/master into v0.11 * Make Mainnet Config Default, No More Demo Config (#5367) * bye bye demo config * gaz * fix usage * fix dep * gaz * Update default balance for sendDeposits Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> * Use FastSSZ Marshal/Unmarshal for DB Encodings in v0.11.1 (#5351) * try * use marshaler structure for db instead of proto * white list types * attempt * revert * testutil.NewBeaconState() * Fully populate fields for round trip ssz marshal * fix //beacon-chain/db/kv:go_default_test * more passing tests * another test target passed * fixed stategen * blockchain tests green * passing sync * more targets fixed * more test fixes in rpc/validator * most rpc val * validators test fixes * skip round robin old * aggregate test * whitelist done * Update beacon-chain/rpc/validator/attester_test.go * edit baz * Fixed tests * Fixed getblock test * Add back init * reduce test size * fix broken build * tests pass Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> Co-authored-by: terence tsao <terence@prysmaticlabs.com> * Reconnect slasher streams on beacon node shutdown (#5376) * restart streams on beacon node shutdown * fix comment * remove export * ivan feedback * ivan feedback * case insensitive * Update slasher/beaconclient/receivers.go * raul feedback Co-authored-by: Ivan Martinez <ivanthegreatdev@gmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Merge branch 'master' into v0.11 * Merge refs/heads/master into v0.11 * Amend Faucet to Offer 32.5 ETH for v0.11 (#5378) * deposit amount in faucet * fix eth amount * gas cost * unskip exec transition test * Revert "Enable NOISE Handshake by Default v0.11 (#5272)" (#5381) This reverts commita8d32d504a. * Merge refs/heads/master into v0.11 * use string for deposit flag * Update Bootnode to v0.11 (#5387) * fix bootnode * add changes * gaz * fix docker * Merge branch 'master' of github.com:prysmaticlabs/prysm into v0.11 * build fix * fix flaky test * Merge refs/heads/master into v0.11 * Unskip E2E for V0.11 (#5386) * Begin work on fixing e2e for v0.11 * Start bootnode work * Begin implementing bootnode into e2e * Fix E2E for v0.11 * Remove extra * gaz * Remove unused key gen code * Remove trailing multiaddr code * add skip for slashing * Fix slashing e2e * Fix docker image build * Merge branch 'master' of https://github.com/prysmaticlabs/prysm into v0.11 * Merge refs/heads/master into v0.11 * Merge branch 'master' of github.com:prysmaticlabs/prysm into v0.11 * Update beacon-chain/p2p/broadcaster_test.go * Merge refs/heads/master into v0.11 * Pass E2E Tests for v0.11 and Enable Attestation Subnets By Default (#5407) * Update README.md Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Apply suggestions from code review Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update beacon-chain/p2p/config.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update shared/keystore/deposit_input.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update tools/faucet/server.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update beacon-chain/p2p/service.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update shared/benchutil/pregen_test.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update shared/benchutil/pregen_test.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update proto/beacon/p2p/v1/BUILD.bazel Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update shared/benchutil/pregen_test.go Co-Authored-By: Preston Van Loon <preston@prysmaticlabs.com> * Update shared/bls/spectest/aggregate_verify_test.go * Addressed feedback. All test passing * Merge branch 'v0.11' of github.com:prysmaticlabs/prysm into v0.11 * Update beacon-chain/core/blocks/block_operations_fuzz_test.go Co-Authored-By: Ivan Martinez <ivanthegreatdev@gmail.com> * Update beacon-chain/core/blocks/block_operations_test.go Co-Authored-By: Ivan Martinez <ivanthegreatdev@gmail.com> * Update shared/testutil/helpers.go Co-Authored-By: Ivan Martinez <ivanthegreatdev@gmail.com> * Update beacon-chain/core/helpers/signing_root.go Co-Authored-By: Ivan Martinez <ivanthegreatdev@gmail.com> * Resolve Misc v0.11 Items (Raul) (#5414) * address all comments * set faucet * nishant feedback * Update beacon-chain/p2p/service.go Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Revert keymanager changes (#5416) * Revert "Updates for remote keymanager (#5260)" This reverts commitbbcd895db5. * Revert "Remove keystore keymanager from validator (#5236)" This reverts commit46008770c1. * Revert "Update eth2 wallet keymanager (#4984)" This reverts commit7f7ef43f21. Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * Update BLS and limit visibility (#5415) * remove duplicated BLS, add golang.org/x/mod * Update BLS and restrict visibility * fix build * Fix eth1data test and fix order of ops (#5413) * use multiaddr builder (#5419) * Unskip benchutil and minor v0.11 fixes (#5417) * Unskip benchutil tests * Remove protos and gaz * Fixes * Networking Fixes (#5421) * check * fix test * fix size * fix test * more fixes * fix test again * Update ethereum APIs with latest master * Error handling for v0.11 tests (#5428) * Proper err handling for tests * Lint * Fixed rest of the tests * Gaz * Fixed old master tests * Sync with master * Rm old aggregate_test.go
1973 lines
56 KiB
Go
1973 lines
56 KiB
Go
package blocks_test
|
|
|
|
import (
|
|
"bytes"
|
|
"context"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"reflect"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/gogo/protobuf/proto"
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/go-bitfield"
|
|
"github.com/prysmaticlabs/go-ssz"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/blocks"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/state/stateutil"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/attestationutil"
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"github.com/prysmaticlabs/prysm/shared/testutil"
|
|
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
|
"github.com/sirupsen/logrus"
|
|
"gopkg.in/d4l3k/messagediff.v1"
|
|
)
|
|
|
|
func init() {
|
|
logrus.SetOutput(ioutil.Discard) // Ignore "validator activated" logs
|
|
}
|
|
|
|
func TestProcessBlockHeader_WrongProposerSig(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
if err := beaconState.SetLatestBlockHeader(ðpb.BeaconBlockHeader{Slot: 9}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
lbhdr, err := stateutil.BlockHeaderRoot(beaconState.LatestBlockHeader())
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
block := ðpb.SignedBeaconBlock{
|
|
Block: ðpb.BeaconBlock{
|
|
ProposerIndex: proposerIdx,
|
|
Slot: 0,
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: []byte{'A', 'B', 'C'},
|
|
},
|
|
ParentRoot: lbhdr[:],
|
|
},
|
|
}
|
|
dt, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatalf("Failed to get domain form state: %v", err)
|
|
}
|
|
signingRoot, err := helpers.ComputeSigningRoot(block.Block, dt)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get signing root of block: %v", err)
|
|
}
|
|
blockSig := privKeys[proposerIdx+1].Sign(signingRoot[:])
|
|
block.Signature = blockSig.Marshal()[:]
|
|
|
|
_, err = blocks.ProcessBlockHeader(beaconState, block)
|
|
want := "signature did not verify"
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %v, received %v", want, err)
|
|
}
|
|
|
|
}
|
|
|
|
func TestProcessBlockHeader_DifferentSlots(t *testing.T) {
|
|
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
|
|
for i := 0; i < len(validators); i++ {
|
|
validators[i] = ðpb.Validator{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
Slashed: true,
|
|
}
|
|
}
|
|
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: validators,
|
|
Slot: 0,
|
|
LatestBlockHeader: ðpb.BeaconBlockHeader{Slot: 9},
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: []byte{0, 0, 0, 0},
|
|
CurrentVersion: []byte{0, 0, 0, 0},
|
|
},
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
lbhsr, err := ssz.HashTreeRoot(state.LatestBlockHeader())
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
currentEpoch := helpers.CurrentEpoch(state)
|
|
dt, err := helpers.Domain(state.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, state.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatalf("Failed to get domain form state: %v", err)
|
|
}
|
|
priv := bls.RandKey()
|
|
root, err := helpers.ComputeSigningRoot([]byte("hello"), dt)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
blockSig := priv.Sign(root[:])
|
|
validators[5896].PublicKey = priv.PublicKey().Marshal()
|
|
block := ðpb.SignedBeaconBlock{
|
|
Block: ðpb.BeaconBlock{
|
|
Slot: 1,
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: []byte{'A', 'B', 'C'},
|
|
},
|
|
ParentRoot: lbhsr[:],
|
|
},
|
|
Signature: blockSig.Marshal(),
|
|
}
|
|
|
|
_, err = blocks.ProcessBlockHeader(state, block)
|
|
want := "is different than block slot"
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %v, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessBlockHeader_PreviousBlockRootNotSignedRoot(t *testing.T) {
|
|
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
|
|
for i := 0; i < len(validators); i++ {
|
|
validators[i] = ðpb.Validator{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
Slashed: true,
|
|
}
|
|
}
|
|
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: validators,
|
|
Slot: 0,
|
|
LatestBlockHeader: ðpb.BeaconBlockHeader{Slot: 9},
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: []byte{0, 0, 0, 0},
|
|
CurrentVersion: []byte{0, 0, 0, 0},
|
|
},
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
currentEpoch := helpers.CurrentEpoch(state)
|
|
dt, err := helpers.Domain(state.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, state.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatalf("Failed to get domain form state: %v", err)
|
|
}
|
|
priv := bls.RandKey()
|
|
root, err := helpers.ComputeSigningRoot([]byte("hello"), dt)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
blockSig := priv.Sign(root[:])
|
|
validators[5896].PublicKey = priv.PublicKey().Marshal()
|
|
block := ðpb.SignedBeaconBlock{
|
|
Block: ðpb.BeaconBlock{
|
|
ProposerIndex: 5669,
|
|
Slot: 0,
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: []byte{'A', 'B', 'C'},
|
|
},
|
|
ParentRoot: []byte{'A'},
|
|
},
|
|
Signature: blockSig.Marshal(),
|
|
}
|
|
|
|
_, err = blocks.ProcessBlockHeader(state, block)
|
|
want := "does not match"
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %v, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessBlockHeader_SlashedProposer(t *testing.T) {
|
|
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
|
|
for i := 0; i < len(validators); i++ {
|
|
validators[i] = ðpb.Validator{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
Slashed: true,
|
|
}
|
|
}
|
|
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: validators,
|
|
Slot: 0,
|
|
LatestBlockHeader: ðpb.BeaconBlockHeader{Slot: 9},
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: []byte{0, 0, 0, 0},
|
|
CurrentVersion: []byte{0, 0, 0, 0},
|
|
},
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
parentRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader())
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
currentEpoch := helpers.CurrentEpoch(state)
|
|
dt, err := helpers.Domain(state.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, state.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatalf("Failed to get domain form state: %v", err)
|
|
}
|
|
priv := bls.RandKey()
|
|
root, err := helpers.ComputeSigningRoot([]byte("hello"), dt)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
blockSig := priv.Sign(root[:])
|
|
validators[12683].PublicKey = priv.PublicKey().Marshal()
|
|
block := ðpb.SignedBeaconBlock{
|
|
Block: ðpb.BeaconBlock{
|
|
ProposerIndex: 5669,
|
|
Slot: 0,
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: []byte{'A', 'B', 'C'},
|
|
},
|
|
ParentRoot: parentRoot[:],
|
|
},
|
|
Signature: blockSig.Marshal(),
|
|
}
|
|
|
|
_, err = blocks.ProcessBlockHeader(state, block)
|
|
want := "was previously slashed"
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %v, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessBlockHeader_OK(t *testing.T) {
|
|
validators := make([]*ethpb.Validator, params.BeaconConfig().MinGenesisActiveValidatorCount)
|
|
for i := 0; i < len(validators); i++ {
|
|
validators[i] = ðpb.Validator{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
Slashed: true,
|
|
}
|
|
}
|
|
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: validators,
|
|
Slot: 0,
|
|
LatestBlockHeader: ðpb.BeaconBlockHeader{Slot: 9},
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: []byte{0, 0, 0, 0},
|
|
CurrentVersion: []byte{0, 0, 0, 0},
|
|
},
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
latestBlockSignedRoot, err := stateutil.BlockHeaderRoot(state.LatestBlockHeader())
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
|
|
currentEpoch := helpers.CurrentEpoch(state)
|
|
dt, err := helpers.Domain(state.Fork(), currentEpoch, params.BeaconConfig().DomainBeaconProposer, state.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatalf("Failed to get domain form state: %v", err)
|
|
}
|
|
priv := bls.RandKey()
|
|
block := ðpb.SignedBeaconBlock{
|
|
Block: ðpb.BeaconBlock{
|
|
ProposerIndex: 5669,
|
|
Slot: 0,
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: []byte{'A', 'B', 'C'},
|
|
},
|
|
ParentRoot: latestBlockSignedRoot[:],
|
|
},
|
|
}
|
|
signingRoot, err := helpers.ComputeSigningRoot(block.Block, dt)
|
|
if err != nil {
|
|
t.Fatalf("Failed to get signing root of block: %v", err)
|
|
}
|
|
blockSig := priv.Sign(signingRoot[:])
|
|
block.Signature = blockSig.Marshal()[:]
|
|
bodyRoot, err := ssz.HashTreeRoot(block.Block.Body)
|
|
if err != nil {
|
|
t.Fatalf("Failed to hash block bytes got: %v", err)
|
|
}
|
|
|
|
proposerIdx, err := helpers.BeaconProposerIndex(state)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
validators[proposerIdx].Slashed = false
|
|
validators[proposerIdx].PublicKey = priv.PublicKey().Marshal()
|
|
err = state.UpdateValidatorAtIndex(proposerIdx, validators[proposerIdx])
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
newState, err := blocks.ProcessBlockHeader(state, block)
|
|
if err != nil {
|
|
t.Fatalf("Failed to process block header got: %v", err)
|
|
}
|
|
var zeroHash [32]byte
|
|
nsh := newState.LatestBlockHeader()
|
|
expected := ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 5669,
|
|
Slot: block.Block.Slot,
|
|
ParentRoot: latestBlockSignedRoot[:],
|
|
BodyRoot: bodyRoot[:],
|
|
StateRoot: zeroHash[:],
|
|
}
|
|
if !proto.Equal(nsh, expected) {
|
|
t.Errorf("Expected %v, received %v", expected, nsh)
|
|
}
|
|
}
|
|
|
|
func TestProcessRandao_IncorrectProposerFailsVerification(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
// We fetch the proposer's index as that is whom the RANDAO will be verified against.
|
|
proposerIdx, err := helpers.BeaconProposerIndex(beaconState)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
epoch := uint64(0)
|
|
buf := make([]byte, 32)
|
|
binary.LittleEndian.PutUint64(buf, epoch)
|
|
domain, err := helpers.Domain(beaconState.Fork(), epoch, params.BeaconConfig().DomainRandao, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
root, err := ssz.HashTreeRoot(&pb.SigningRoot{ObjectRoot: buf, Domain: domain})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// We make the previous validator's index sign the message instead of the proposer.
|
|
epochSignature := privKeys[proposerIdx-1].Sign(root[:])
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: epochSignature.Marshal(),
|
|
},
|
|
}
|
|
|
|
want := "block randao: signature did not verify"
|
|
if _, err := blocks.ProcessRandao(
|
|
beaconState,
|
|
block.Body,
|
|
); err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %v, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessRandao_SignatureVerifiesAndUpdatesLatestStateMixes(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
epoch := helpers.CurrentEpoch(beaconState)
|
|
epochSignature, err := testutil.RandaoReveal(beaconState, epoch, privKeys)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
RandaoReveal: epochSignature,
|
|
},
|
|
}
|
|
|
|
newState, err := blocks.ProcessRandao(
|
|
beaconState,
|
|
block.Body,
|
|
)
|
|
if err != nil {
|
|
t.Errorf("Unexpected error processing block randao: %v", err)
|
|
}
|
|
currentEpoch := helpers.CurrentEpoch(beaconState)
|
|
mix := newState.RandaoMixes()[currentEpoch%params.BeaconConfig().EpochsPerHistoricalVector]
|
|
|
|
if bytes.Equal(mix, params.BeaconConfig().ZeroHash[:]) {
|
|
t.Errorf(
|
|
"Expected empty signature to be overwritten by randao reveal, received %v",
|
|
params.BeaconConfig().EmptySignature,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestProcessEth1Data_SetsCorrectly(t *testing.T) {
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Eth1DataVotes: []*ethpb.Eth1Data{},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Eth1Data: ðpb.Eth1Data{
|
|
DepositRoot: []byte{2},
|
|
BlockHash: []byte{3},
|
|
},
|
|
},
|
|
}
|
|
|
|
period := params.BeaconConfig().EpochsPerEth1VotingPeriod * params.BeaconConfig().SlotsPerEpoch
|
|
for i := uint64(0); i < period; i++ {
|
|
beaconState, err = blocks.ProcessEth1DataInBlock(beaconState, block)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
newETH1DataVotes := beaconState.Eth1DataVotes()
|
|
if len(newETH1DataVotes) <= 1 {
|
|
t.Error("Expected new ETH1 data votes to have length > 1")
|
|
}
|
|
if !proto.Equal(beaconState.Eth1Data(), stateTrie.CopyETH1Data(block.Body.Eth1Data)) {
|
|
t.Errorf(
|
|
"Expected latest eth1 data to have been set to %v, received %v",
|
|
block.Body.Eth1Data,
|
|
beaconState.Eth1Data(),
|
|
)
|
|
}
|
|
}
|
|
func TestProcessProposerSlashings_UnmatchedHeaderSlots(t *testing.T) {
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 20)
|
|
currentSlot := uint64(0)
|
|
slashings := []*ethpb.ProposerSlashing{
|
|
{
|
|
Header_1: ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 1,
|
|
Slot: params.BeaconConfig().SlotsPerEpoch + 1,
|
|
},
|
|
},
|
|
Header_2: ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 1,
|
|
Slot: 0,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
if err := beaconState.SetSlot(currentSlot); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
ProposerSlashings: slashings,
|
|
},
|
|
}
|
|
want := "mismatched header slots"
|
|
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessProposerSlashings_SameHeaders(t *testing.T) {
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 2)
|
|
currentSlot := uint64(0)
|
|
slashings := []*ethpb.ProposerSlashing{
|
|
{
|
|
Header_1: ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 1,
|
|
Slot: 0,
|
|
},
|
|
},
|
|
Header_2: ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 1,
|
|
Slot: 0,
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
if err := beaconState.SetSlot(currentSlot); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
ProposerSlashings: slashings,
|
|
},
|
|
}
|
|
want := "expected slashing headers to differ"
|
|
_, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessProposerSlashings_ValidatorNotSlashable(t *testing.T) {
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
PublicKey: []byte("key"),
|
|
Slashed: true,
|
|
ActivationEpoch: 0,
|
|
WithdrawableEpoch: 0,
|
|
},
|
|
}
|
|
currentSlot := uint64(0)
|
|
slashings := []*ethpb.ProposerSlashing{
|
|
{
|
|
Header_1: ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 0,
|
|
Slot: 0,
|
|
},
|
|
Signature: []byte("A"),
|
|
},
|
|
Header_2: ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: 0,
|
|
Slot: 0,
|
|
},
|
|
Signature: []byte("B"),
|
|
},
|
|
},
|
|
}
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Slot: currentSlot,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
ProposerSlashings: slashings,
|
|
},
|
|
}
|
|
want := fmt.Sprintf(
|
|
"validator with key %#x is not slashable",
|
|
beaconState.Validators()[0].PublicKey,
|
|
)
|
|
|
|
_, err = blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessProposerSlashings_AppliesCorrectStatus(t *testing.T) {
|
|
// We test the case when data is correct and verify the validator
|
|
// registry has been updated.
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
proposerIdx := uint64(1)
|
|
|
|
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconProposer, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
header1 := ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: proposerIdx,
|
|
Slot: 0,
|
|
StateRoot: []byte("A"),
|
|
},
|
|
}
|
|
signingRoot, err := helpers.ComputeSigningRoot(header1.Header, domain)
|
|
if err != nil {
|
|
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
|
}
|
|
header1.Signature = privKeys[proposerIdx].Sign(signingRoot[:]).Marshal()[:]
|
|
|
|
header2 := ðpb.SignedBeaconBlockHeader{
|
|
Header: ðpb.BeaconBlockHeader{
|
|
ProposerIndex: proposerIdx,
|
|
Slot: 0,
|
|
StateRoot: []byte("B"),
|
|
},
|
|
}
|
|
signingRoot, err = helpers.ComputeSigningRoot(header2.Header, domain)
|
|
if err != nil {
|
|
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
|
}
|
|
header2.Signature = privKeys[proposerIdx].Sign(signingRoot[:]).Marshal()[:]
|
|
|
|
slashings := []*ethpb.ProposerSlashing{
|
|
{
|
|
Header_1: header1,
|
|
Header_2: header2,
|
|
},
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
ProposerSlashings: slashings,
|
|
},
|
|
}
|
|
|
|
newState, err := blocks.ProcessProposerSlashings(context.Background(), beaconState, block.Body)
|
|
if err != nil {
|
|
t.Fatalf("Unexpected error: %s", err)
|
|
}
|
|
|
|
newStateVals := newState.Validators()
|
|
if newStateVals[1].ExitEpoch != beaconState.Validators()[1].ExitEpoch {
|
|
t.Errorf("Proposer with index 1 did not correctly exit,"+"wanted slot:%d, got:%d",
|
|
newStateVals[1].ExitEpoch, beaconState.Validators()[1].ExitEpoch)
|
|
}
|
|
}
|
|
|
|
func TestSlashableAttestationData_CanSlash(t *testing.T) {
|
|
att1 := ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{Epoch: 1},
|
|
Source: ðpb.Checkpoint{Root: []byte{'A'}},
|
|
}
|
|
att2 := ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{Epoch: 1},
|
|
Source: ðpb.Checkpoint{Root: []byte{'B'}},
|
|
}
|
|
if !blocks.IsSlashableAttestationData(att1, att2) {
|
|
t.Error("atts should have been slashable")
|
|
}
|
|
att1.Target.Epoch = 4
|
|
att1.Source.Epoch = 2
|
|
att2.Source.Epoch = 3
|
|
if !blocks.IsSlashableAttestationData(att1, att2) {
|
|
t.Error("atts should have been slashable")
|
|
}
|
|
}
|
|
|
|
func TestProcessAttesterSlashings_DataNotSlashable(t *testing.T) {
|
|
slashings := []*ethpb.AttesterSlashing{
|
|
{
|
|
Attestation_1: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
},
|
|
Attestation_2: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 1},
|
|
Target: ðpb.Checkpoint{Epoch: 1},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{}
|
|
currentSlot := uint64(0)
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Slot: currentSlot,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
AttesterSlashings: slashings,
|
|
},
|
|
}
|
|
want := fmt.Sprint("attestations are not slashable")
|
|
|
|
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttesterSlashings_IndexedAttestationFailedToVerify(t *testing.T) {
|
|
registry := []*ethpb.Validator{}
|
|
currentSlot := uint64(0)
|
|
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Slot: currentSlot,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
slashings := []*ethpb.AttesterSlashing{
|
|
{
|
|
Attestation_1: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 1},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
|
|
},
|
|
Attestation_2: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+1),
|
|
},
|
|
},
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
AttesterSlashings: slashings,
|
|
},
|
|
}
|
|
|
|
want := fmt.Sprint("validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE")
|
|
_, err = blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttesterSlashings_AppliesCorrectStatus(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
for _, vv := range beaconState.Validators() {
|
|
vv.WithdrawableEpoch = 1 * params.BeaconConfig().SlotsPerEpoch
|
|
}
|
|
|
|
att1 := ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 1},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
AttestingIndices: []uint64{0, 1},
|
|
}
|
|
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
signingRoot, err := helpers.ComputeSigningRoot(att1.Data, domain)
|
|
if err != nil {
|
|
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
|
}
|
|
sig0 := privKeys[0].Sign(signingRoot[:])
|
|
sig1 := privKeys[1].Sign(signingRoot[:])
|
|
aggregateSig := bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
|
|
att1.Signature = aggregateSig.Marshal()[:]
|
|
|
|
att2 := ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
AttestingIndices: []uint64{0, 1},
|
|
}
|
|
signingRoot, err = helpers.ComputeSigningRoot(att2.Data, domain)
|
|
if err != nil {
|
|
t.Errorf("Could not get signing root of beacon block header: %v", err)
|
|
}
|
|
sig0 = privKeys[0].Sign(signingRoot[:])
|
|
sig1 = privKeys[1].Sign(signingRoot[:])
|
|
aggregateSig = bls.AggregateSignatures([]*bls.Signature{sig0, sig1})
|
|
att2.Signature = aggregateSig.Marshal()[:]
|
|
|
|
slashings := []*ethpb.AttesterSlashing{
|
|
{
|
|
Attestation_1: att1,
|
|
Attestation_2: att2,
|
|
},
|
|
}
|
|
|
|
currentSlot := 2 * params.BeaconConfig().SlotsPerEpoch
|
|
if err := beaconState.SetSlot(currentSlot); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
AttesterSlashings: slashings,
|
|
},
|
|
}
|
|
|
|
newState, err := blocks.ProcessAttesterSlashings(context.Background(), beaconState, block.Body)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
newRegistry := newState.Validators()
|
|
|
|
// Given the intersection of slashable indices is [1], only validator
|
|
// at index 1 should be slashed and exited. We confirm this below.
|
|
if newRegistry[1].ExitEpoch != beaconState.Validators()[1].ExitEpoch {
|
|
t.Errorf(
|
|
`
|
|
Expected validator at index 1's exit epoch to match
|
|
%d, received %d instead
|
|
`,
|
|
beaconState.Validators()[1].ExitEpoch,
|
|
newRegistry[1].ExitEpoch,
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestations_InclusionDelayFailure(t *testing.T) {
|
|
attestations := []*ethpb.Attestation{
|
|
{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
Slot: 5,
|
|
},
|
|
},
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: attestations,
|
|
},
|
|
}
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
want := fmt.Sprintf(
|
|
"attestation slot %d + inclusion delay %d > state slot %d",
|
|
attestations[0].Data.Slot,
|
|
params.BeaconConfig().MinAttestationInclusionDelay,
|
|
beaconState.Slot(),
|
|
)
|
|
_, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestations_NeitherCurrentNorPrevEpoch(t *testing.T) {
|
|
att := ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
|
Target: ðpb.Checkpoint{Epoch: 0}}}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: []*ethpb.Attestation{att},
|
|
},
|
|
}
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
|
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().SlotsPerEpoch*4 + params.BeaconConfig().MinAttestationInclusionDelay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pfc := beaconState.PreviousJustifiedCheckpoint()
|
|
pfc.Root = []byte("hello-world")
|
|
if err := beaconState.SetPreviousJustifiedCheckpoint(pfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
want := fmt.Sprintf(
|
|
"expected target epoch (%d) to be the previous epoch (%d) or the current epoch (%d)",
|
|
att.Data.Target.Epoch,
|
|
helpers.PrevEpoch(beaconState),
|
|
helpers.CurrentEpoch(beaconState),
|
|
)
|
|
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestations_CurrentEpochFFGDataMismatches(t *testing.T) {
|
|
aggBits := bitfield.NewBitlist(3)
|
|
attestations := []*ethpb.Attestation{
|
|
{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
Source: ðpb.Checkpoint{Epoch: 1},
|
|
},
|
|
AggregationBits: aggBits,
|
|
},
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: attestations,
|
|
},
|
|
}
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
|
if err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
cfc := beaconState.CurrentJustifiedCheckpoint()
|
|
cfc.Root = []byte("hello-world")
|
|
if err := beaconState.SetCurrentJustifiedCheckpoint(cfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
want := fmt.Sprintf(
|
|
"expected source epoch %d, received %d",
|
|
helpers.CurrentEpoch(beaconState),
|
|
attestations[0].Data.Source.Epoch,
|
|
)
|
|
_, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
|
|
block.Body.Attestations[0].Data.Source.Epoch = helpers.CurrentEpoch(beaconState)
|
|
block.Body.Attestations[0].Data.Source.Root = []byte{}
|
|
|
|
want = fmt.Sprintf(
|
|
"expected source root %#x, received %#x",
|
|
beaconState.CurrentJustifiedCheckpoint().Root,
|
|
attestations[0].Data.Source.Root,
|
|
)
|
|
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestations_PrevEpochFFGDataMismatches(t *testing.T) {
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
aggBits := bitfield.NewBitlist(3)
|
|
aggBits.SetBitAt(0, true)
|
|
attestations := []*ethpb.Attestation{
|
|
{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 1},
|
|
Target: ðpb.Checkpoint{Epoch: 1},
|
|
Slot: params.BeaconConfig().SlotsPerEpoch,
|
|
},
|
|
AggregationBits: aggBits,
|
|
},
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: attestations,
|
|
},
|
|
}
|
|
|
|
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().SlotsPerEpoch + params.BeaconConfig().MinAttestationInclusionDelay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
pfc := beaconState.PreviousJustifiedCheckpoint()
|
|
pfc.Root = []byte("hello-world")
|
|
if err := beaconState.SetPreviousJustifiedCheckpoint(pfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetPreviousEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
want := fmt.Sprintf(
|
|
"expected source epoch %d, received %d",
|
|
helpers.PrevEpoch(beaconState),
|
|
attestations[0].Data.Source.Epoch,
|
|
)
|
|
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
|
|
block.Body.Attestations[0].Data.Source.Epoch = helpers.PrevEpoch(beaconState)
|
|
block.Body.Attestations[0].Data.Target.Epoch = helpers.CurrentEpoch(beaconState)
|
|
block.Body.Attestations[0].Data.Source.Root = []byte{}
|
|
|
|
want = fmt.Sprintf(
|
|
"expected source root %#x, received %#x",
|
|
beaconState.CurrentJustifiedCheckpoint().Root,
|
|
attestations[0].Data.Source.Root,
|
|
)
|
|
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestations_InvalidAggregationBitsLength(t *testing.T) {
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
aggBits := bitfield.NewBitlist(4)
|
|
att := ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
|
Target: ðpb.Checkpoint{Epoch: 0}},
|
|
AggregationBits: aggBits,
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: []*ethpb.Attestation{att},
|
|
},
|
|
}
|
|
|
|
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
cfc := beaconState.CurrentJustifiedCheckpoint()
|
|
cfc.Root = []byte("hello-world")
|
|
if err := beaconState.SetCurrentJustifiedCheckpoint(cfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
expected := "failed to verify aggregation bitfield: wanted participants bitfield length 3, got: 4"
|
|
_, err = blocks.ProcessAttestations(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), expected) {
|
|
t.Errorf("Did not receive wanted error")
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestations_OK(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
aggBits := bitfield.NewBitlist(3)
|
|
aggBits.SetBitAt(0, true)
|
|
var mockRoot [32]byte
|
|
copy(mockRoot[:], "hello-world")
|
|
att := ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
|
|
Target: ðpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
|
|
},
|
|
AggregationBits: aggBits,
|
|
}
|
|
|
|
cfc := beaconState.CurrentJustifiedCheckpoint()
|
|
cfc.Root = mockRoot[:]
|
|
if err := beaconState.SetCurrentJustifiedCheckpoint(cfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
committee, err := helpers.BeaconCommitteeFromState(beaconState, att.Data.Slot, att.Data.CommitteeIndex)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
attestingIndices := attestationutil.AttestingIndices(att.AggregationBits, committee)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
hashTreeRoot, err := helpers.ComputeSigningRoot(att.Data, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
sigs := make([]*bls.Signature, len(attestingIndices))
|
|
for i, indice := range attestingIndices {
|
|
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
|
sigs[i] = sig
|
|
}
|
|
att.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: []*ethpb.Attestation{att},
|
|
},
|
|
}
|
|
|
|
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body); err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAggregatedAttestation_OverlappingBits(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
data := ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
|
Target: ðpb.Checkpoint{Epoch: 0, Root: []byte("hello-world")},
|
|
}
|
|
aggBits1 := bitfield.NewBitlist(4)
|
|
aggBits1.SetBitAt(0, true)
|
|
aggBits1.SetBitAt(1, true)
|
|
aggBits1.SetBitAt(2, true)
|
|
att1 := ðpb.Attestation{
|
|
Data: data,
|
|
AggregationBits: aggBits1,
|
|
}
|
|
|
|
cfc := beaconState.CurrentJustifiedCheckpoint()
|
|
cfc.Root = []byte("hello-world")
|
|
if err := beaconState.SetCurrentJustifiedCheckpoint(cfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
attestingIndices1 := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
hashTreeRoot, err := helpers.ComputeSigningRoot(att1.Data, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
sigs := make([]*bls.Signature, len(attestingIndices1))
|
|
for i, indice := range attestingIndices1 {
|
|
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
|
sigs[i] = sig
|
|
}
|
|
att1.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
|
|
|
aggBits2 := bitfield.NewBitlist(4)
|
|
aggBits2.SetBitAt(1, true)
|
|
aggBits2.SetBitAt(2, true)
|
|
aggBits2.SetBitAt(3, true)
|
|
att2 := ðpb.Attestation{
|
|
Data: data,
|
|
AggregationBits: aggBits2,
|
|
}
|
|
|
|
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
attestingIndices2 := attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
hashTreeRoot, err = helpers.ComputeSigningRoot(data, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
sigs = make([]*bls.Signature, len(attestingIndices2))
|
|
for i, indice := range attestingIndices2 {
|
|
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
|
sigs[i] = sig
|
|
}
|
|
att2.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
|
|
|
if _, err = helpers.AggregateAttestation(att1, att2); err != helpers.ErrAttestationAggregationBitsOverlap {
|
|
t.Error("Did not receive wanted error")
|
|
}
|
|
}
|
|
|
|
func TestProcessAggregatedAttestation_NoOverlappingBits(t *testing.T) {
|
|
beaconState, privKeys := testutil.DeterministicGenesisState(t, 300)
|
|
|
|
domain, err := helpers.Domain(beaconState.Fork(), 0, params.BeaconConfig().DomainBeaconAttester, beaconState.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var mockRoot [32]byte
|
|
copy(mockRoot[:], "hello-world")
|
|
data := ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
|
|
Target: ðpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
|
|
}
|
|
aggBits1 := bitfield.NewBitlist(9)
|
|
aggBits1.SetBitAt(0, true)
|
|
aggBits1.SetBitAt(1, true)
|
|
att1 := ðpb.Attestation{
|
|
Data: data,
|
|
AggregationBits: aggBits1,
|
|
}
|
|
|
|
cfc := beaconState.CurrentJustifiedCheckpoint()
|
|
cfc.Root = mockRoot[:]
|
|
if err := beaconState.SetCurrentJustifiedCheckpoint(cfc); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
committee, err := helpers.BeaconCommitteeFromState(beaconState, att1.Data.Slot, att1.Data.CommitteeIndex)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
attestingIndices1 := attestationutil.AttestingIndices(att1.AggregationBits, committee)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
hashTreeRoot, err := helpers.ComputeSigningRoot(data, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
sigs := make([]*bls.Signature, len(attestingIndices1))
|
|
for i, indice := range attestingIndices1 {
|
|
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
|
sigs[i] = sig
|
|
}
|
|
att1.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
|
|
|
aggBits2 := bitfield.NewBitlist(9)
|
|
aggBits2.SetBitAt(2, true)
|
|
aggBits2.SetBitAt(3, true)
|
|
att2 := ðpb.Attestation{
|
|
Data: data,
|
|
AggregationBits: aggBits2,
|
|
}
|
|
|
|
committee, err = helpers.BeaconCommitteeFromState(beaconState, att2.Data.Slot, att2.Data.CommitteeIndex)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
attestingIndices2 := attestationutil.AttestingIndices(att2.AggregationBits, committee)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
hashTreeRoot, err = helpers.ComputeSigningRoot(data, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
sigs = make([]*bls.Signature, len(attestingIndices2))
|
|
for i, indice := range attestingIndices2 {
|
|
sig := privKeys[indice].Sign(hashTreeRoot[:])
|
|
sigs[i] = sig
|
|
}
|
|
att2.Signature = bls.AggregateSignatures(sigs).Marshal()[:]
|
|
|
|
aggregatedAtt, err := helpers.AggregateAttestation(att1, att2)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Attestations: []*ethpb.Attestation{aggregatedAtt},
|
|
},
|
|
}
|
|
|
|
err = beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := blocks.ProcessAttestations(context.Background(), beaconState, block.Body); err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestationsNoVerify_IncorrectSlotTargetEpoch(t *testing.T) {
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 1)
|
|
|
|
att := ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Slot: params.BeaconConfig().SlotsPerEpoch,
|
|
Target: ðpb.Checkpoint{},
|
|
},
|
|
}
|
|
wanted := fmt.Sprintf("data slot is not in the same epoch as target %d != %d", helpers.SlotToEpoch(att.Data.Slot), att.Data.Target.Epoch)
|
|
_, err := blocks.ProcessAttestationNoVerify(context.TODO(), beaconState, att)
|
|
if err == nil || err.Error() != wanted {
|
|
t.Error("Did not get wanted error")
|
|
}
|
|
}
|
|
|
|
func TestProcessAttestationsNoVerify_OK(t *testing.T) {
|
|
// Attestation with an empty signature
|
|
|
|
beaconState, _ := testutil.DeterministicGenesisState(t, 100)
|
|
|
|
aggBits := bitfield.NewBitlist(3)
|
|
aggBits.SetBitAt(1, true)
|
|
var mockRoot [32]byte
|
|
copy(mockRoot[:], "hello-world")
|
|
att := ðpb.Attestation{
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0, Root: mockRoot[:]},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
AggregationBits: aggBits,
|
|
}
|
|
|
|
zeroSig := [96]byte{}
|
|
att.Signature = zeroSig[:]
|
|
|
|
err := beaconState.SetSlot(beaconState.Slot() + params.BeaconConfig().MinAttestationInclusionDelay)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
ckp := beaconState.CurrentJustifiedCheckpoint()
|
|
copy(ckp.Root, "hello-world")
|
|
if err := beaconState.SetCurrentJustifiedCheckpoint(ckp); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if err := beaconState.SetCurrentEpochAttestations([]*pb.PendingAttestation{}); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if _, err := blocks.ProcessAttestationNoVerify(context.TODO(), beaconState, att); err != nil {
|
|
t.Errorf("Unexpected error: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestConvertToIndexed_OK(t *testing.T) {
|
|
helpers.ClearCache()
|
|
validators := make([]*ethpb.Validator, 2*params.BeaconConfig().SlotsPerEpoch)
|
|
for i := 0; i < len(validators); i++ {
|
|
validators[i] = ðpb.Validator{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
}
|
|
}
|
|
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Slot: 5,
|
|
Validators: validators,
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tests := []struct {
|
|
aggregationBitfield bitfield.Bitlist
|
|
wantedAttestingIndices []uint64
|
|
}{
|
|
{
|
|
aggregationBitfield: bitfield.Bitlist{0x07},
|
|
wantedAttestingIndices: []uint64{43, 47},
|
|
},
|
|
{
|
|
aggregationBitfield: bitfield.Bitlist{0x03},
|
|
wantedAttestingIndices: []uint64{47},
|
|
},
|
|
{
|
|
aggregationBitfield: bitfield.Bitlist{0x01},
|
|
wantedAttestingIndices: []uint64{},
|
|
},
|
|
}
|
|
|
|
var sig [96]byte
|
|
copy(sig[:], "signed")
|
|
attestation := ðpb.Attestation{
|
|
Signature: sig[:],
|
|
Data: ðpb.AttestationData{
|
|
Source: ðpb.Checkpoint{Epoch: 0},
|
|
Target: ðpb.Checkpoint{Epoch: 0},
|
|
},
|
|
}
|
|
for _, tt := range tests {
|
|
attestation.AggregationBits = tt.aggregationBitfield
|
|
wanted := ðpb.IndexedAttestation{
|
|
AttestingIndices: tt.wantedAttestingIndices,
|
|
Data: attestation.Data,
|
|
Signature: attestation.Signature,
|
|
}
|
|
|
|
committee, err := helpers.BeaconCommitteeFromState(state, attestation.Data.Slot, attestation.Data.CommitteeIndex)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
ia := attestationutil.ConvertToIndexed(context.Background(), attestation, committee)
|
|
if !reflect.DeepEqual(wanted, ia) {
|
|
diff, _ := messagediff.PrettyDiff(ia, wanted)
|
|
t.Log(diff)
|
|
t.Error("convert attestation to indexed attestation didn't result as wanted")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestVerifyIndexedAttestation_OK(t *testing.T) {
|
|
numOfValidators := 4 * params.BeaconConfig().SlotsPerEpoch
|
|
validators := make([]*ethpb.Validator, numOfValidators)
|
|
_, keys, err := testutil.DeterministicDepositsAndKeys(numOfValidators)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for i := 0; i < len(validators); i++ {
|
|
validators[i] = ðpb.Validator{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
PublicKey: keys[i].PublicKey().Marshal(),
|
|
}
|
|
}
|
|
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Slot: 5,
|
|
Validators: validators,
|
|
Fork: &pb.Fork{
|
|
Epoch: 0,
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
},
|
|
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
tests := []struct {
|
|
attestation *ethpb.IndexedAttestation
|
|
}{
|
|
{attestation: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: 2,
|
|
},
|
|
},
|
|
AttestingIndices: []uint64{1},
|
|
}},
|
|
{attestation: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: 1,
|
|
},
|
|
},
|
|
AttestingIndices: []uint64{47, 99, 101},
|
|
}},
|
|
{attestation: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: 4,
|
|
},
|
|
},
|
|
AttestingIndices: []uint64{21, 72},
|
|
}},
|
|
{attestation: ðpb.IndexedAttestation{
|
|
Data: ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: 7,
|
|
},
|
|
},
|
|
AttestingIndices: []uint64{100, 121, 122},
|
|
}},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
domain, err := helpers.Domain(state.Fork(), tt.attestation.Data.Target.Epoch, params.BeaconConfig().DomainBeaconAttester, state.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
root, err := helpers.ComputeSigningRoot(tt.attestation.Data, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
var sig []*bls.Signature
|
|
for _, idx := range tt.attestation.AttestingIndices {
|
|
validatorSig := keys[idx].Sign(root[:])
|
|
sig = append(sig, validatorSig)
|
|
}
|
|
aggSig := bls.AggregateSignatures(sig)
|
|
marshalledSig := aggSig.Marshal()
|
|
|
|
tt.attestation.Signature = marshalledSig
|
|
|
|
err = blocks.VerifyIndexedAttestation(context.Background(), state, tt.attestation)
|
|
if err != nil {
|
|
t.Errorf("failed to verify indexed attestation: %v", err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestValidateIndexedAttestation_AboveMaxLength(t *testing.T) {
|
|
indexedAtt1 := ðpb.IndexedAttestation{
|
|
AttestingIndices: make([]uint64, params.BeaconConfig().MaxValidatorsPerCommittee+5),
|
|
}
|
|
|
|
for i := uint64(0); i < params.BeaconConfig().MaxValidatorsPerCommittee+5; i++ {
|
|
indexedAtt1.AttestingIndices[i] = i
|
|
indexedAtt1.Data = ðpb.AttestationData{
|
|
Target: ðpb.Checkpoint{
|
|
Epoch: i,
|
|
},
|
|
}
|
|
}
|
|
|
|
want := "validator indices count exceeds MAX_VALIDATORS_PER_COMMITTEE"
|
|
err := blocks.VerifyIndexedAttestation(context.Background(), &stateTrie.BeaconState{}, indexedAtt1)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected verification to fail return false, received: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestProcessDeposits_SameValidatorMultipleDepositsSameBlock(t *testing.T) {
|
|
// Same validator created 3 valid deposits within the same block
|
|
testutil.ResetCache()
|
|
dep, _, err := testutil.DeterministicDepositsAndKeysSameValidator(3)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
// 3 deposits from the same validator
|
|
Deposits: []*ethpb.Deposit{dep[0], dep[1], dep[2]},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
PublicKey: []byte{1},
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
},
|
|
}
|
|
balances := []uint64{0}
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Balances: balances,
|
|
Eth1Data: eth1Data,
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body)
|
|
if err != nil {
|
|
t.Fatalf("Expected block deposits to process correctly, received: %v", err)
|
|
}
|
|
|
|
if len(newState.Validators()) != 2 {
|
|
t.Errorf("Incorrect validator count. Wanted %d, got %d", 2, len(newState.Validators()))
|
|
}
|
|
}
|
|
|
|
func TestProcessDeposits_MerkleBranchFailsVerification(t *testing.T) {
|
|
deposit := ðpb.Deposit{
|
|
Data: ðpb.Deposit_Data{
|
|
PublicKey: []byte{1, 2, 3},
|
|
Signature: make([]byte, 96),
|
|
},
|
|
}
|
|
leaf, err := ssz.HashTreeRoot(deposit.Data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// We then create a merkle branch for the test.
|
|
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, int(params.BeaconConfig().DepositContractTreeDepth))
|
|
if err != nil {
|
|
t.Fatalf("Could not generate trie: %v", err)
|
|
}
|
|
proof, err := depositTrie.MerkleProof(0)
|
|
if err != nil {
|
|
t.Fatalf("Could not generate proof: %v", err)
|
|
}
|
|
|
|
deposit.Proof = proof
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Deposits: []*ethpb.Deposit{deposit},
|
|
},
|
|
}
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Eth1Data: ðpb.Eth1Data{
|
|
DepositRoot: []byte{0},
|
|
BlockHash: []byte{1},
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
want := "deposit root did not verify"
|
|
_, err = blocks.ProcessDeposits(context.Background(), beaconState, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected error: %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessDeposits_AddsNewValidatorDeposit(t *testing.T) {
|
|
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Deposits: []*ethpb.Deposit{dep[0]},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
PublicKey: []byte{1},
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
},
|
|
}
|
|
balances := []uint64{0}
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Balances: balances,
|
|
Eth1Data: eth1Data,
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body)
|
|
if err != nil {
|
|
t.Fatalf("Expected block deposits to process correctly, received: %v", err)
|
|
}
|
|
if newState.Balances()[1] != dep[0].Data.Amount {
|
|
t.Errorf(
|
|
"Expected state validator balances index 0 to equal %d, received %d",
|
|
dep[0].Data.Amount,
|
|
newState.Balances()[1],
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestProcessDeposits_RepeatedDeposit_IncreasesValidatorBalance(t *testing.T) {
|
|
sk := bls.RandKey()
|
|
deposit := ðpb.Deposit{
|
|
Data: ðpb.Deposit_Data{
|
|
PublicKey: sk.PublicKey().Marshal(),
|
|
Amount: 1000,
|
|
},
|
|
}
|
|
sr, err := helpers.ComputeSigningRoot(deposit.Data, bytesutil.ToBytes(3, 8))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
sig := sk.Sign(sr[:])
|
|
deposit.Data.Signature = sig.Marshal()
|
|
leaf, err := ssz.HashTreeRoot(deposit.Data)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
// We then create a merkle branch for the test.
|
|
depositTrie, err := trieutil.GenerateTrieFromItems([][]byte{leaf[:]}, int(params.BeaconConfig().DepositContractTreeDepth))
|
|
if err != nil {
|
|
t.Fatalf("Could not generate trie: %v", err)
|
|
}
|
|
proof, err := depositTrie.MerkleProof(0)
|
|
if err != nil {
|
|
t.Fatalf("Could not generate proof: %v", err)
|
|
}
|
|
|
|
deposit.Proof = proof
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
Deposits: []*ethpb.Deposit{deposit},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
PublicKey: []byte{1, 2, 3},
|
|
},
|
|
{
|
|
PublicKey: sk.PublicKey().Marshal(),
|
|
WithdrawalCredentials: []byte{1},
|
|
},
|
|
}
|
|
balances := []uint64{0, 50}
|
|
root := depositTrie.Root()
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Balances: balances,
|
|
Eth1Data: ðpb.Eth1Data{
|
|
DepositRoot: root[:],
|
|
BlockHash: root[:],
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
newState, err := blocks.ProcessDeposits(context.Background(), beaconState, block.Body)
|
|
if err != nil {
|
|
t.Fatalf("Process deposit failed: %v", err)
|
|
}
|
|
if newState.Balances()[1] != 1000+50 {
|
|
t.Errorf("Expected balance at index 1 to be 1050, received %d", newState.Balances()[1])
|
|
}
|
|
}
|
|
|
|
func TestProcessDeposit_AddsNewValidatorDeposit(t *testing.T) {
|
|
//Similar to TestProcessDeposits_AddsNewValidatorDeposit except that this test directly calls ProcessDeposit
|
|
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
eth1Data, err := testutil.DeterministicEth1Data(len(dep))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
PublicKey: []byte{1},
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
},
|
|
}
|
|
balances := []uint64{0}
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Balances: balances,
|
|
Eth1Data: eth1Data,
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
newState, err := blocks.ProcessDeposit(
|
|
beaconState,
|
|
dep[0],
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Process deposit failed: %v", err)
|
|
}
|
|
if len(newState.Validators()) != 2 {
|
|
t.Errorf("Expected validator list to have length 2, received: %v", len(newState.Validators()))
|
|
}
|
|
if len(newState.Balances()) != 2 {
|
|
t.Fatalf("Expected validator balances list to have length 2, received: %v", len(newState.Balances()))
|
|
}
|
|
if newState.Balances()[1] != dep[0].Data.Amount {
|
|
t.Errorf(
|
|
"Expected state validator balances index 1 to equal %d, received %d",
|
|
dep[0].Data.Amount,
|
|
newState.Balances()[1],
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestProcessDeposit_SkipsInvalidDeposit(t *testing.T) {
|
|
// Same test settings as in TestProcessDeposit_AddsNewValidatorDeposit, except that we use an invalid signature
|
|
dep, _, err := testutil.DeterministicDepositsAndKeys(1)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
dep[0].Data.Signature = make([]byte, 96)
|
|
trie, _, err := testutil.DepositTrieFromDeposits(dep)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
root := trie.Root()
|
|
eth1Data := ðpb.Eth1Data{
|
|
DepositRoot: root[:],
|
|
DepositCount: 1,
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
PublicKey: []byte{1},
|
|
WithdrawalCredentials: []byte{1, 2, 3},
|
|
},
|
|
}
|
|
balances := []uint64{0}
|
|
beaconState, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Balances: balances,
|
|
Eth1Data: eth1Data,
|
|
Fork: &pb.Fork{
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
newState, err := blocks.ProcessDeposit(
|
|
beaconState,
|
|
dep[0],
|
|
)
|
|
if err != nil {
|
|
t.Fatalf("Expected invalid block deposit to be ignored without error, received: %v", err)
|
|
}
|
|
|
|
if newState.Eth1DepositIndex() != 1 {
|
|
t.Errorf(
|
|
"Expected Eth1DepositIndex to be increased by 1 after processing an invalid deposit, received change: %v",
|
|
newState.Eth1DepositIndex(),
|
|
)
|
|
}
|
|
if len(newState.Validators()) != 1 {
|
|
t.Errorf("Expected validator list to have length 1, received: %v", len(newState.Validators()))
|
|
}
|
|
if len(newState.Balances()) != 1 {
|
|
t.Errorf("Expected validator balances list to have length 1, received: %v", len(newState.Balances()))
|
|
}
|
|
if newState.Balances()[0] != 0 {
|
|
t.Errorf("Expected validator balance at index 0 to stay 0, received: %v", newState.Balances()[0])
|
|
}
|
|
}
|
|
|
|
func TestProcessVoluntaryExits_ValidatorNotActive(t *testing.T) {
|
|
exits := []*ethpb.SignedVoluntaryExit{
|
|
{
|
|
Exit: ðpb.VoluntaryExit{
|
|
ValidatorIndex: 0,
|
|
},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
ExitEpoch: 0,
|
|
},
|
|
}
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
VoluntaryExits: exits,
|
|
},
|
|
}
|
|
|
|
want := "non-active validator cannot exit"
|
|
|
|
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessVoluntaryExits_InvalidExitEpoch(t *testing.T) {
|
|
exits := []*ethpb.SignedVoluntaryExit{
|
|
{
|
|
Exit: ðpb.VoluntaryExit{
|
|
Epoch: 10,
|
|
},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
},
|
|
}
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Slot: 0,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
VoluntaryExits: exits,
|
|
},
|
|
}
|
|
|
|
want := "expected current epoch >= exit epoch"
|
|
|
|
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessVoluntaryExits_NotActiveLongEnoughToExit(t *testing.T) {
|
|
exits := []*ethpb.SignedVoluntaryExit{
|
|
{
|
|
Exit: ðpb.VoluntaryExit{
|
|
ValidatorIndex: 0,
|
|
Epoch: 0,
|
|
},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
},
|
|
}
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Slot: 10,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
VoluntaryExits: exits,
|
|
},
|
|
}
|
|
|
|
want := "validator has not been active long enough to exit"
|
|
_, err = blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
|
|
if err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("Expected %s, received %v", want, err)
|
|
}
|
|
}
|
|
|
|
func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
|
exits := []*ethpb.SignedVoluntaryExit{
|
|
{
|
|
Exit: ðpb.VoluntaryExit{
|
|
ValidatorIndex: 0,
|
|
Epoch: 0,
|
|
},
|
|
},
|
|
}
|
|
registry := []*ethpb.Validator{
|
|
{
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
ActivationEpoch: 0,
|
|
},
|
|
}
|
|
state, err := stateTrie.InitializeFromProto(&pb.BeaconState{
|
|
Validators: registry,
|
|
Fork: &pb.Fork{
|
|
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
|
|
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
|
},
|
|
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
err = state.SetSlot(state.Slot() + (params.BeaconConfig().PersistentCommitteePeriod * params.BeaconConfig().SlotsPerEpoch))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
priv := bls.RandKey()
|
|
val, err := state.ValidatorAtIndex(0)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
val.PublicKey = priv.PublicKey().Marshal()[:]
|
|
if err := state.UpdateValidatorAtIndex(0, val); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
domain, err := helpers.Domain(state.Fork(), helpers.CurrentEpoch(state), params.BeaconConfig().DomainVoluntaryExit, state.GenesisValidatorRoot())
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
signingRoot, err := helpers.ComputeSigningRoot(exits[0].Exit, domain)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
sig := priv.Sign(signingRoot[:])
|
|
exits[0].Signature = sig.Marshal()
|
|
block := ðpb.BeaconBlock{
|
|
Body: ðpb.BeaconBlockBody{
|
|
VoluntaryExits: exits,
|
|
},
|
|
}
|
|
|
|
newState, err := blocks.ProcessVoluntaryExits(context.Background(), state, block.Body)
|
|
if err != nil {
|
|
t.Fatalf("Could not process exits: %v", err)
|
|
}
|
|
newRegistry := newState.Validators()
|
|
if newRegistry[0].ExitEpoch != helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch) {
|
|
t.Errorf("Expected validator exit epoch to be %d, got %d",
|
|
helpers.ActivationExitEpoch(state.Slot()/params.BeaconConfig().SlotsPerEpoch), newRegistry[0].ExitEpoch)
|
|
}
|
|
}
|